-
Notifications
You must be signed in to change notification settings - Fork 517
创建新图层
图层(Layer)是maptalks的(核心), 你可以创建自己的图层, 来可视化数据, 实现复杂的交互, 载入自定义格式数据等.
创建图层非常简单, 你只需要两个步骤:
继承 maptalks.Layer, 添加必要的图层方法, 并选择实现下列接口方法(均为可选):
-
onAdd: map.addLayer(map)或layer.addTo(map) 添加地图时的回调函数. -
onLoad: layer.load()加载图层时的回调函数, return false时暂停图层加载, 适合需异步载入外部资源的场景: 返回false暂停图层加载, 查询远程服务或载入外部资源, 待完成后再继续加载图层(layer.load()).. -
onRemove: map.removeLayer(layer)或layer.remove()时的回调函数, 用于在删除图层时清理/释放资源. -
toJSON: 将图层实例序列化为JSON对象的方法 -
static fromJSON: 一个静态方法, 用来从JSON对象生成图层实例.
以下为一个简单示例, 图层能在地图中央用随机颜色显示指定的内容
const options = {
'color' : 'Red'
};
class HelloLayer extends maptalks.Layer {
constructor(id, content, options) {
super(id, options);
this.content = content;
}
getContent() {
return this.content;
}
setContent(content) {
this.content = content;
return this;
}
onAdd() {
console.log('A HelloLayer is added to map');
}
onLoad() {
console.log('HelloLayer is about to load');
// 返回true, 让图层继续加载
return true;
}
onRemove() {
delete this.content;
delete this.rgb;
delete this.crs;
}
// 将图层序列化为json对象
toJSON{
return {
'type' : 'HelloLayer',
'id' : this.getId(),
'options' : this.config(),
'content' : this.getContent()
};
}
// 由json对象反序列化, 生成图层实例
static fromJSON(json) {
if (!json) {
return null;
}
return new HelloLayer(json.id, json.content, json.options);
}
}
// 定义HelloLayer的默认options
HelloLayer.mergeOptions(options);
// 注册图层的 JSON Type
HelloLayer.registerJSONType('HelloLayer');图层渲染器负责图层的绘制, 交互和事件监听等. 你可以使用任何心仪的图形技术来实现图层渲染器, 如Canvas 2D, WebGL, SVG 或HTML + CSS. 一个图层可以有多个渲染器, 例如TileLayer有dom和canvas两个渲染器, 使用哪个渲染器由图层的options.renderer来决定, 默认值为canvas.
maptalks中最常见的是基于Canvas容器的渲染器(Canvas 2D 或 WebGL), 为方便用户, maptalks提供了CanvasRenderer类, 包含了一些常用Canvas容器操作方法, 你可以通过继承它来轻松创建你自己的CanvasRenderer.
[补充图层绘制流程示意图]
以下通过创建HelloLayer的CanvasRenderer, 来介绍CanvasRenderer中的抽象方法与工具方法
//HelloLayer's renderer
class HelloLayerRenderer extends maptalks.renderer.CanvasRenderer {
//constructor
constructor(layer) {
super(layer);
}
/**
* 检查是否有外部资源需要加载, 如果有, renderer会先载入资源, 再调用draw方法
* @returns {Array[]} 外部资源数组 [ [url1, width, height], [url2, width, height], [url3, width, height] .. ]
*/
checkResources() {
return [];
}
/**
* 必须实现的abstract方法
* 用来在地图没有交互时绘制图层
* @abstract
* @required
*/
draw() {
const map = this.getMap(),
size = map.getSize();
//prepare layer's canvas
this.prepareCanvas();
//convert center coordinate to containerPoint
//a containerPoint is screen position from top-left of container.
const point = map.coordinateToContainerPoint(map.getCenter());
const text = this.layer.getText();
//this.context is the CanvasRenderingContext2D of the layer canvas
this.context.fillStyle = this.layer.options['textColor'];
this.context.font = 'bold 50px sans-serif';
const len = this.context.measureText(text);
this.context.fillText(text, point.x - len.width / 2, point.y);
//ask map to render
this.completeRender();
}
/**
* 可选实现的abstract方法
* 用来在地图交互时绘制图层
* 因为地图交互需要较高的fps, 实现绘制时需要平衡用户体验和性能.
* 如果地图交互的fps很低时, 该方法有可能被忽略, 此时回调方法onSkipDrawOnInteracting会被调用
* @abstract
* @optional
* @param {Object} eventParam event parameters
*/
drawOnInteracting(eventParam) {
this.draw();
}
/**
* 可选实现的方法
* 图层是否是动画
* 如果是, 则图层一直处于重绘状态, draw/drawOnInteracting会一直被调用
* @optional
*/
isAnimating() {
return false;
}
/**
* 可选实现的方法
* 图层是否需要重绘
* 如果是, 则map会调用draw/drawOnInteracting重绘图层
* @optional
*/
needToRedraw() {
if (map.isInteracting()) {
return true;
}
return super.needToRedraw();
}
/**
* 回调函数, 图层第一次加载绘制时调用
* @optional
*/
onAdd() {
console.log('I am added');
}
/**
* 回调函数, 图层从map移除时调用, 可以用来释放资源
* @optional
*/
onRemove() {
console.log('I am removed');
}
// 各种事件回调, 可以根据需要选择实现
onZoomStart(e) { super.onZoomStart(e); }
onZoomEnd(e) { super.onZoomEnd(e); }
onResize(e) { super.onResize(e); }
onMoveStart(e) { super.onMoveStart(e); }
onMoveEnd(e) { super.onMoveEnd(e); }
onDragRotateStart(e) { super.onDragRotateStart(e); }
onDragRotateEnd(e) { super.onDragRotateEnd(e); }
onSpatialReferenceChange(e) { super.onSpatialReferenceChange(e); }
}
//将HelloLayerRenderer注册为'canvas' renderer, 图层的默认渲染器
HelloLayer.registerRenderer('canvas', HelloLayerRenderer);CanvasRenderer中常用的一些工具方法:
-
setToRedraw()设置CanvasRenderer为重绘状态, 请求map调用draw/drawOnInteracting重绘, 并重画图层的canvas
-
setCanvasUpdated()设置CanvasRenderer的Canvas为更新状态, 请求map重画图层的canvas, 但不会调用draw/drawOnInteracting重绘
-
getCanvasImage()获取图层的Canvas图像, 返回的对象格式: { image : canvas画布, layer : 图层对象, point : 左上角containerPoint, size : 画布大小 }
-
createCanvas()创建Canvas画布, 并进行必要的设置
-
prepareCanvas()绘制前, 预备Canvas: 1. 清除Canvas, 2. 如果图层有mask, 则调用clip方法设置Canvas遮罩
-
clearCanvas()清除Canvas
-
resizeCanvas(size)按照size中大小, 设置Canvas的高宽
-
completeRender()绘制结束后的调用方法, 触发必要的事件, 并调用setCanvasUpdated请求重画图层的canvas
-
其他方法可以参考CanvasRenderer的API文档
上述内容中的HelloLayer的运行示例地址
[补充运行截图]