ImageLayer
ImageLayer是用来添加和管理图片资源的,有时我们需要将一些静态图片整体的添加到地图上,这时ImageLayer就派上用场了,ImageLayer的使用方式就是不断的:
- 添加到地图
- 从地图上移除
- 不断设置其图片集合(setImages),
- 清空图片资源(clear)
加载时序图片
ImageLayer 常规的使用方式是:
js
layer.setImages({
url,
extent,
});
当我们使用url图片时因为内部要请求图片这个过程是需要时间的,所以当用户不断的的setImages时就会出现闪烁的效果
怎样解决这个问题呢?
- 在重新设置图片资源前,我们可以先把图片加载完,然后在设置ImageLayer的数据
- ImageLayer的图片资源不仅仅支持url,也支持ImageBitMap的
- ImageBitMap是纯内存的,复制速度非常快的就可以避免引擎加载图片时空出的白屏时间了
WARNING
maptalks version 1.1.2版本才支持该特性
js
const max = 6;
let idx = 1;
let imageLoading = false;
function loadImage() {
if (imageLoading) {
return;
}
imageLoading = true;
const image = new Image();
image.onload = () => {
createImageBitmap(image).then((bitImage) => {
console.log(image);
idx++;
if (idx > max) {
idx = 1;
}
imageLoading = false;
layer.setImages({
url: bitImage,
extent,
});
});
};
image.src = `./../assets/image/wendu/${idx}.png`;
}
const now = maptalks.Util.now;
let time = now();
function animation() {
const t = now();
if (t - time >= 2000) {
loadImage();
time = t;
}
requestAnimationFrame(animation);
}
requestAnimationFrame(animation);
loadImage();
加载大图片
一般业务里在前端我们是不会加载大的图片的(几十甚至百兆的),如果你一定要加载
由于浏览器底层限制(canvas/webgl等)的原因加载大尺寸的图片会报错的
这时我们需要将大图片进行切割的,社区插件maptalks.tileclip提供了图片切割功能
返回的图片集合是ImageBitMap
- ImageBitMap纯内存的,不管是数据的复制和渲染性能更好
- maptalks内部也支持ImageBitMap作为数据源的
具体操作:
- 利用 maptalks.tileclip 切割图片
- 计算切割的子图片集合的包围盒
- 将子图片的数据加入 ResourceProxy 资源管理工具
- 批量设置ImageLayer的数据集合
js
const bbox = [120, 31, 121, 32];
const layer = new maptalks.VectorLayer("layer").addTo(map);
const extent = new maptalks.Extent(bbox);
const polygon = new maptalks.Polygon(extent.toArray()).addTo(layer);
const imagelayer = new maptalks.ImageLayer("imagelayer", {}).addTo(map);
const prefix = `temp_${imagelayer.getId()}_`;
//清除每次的临时图片资源
function clearCache() {
const caches = maptalks.ResourceProxy.allResource();
const keys = Object.keys(caches).filter((key) => {
return key.includes(prefix);
});
keys.forEach((key) => {
const image = maptalks.ResourceProxy.getResource(key);
if (image && image.close) {
image.close();
}
maptalks.ResourceProxy.removeResource(key);
});
}
//图片加入资源管理工具
function addCache(key, image) {
// const { row, col } = item;
maptalks.ResourceProxy.addResource(key, image);
}
function setImages(result) {
clearCache();
const { width, height, items } = result;
const [minx, miny, maxx, maxy] = bbox;
const ax = (maxx - minx) / width;
const ay = (maxy - miny) / height;
items.forEach((item) => {
const { x, y, width, height, image } = item;
const x1 = minx + x * ax;
const x2 = x1 + width * ax;
const y2 = maxy - y * ay;
const y1 = y2 - ay * height;
//计算每个小图片的包围盒范围
item.bbox = [x1, y1, x2, y2];
});
const images = items.map((item) => {
// console.log(item.image);
const id = maptalks.Util.GUID();
const key = `${prefix}${id}`;
addCache(key, item.image);
return {
//表示从资源池里取资源
url: `$${key}`,
extent: item.bbox,
};
});
imagelayer.setImages(images);
}
let fileUrl;
function readImage() {
if (!fileUrl) {
return;
}
console.log("readimage ing");
tileActor
.imageSlicing({
url: fileUrl,
// returnBlobURL: true,
debug: true,
// filter: 'sepia(100%) invert(90%)'
})
.then((result) => {
console.log(result);
setImages(result);
URL.revokeObjectURL(fileUrl);
console.log("readimage end");
})
.catch((error) => {
console.error(error);
URL.revokeObjectURL(fileUrl);
});
}