maptalks 1.0.0-rc.35 心心念念的ts来了
很高兴在这里和大家宣布,maptalks的ts版本终于来了。 在社区同学一起的努力下,历经5个月左右的时间,终于将maptalks核心库迁移到ts
主要更新内容
- ts重构
- 优化worker消息调度机制
- ResourceProxy 全局资源代理
- 地图渲染支持锁帧(Lock FPS)
- 瓦片加载支持Mask过滤
- 绘制工具增强
- 优化map maxExtent的体验
- Geometry支持跨时间线
- 图形编辑时控制点支持配置碰撞权重
- 文本读取支持任意字段名字
- symbol.visible支持fucntion-type
- 图层mask clip支持holes
- Control和UI支持自定义css class
- 优化椭圆点集的生成效果
- 若干bug修复
TS重构
大家期盼已久的ts版本终于来了,几年前就有同学问何时出ts版本,但是因为作者一直忙于webgl功能的开发,导致这个问题一直被搁置,这里深表歉意。
maptalks的核心功能开发已经接近尾声,所以作者目前正在整理整个maptalks体系的文档和工程化相关的工作 在5个多月的时间里, 在社区多个同学的共同努力下,终于将项目迁移到ts了,在这里要特地感谢各位同学的辛勤付出
aliothor
LuckLiang
sakitam-fdd
deyihu
Liquid-Zhangliquan
fuzhenn
wodehaochide
L-hikari
相关说明:
- 目前ts标注还没有做到百分百,也做不到百分百
- 不保证标注的类型全部正确,使用过程遇到type标注错误或者使用起来体验不好的,请及时反馈,当然也欢迎随进行type 的相关pr
- 目标是满足大家平时开始的使用即可,ts化是个过程,是个运动,不断的标注来满足大家开发时的体验即可, 所以大家使用时遇到type问题的要及时反馈
- 经过几个版本的迭代基本就可以满足平时的开发体验了
- webgl版本包
maptalks-gl
的ts改造成功
优化worker消息调度机制
原来worker通信的并发数量是按个数的,现在改成按百分比了,避免因为主线程一直繁忙导致worker数据不回主线程的问题
function loop(isBusy?: boolean) {
const messageRatio =
GlobalConfig.messagePostRatioPerWorker * (isBusy ? 0.5 : 1);
getGlobalWorkerPool().commit();
getGlobalWorkerPool().broadcastIdleMessage(messageRatio);
executeMicroTasks();
loopHooks.forEach((func) => {
func();
});
}
maptalks里关于全局环境的配置:
/**
* global config
* idle/worker etc
*/
const GlobalConfig = {
//test env
isTest: false,
//idle logging
idleLog: false,
//idle 申请不到idle时,强制执行时间阈值
idleForceTimeThreshold: 48,
//worker 数量
workerCount: (getGlobalThis().MAPTALKS_WORKER_COUNT as number) || 0,
//每个Worker Message中封装的task message数量
messagePostRatioPerWorker: 0.3,
//当前运行环境的最大FPS,用户可以手动配置,否则将自动检测并赋值,为地图锁帧渲染准备
maxFPS: 0,
};
export default GlobalConfig;
你可以根据自己的需要进行修改,但是一般是不需要修改的
import { GlobalConfig } from "maptalks";
GlobalConfig.idleForceTimeThreshold = 32;
ResourceProxy 全局资源代理
ResourceProxy 顾名思义,资源代理工具,也是这个版本一个非常重要的feature,其是个全局的资源代理和管理工具,主要包括:
- 资源地址代理
- 主机地址代理
- 全局资源的缓存和管理
- Sprite加载
- svg资源加载
- iconfont图标加载
- 开放自定义资源管理
WARNING
webgl图层里还没有适配好,我们会尽快适配好的
动机
地图里会涉及大量的资源,包括图标,纹理图片,模型,GeoJSON文件等, 在前端世界里我们认为这些都是静态资源,在开发时会存在一些情况:
- 静态资源可能托管在cdn等服务器上
- maptalks有自己的设计软件(Studio,Designer等),导出的产物里会携带这些静态资源和对应的一个json文件
- 图标资源可能很多
const map = new maptalks.Map("map", {
center: [-74.00912099912109, 40.71107610933129],
zoom: 11,
pitch: 70,
lights: {
ambient: {
resource: {
url: {
front: "/resources/hdr/gradient/front.png",
back: "/resources/hdr/gradient/back.png",
left: "/resources/hdr/gradient/left.png",
right: "/resources/hdr/gradient/right.png",
top: "/resources/hdr/gradient/top.png",
bottom: "/resources/hdr/gradient/bottom.png",
},
prefilterCubeSize: 32,
},
exposure: 1,
hsv: [0, 1, -0.042],
orientation: 0,
},
directional: {
direction: [-0.1, 1, -1],
color: [1, 1, 1],
},
},
});
以上代码演示了一个带天空和的地图,里面涉及到了天空盒的图片资源
根据我的观察,maptalks的用户同学基本都是把这些资源放到前端项目里的(使用相对地址),这样从开发的角度是没有是么问题的,只是后续维护比较费力一点,每次都需要更新前端项目里的资源文件和json配置文件等
但是有的同学可能把这些资源托管在cdn服务器上的,比如我。让资源和前端代码解耦掉,好处是不用动前端项目里的东西了,资源的更新直接推送到cdn即可, 资源的变更都是json配置文件里的,但是在开发时这时问题就来了:
- 前端里想加载这些资源就必须配置资源的绝对地址了(远程地址)
const hostURL = "http://localhost/e/mtk-resources";
const map = new maptalks.Map("map", {
center: [-74.00912099912109, 40.71107610933129],
zoom: 11,
pitch: 70,
lights: {
ambient: {
resource: {
url: {
front: hostUrl + "/resources/hdr/gradient/front.png",
back: hostUrl + "/resources/hdr/gradient/back.png",
left: hostUrl + "/resources/hdr/gradient/left.png",
right: hostUrl + "/resources/hdr/gradient/right.png",
top: hostUrl + "/resources/hdr/gradient/top.png",
bottom: hostUrl + "/resources/hdr/gradient/bottom.png",
},
prefilterCubeSize: 32,
},
exposure: 1,
hsv: [0, 1, -0.042],
orientation: 0,
},
directional: {
direction: [-0.1, 1, -1],
color: [1, 1, 1],
},
},
});
maptalks是支持json序列化的,如果用绝对地址,那么就会把绝对地址序列化进去,json体积膨胀,一旦资源的服务地址发生变更这时问题就来了:
- 使用相对地址的话就加载不到资源
- 使用绝对地址如果服务地址发生变更,反序列化时会导致资源找不到,那么就不得不去修改整个配置文件里的资源路径
有没有一种方法可以来解决这个问题呢?ResourceProxy就是用来解决这个问题的
基本使用
const { ResourceProxy } = maptalks;
//import {ResourceProxy} from 'maptalks';
//设置arcgisonline目录的代理地址
ResourceProxy.proxy["/arcgisonline/"] = {
target: "https://services.arcgisonline.com/ArcGIS/",
};
const map = new maptalks.Map("map", {
center: [-74.00912099912109, 40.71107610933129],
zoom: 11,
pitch: 70,
});
const layer = new maptalks.TileLayer("base", {
repeatWorld: false,
urlTemplate:
"/arcgisonline/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
subdomains: ["a", "b", "c", "d"],
attribution:
'© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a>',
});
以上的代码里我们代理了 arcgisonline目录,凡是资源地址的我们使用相对地址即可,maptalks内部凡是涉及资源请求的都会去ResourceProxy里匹配的,会使用匹配到的代理地址进行资源请求。
这样优点就凸显出来了:
- maptalks设计软件导出的产物资源地址是相对地址,再也不需要一定把产物放到前端项目里
- 如果是硬编码涉及到资源的,也可以使用相对目录了
- 资源服务地址改变了更改下proxy即可
- 看到如上的代码如果对webpack和vite熟悉的同学应该非常亲切,我们在设计时也是有参考这两个软件,尽可能的减少大家的学习成本。
WARNING
ResourceProxy 对 /
敏感,所以配置请仔细点,意思就是多一个/
或者少一个/
都可能导致代理出问题,如果你在使用时发现资源请求不到, 请查看网络控制台,看看是不是丢了或者多了/
导致的
主机地址代理
ResourceProxy除了代理相对目录地址,也可以代理主机的地址
const { ResourceProxy } = maptalks;
//import {ResourceProxy} from 'maptalks';
//设置arcgisonline主机的代理地址
ResourceProxy.origin["https://services.arcgisonline.com/ArcGIS/"] = {
target: "http://localhost/e/arcgis/",
};
const layer = new maptalks.TileLayer("base", {
urlTemplate:
"https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
subdomains: ["a", "b", "c", "d"],
});
如果代码演示了将arcgisonline服务代理我本地arcgis服务。
这个设计主要价值为:当你的代码或者配置文件里已经包含了绝对地址,那么我们可以通过主机代理来解决主机变更导致资源加载不到的问题,不需要去修改代码和配置文件了
比如你的底图用的arcgisonline(https://services.arcgisonline.com)的服务,假设现在这个服务已经不可用了,但是在代码里这个地址是写死的,这时我们就可以通过主机地址代理,将原来的https://services.arcgisonline.com代理到 http://localhost/e/arcgis/
建议在代码和配置json文件里最好使用相对目录,不要使用绝对的地址,这个功能属于亡羊补牢
加载Sprite
有时项目里会涉及到大量的图标,大量的图标加载会对网络形成大的压力,这时Sprite就可以派上用场了
const options = {
imgUrl: "./assets/1718345235147.png",
jsonUrl: "./assets/1718345235147.json",
sourceName: "sprite/",
};
ResourceProxy.loadSprite(options).then((result) => {
console.log(result);
// addSpriteImage(result);
const icons = result;
fetch("./../assets/data/ne_50m_populated_places_simple.geojson")
.then((res) => res.json())
.then((geojson) => {
const points = maptalks.GeoJSON.toGeometry(geojson);
layer.addGeometry(points);
let idx = 0;
points.forEach((point) => {
const icon = icons[idx].name;
point.setSymbol({
markerFile: `$sprite/${icon}`,
markerWidth: 20,
markerHeight: 20,
});
idx++;
if (idx === icons.length) {
idx = 0;
}
});
});
});
- loadSprite 方法用来加载sprite资源,返回一个Promise,加载好的资源会自动注入ResourceProxy全局资源池
- sourceName 参数表示这批资源的分类,可以理解为文件夹,用来分类存放
- $ 符号用来从资源池取资源,代码里我们演示了markerFile 从资源池里取图标,$必须是第一个字符 为什么用 $呢?因为maptalks里资源可以是一个相对地址,所以必须要一个特殊的符号来表示从资源池取资源
比如这样的代码
point.setSymbol({
markerFile: `sprite/hello.png`,
markerWidth: 20,
markerHeight: 20,
});
引擎里无法区分这个 markerFile的值究竟是一个相对地址,还是表示从资源池里取资源, 所以需要一个特殊符合来告诉引擎,至于用 $ 符合,因为前端jQuery,vue,svelte等库也是用的 $ 符号, 故这里和他们统一,大家对$比较较熟悉减少大家学习成本
加载SVG资源
ResourceProxy.loadSvgs({
sourceName: "svgs/",
url: "./assets/1711521509341-svg-collection.json",
// fill: 'blue'
}).then((result) => {
console.log(result);
// addSvgs(result);
const icons = result;
fetch("./../assets/data/ne_50m_populated_places_simple.geojson")
.then((res) => res.json())
.then((geojson) => {
const points = maptalks.GeoJSON.toGeometry(geojson);
layer.addGeometry(points);
let idx = 0;
points.forEach((point) => {
const icon = icons[idx].name;
point.setSymbol({
markerType: "path",
markerPath: "$svgs/" + icon, //use $ get icon data
markerPathWidth: 15,
markerPathHeight: 15,
markerWidth: 15,
markerHeight: 15,
});
idx++;
if (idx === icons.length) {
idx = 0;
}
});
});
});
- loadSvgs方法用来加载svg资源,返回一个Promise,加载好的资源会自动注入ResourceProxy全局资源池
- sourceName 参数表示这批资源的分类,可以理解为文件夹,用来分类存放
- $ 符号用来从资源池取资源,代码里我们演示了markerPath 从资源池里取图标,$必须是第一个字符
也支持简单的为svg配个色
ResourceProxy.loadSvgs({
sourceName: "svgs/",
url: "./assets/1711521509341-svg-collection.json",
fill: "yellow",
}).then((result) => {
console.log(result);
// addSvgs(result);
const icons = result;
fetch(
"https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_50m_populated_places_simple.geojson",
)
.then((res) => res.json())
.then((geojson) => {
const points = maptalks.GeoJSON.toGeometry(geojson);
layer.addGeometry(points);
let idx = 0;
points.forEach((point) => {
const icon = icons[idx].name;
point.setSymbol({
markerType: "path",
markerPath: "$svgs/" + icon, //use $ get icon data
markerPathWidth: 15,
markerPathHeight: 15,
markerWidth: 15,
markerHeight: 15,
});
idx++;
if (idx === icons.length) {
idx = 0;
}
});
});
});
- fill参数表示为svg资源设置填充色,不填就采用svg默认色
注意maptalks里处理svg资源本质还是将其格式化成一个base64资源,所以svg资源数据量不可太大,否则带来网络压力比较大,如果你的数据量很大,应该考虑使用Sprite
加载iconfont图标库
document.addEventListener("DOMContentLoaded", () => {
ResourceProxy.loadSvgs({
symbols: document.body.childNodes[0].childNodes,
sourceName: "iconfont/",
}).then((result) => {
console.log(result);
// addIconFontSVGS(result);
const icons = result;
fetch("./../assets/data/ne_50m_populated_places_simple.geojson")
.then((res) => res.json())
.then((geojson) => {
const points = maptalks.GeoJSON.toGeometry(geojson);
layer.addGeometry(points);
let idx = 0;
points.forEach((point) => {
const icon = icons[idx].name;
point.setSymbol({
markerType: "path",
markerPath: "$iconfont/" + icon, //use $ get icon data
markerPathWidth: 1024,
markerPathHeight: 1024,
markerWidth: 20,
markerHeight: 20,
});
idx++;
if (idx === icons.length) {
idx = 0;
}
});
});
});
});
- loadSvgs方法也可以用来加载iconfont资源,返回一个Promise,加载好的资源会自动注入ResourceProxy全局资源池
- sourceName 参数表示这批资源的分类,可以理解为文件夹,用来分类存放
- symbols 即iconfont脚本执行挂载的svg集合,注意页面要引入iconfont的相关js脚本
<script
type="text/javascript"
src="//at.alicdn.com/t/font_3330503_allx40pxkxd.js"
></script>
<!-- 测试iconfont图标集合-->
自定义资源
ResourceProxy也开放用户自定义资源,提供了如下方法
- addResource(key,value)
- removeResource(key)
- updateResource(key,value)
- allResource()
- getResource(key)
下面我们来演示一些自定义的例子
- 演示注入一个简单的url
ResourceProxy.addResource(
"baidu/map",
"https://maponline0.bdimg.com/sty/map_icons2x/MapRes/changtuqichezhan.png?udt=20240227",
);
const point = new maptalks.Marker(map.getCenter(), {
symbol: {
markerFile: "$baidu/map",
},
}).addTo(layer);
- 演示注入一个Base64
const canvas = document.createElement("canvas");
canvas.width = canvas.height = 50;
const ctx = canvas.getContext("2d");
ctx.fillStyle = "red";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.fillRect(10, 10, 30, 30);
ResourceProxy.addResource("test/base64", canvas.toDataURL());
const point = new maptalks.Marker(map.getCenter(), {
symbol: {
markerFile: "$test/base64",
},
}).addTo(layer);
- 演示注入一个ImageBitmap
const canvas = document.createElement("canvas");
canvas.width = canvas.height = 50;
const ctx = canvas.getContext("2d");
ctx.fillStyle = "green";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.fillRect(10, 10, 30, 30);
createImageBitmap(canvas).then((imgbitmap) => {
ResourceProxy.addResource("test/imagebitmap", canvas.toDataURL());
const point = new maptalks.Marker(map.getCenter(), {
symbol: {
markerFile: "$test/imagebitmap",
},
}).addTo(layer);
});
- 演示注入一个blob url
fetch("./assets/plane.png")
.then((res) => res.blob())
.then((blob) => {
const url = URL.createObjectURL(blob);
ResourceProxy.addResource("test/blob", url);
const point = new maptalks.Marker(map.getCenter(), {
symbol: {
markerFile: "$test/blob",
},
}).addTo(layer);
});
blob url 注入尤其适合纯前端的资源处理,用户上传资源,用户拖拽资源,比如maptalks的designer设计工具等
注意:
- 注入的资源如果确定不使用了,请获取资源(getResource)并销毁资源值(imagebitmap/blob url),并移除这个资源(removeResource)
- 不是你随便注入的任何资源值都能被引擎内部处理的,引擎内部支持 url,blob url,base64,imagebitmap, 如果你注入其他类型的资源,引擎可能没有适配,比如注入File,引擎内部可能是不支持的
地图渲染支持锁帧(Lock FPS)
锁帧可以让地图拥有更好的性能表现。
如何使用?
创建地图时指定maxFPS参数即可, maxFPS默认是0表示不锁帧,maptalks内部会自动检测当前浏览器的最大FPS,然后根据你设置的值进行跳帧处理的
- maxFPS越小性能越好,但是不可太小,否则会导致地图的整个渲染不流畅,出现不跟手的现象,一般设置30
- maptalks内部利用worker自动检测了当前浏览器的最大FPS,不管是高刷屏还是普通的60fps都会进行合适的调度和调整处理的
- 我的60FPS的电脑上锁帧到30FPS,大概可以使渲染帧数提升10FPS
var map = new maptalks.Map("map", {
center: [120.77756364, 31.92043679],
zoom: 6,
pitch: 0,
maxFPS: 30,
});
瓦片加载支持Mask过滤
当我们加载区域性的地图时,会导致溢出边界的瓦片资源加载不到,导致浏览器控制台大量的404错误,大量的网络请求是无效,浪费浏览器性能和资源,尤其是geoserver服务,还会报边界溢出错误, 这个版本里添加了只加载蒙层里的瓦片支持,这样就可以只加载特定范围内的瓦片了
在做这个功能时有用户提出,支持extent/bbox边界过滤即可,但是这个方法并不能彻底解决瓦片过滤的问题, 因为我们平时瓦片底图资源基本都是不规则的,所以我们并没有采纳这个方法, mask方法更加精细化,可以彻底解决边界溢出的问题
使用方法
const layer = new maptalks.TileLayer("base", {
debug: true,
// repeatWorld: false,
// cascadeTiles:false,
urlTemplate:
"https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
urlTemplate:
"https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
subdomains: ["a", "b", "c", "d"],
maxAvailableZoom: 18,
maskClip: false,
});
const polygons = maptalks.GeoJSON.toGeometry(geojson);
layer.setMask(polygons[0]);
layer.addTo(map);
图层设置图层的mask即可。
注意
因为mask的作用有两个了:
- 剪裁图层
- 过滤瓦片
所以我们在图层里加了 maskClip 选项,表示否是剪裁图层,默认true,如果你只是想过滤瓦片并不希望开启剪裁,关闭maskClip即可
支持的图层
- TileLayer
- VectorTileLayer
- GeoJSONVectorTileLayer
- Geo3DTilesLayer
- 其他的TileLayer的子图层等,像WMSTileLayer
绘制工具增强
支持自定义坐标转换
有时我们想在地形或者3dtiles上绘制图形,这时需要开启3d绘制,绘制工具DrawTool上提供了 transformCoordinate 配置选项用来对当前绘制的坐标进行转换,这里演示将绘制的坐标点 转换成3dtiles下的坐标,如果想转换成其他图层的坐标点以此类推,比如地形,VT等
const layer1 = new maptalks.Geo3DTilesLayer("3dtiles", {
geometryEvents: true,
services: [
{
url: "http://resource.dvgis.cn/data/3dtiles/dayanta/tileset.json",
maximumScreenSpaceError: 16.0,
heightOffset: -400,
},
],
});
const drawTool = new maptalks.DrawTool({
mode: "Point",
once: true,
transformCoordinate: (coordinate, mapEvent) => {
const result = layer1.identify(coordinate);
if (result.length) {
return new maptalks.Coordinate(result[0].coordinate);
}
},
})
.addTo(map)
.disable();
支持动态添加自定义的坐标点
DrawTool 上提供了addCoordinate方法,可以动态的往绘制工具上添加一个自定义的坐标点
drawtool.addCoordinate([1, 1]);
优化map maxExtent的体验
map里添加了个配置选项limitExtentOnMaxExtent
,这个选项可以强制限制地图的边界
var map = new maptalks.Map("map", {
center: [120, 31.498568],
zoom: 4,
limitExtentOnMaxExtent: true,
zoomControl: true,
});
map.on("click", (e) => {
// console.log(e);
});
const baseLayer = new maptalks.TileLayer("base", {
repeatWorld: false,
urlTemplate: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
subdomains: ["a", "b", "c", "d"],
attribution:
'© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a> ',
}).addTo(map);
var bbox = [
118.681640625, 30.929531859423406, 121.318359375, 32.06416211965538,
];
var bbox = [-180, -85, 180, 85];
map.setMaxExtent(bbox);
const layer = new maptalks.VectorLayer("layer").addTo(map);
const debugBBOX = bbox.map((v, index) => {
const offset = 0.01;
if (index < 2) {
return v + offset;
}
return v - offset;
});
const line = new maptalks.LineString(new maptalks.Extent(debugBBOX).toArray(), {
symbol: {
lineDasharray: [5, 5],
},
}).addTo(layer);
const polygon = new maptalks.Polygon([map.getMaxExtent().toArray()]);
baseLayer.setMask(polygon);
const point = new maptalks.Marker(map.getMaxExtent().getCenter()).addTo(layer);
Geometry支持跨时间线
图形上有个配置选项antiMeridian开启即可,注意你的数据必须是跨日期线的才可以,否则 仅仅配置了仍然不生效的
const layer = new maptalks.VectorLayer("layer").addTo(map);
function getGeoOptions() {
return {
antiMeridian: true,
};
}
const polygon = new maptalks.Polygon(
[
[
[171.2109375, 70.50582938421903],
[-153.28125, 67.75439373171932],
[-154.3359375, 57.72055958184691],
[172.265625, 53.3492177615793],
],
],
{
antiMeridian: true,
},
).addTo(layer);
const line = new maptalks.LineString(
[
[171.2109375, 70.50582938421903],
[-153.28125, 70.50582938421903],
],
{
antiMeridian: true,
arrowStyle: "classic",
},
).addTo(layer);
const line1 = new maptalks.LineString(
[
[-153.28125, 70.50582938421903],
[171.2109375, 70.50582938421903],
],
{
antiMeridian: true,
arrowStyle: "classic",
},
).addTo(layer);
图形编辑时控制点支持配置碰撞权重
polygon.startEdit({
collision: true,
vertexZIndex: 1,
newVertexZIndex: 0,
});
图形编辑时控制点碰撞时maptalks特有的一个功能,上一个版本中我们就加入了碰撞功能(collision)了
- 当你的图形顶点数量比较大时,开启碰撞可以拥有更好的性能表现
- vertexZIndex 顶点控制点碰撞权重
- newVertexZIndex 创建新顶点控制点碰撞权重
- 注意只有开启编辑碰撞时我们才需要这两个参数的,如果不开启collision就不要配置这两个参数了
文本读取支持任意字段名字
WARNING
webgl图层还没有适配,下个版本里我们会适配好的
maptalks渲染文本时支持从图形上动态读取字段的值作为文本值的
geometry.updateSymbol({
textName: "{name}",
textFill: "red",
textSize: 16,
});
但是根据同学们的反馈,有时数据里的字段是不是符合标识符的字段规范的
geometry.updateSymbol({
textName: "{名称}",
textFill: "red",
textSize: 16,
});
导致属性读取时无法读取到属性里的数据,这个版本我们不再用正则进行匹配了,而是用最原始的模板数据字段的匹配了,现在可以支持任意字符了,不管是中文,还是其他语言等
注意
不支持套娃,如果套娃会直接拿最里面的字段,即 {名称}
,不管外面套了多少层{}
symbol.visible支持fucntion-type
symbol.visible不仅仅支持简单的值类型,你可以配置function-type了
const point = new maptalks.Marker(center, {
symbol: {
visible: {
//mock minZoom=15,maxZoom=18
stops: [
[1, false],
[15.0, true],
[18.1, false],
[Infinity, false],
],
type: "interval",
},
},
});
一般用于图形来控制图形的层级可见性,上面的代码演示了图形 在地图zoom=[15,18]时才可见,其他的一律隐藏掉
图层mask clip支持holes
- mask支持Polygon或者MultiPolygon
- 每个polygon里携带相关的holes数据即可
Control和UI支持自定义css class
const panel = new maptalks.control.Panel({
content: "hello xxxxxxxxxx",
cssName: "hello",
}).addTo(map);
panel.on("close", (e) => {
console.log(e);
});
const infowindow = new maptalks.ui.InfoWindow({
content: "hello",
cssName: "hello",
}).addTo(map);
const marker = new maptalks.ui.UIMarker(map.getCenter(), {
content: "hello",
cssName: "hello",
}).addTo(map);
优化椭圆点集的生成效果
bug修复
- 修复扇形角度为负的时事件不响应
- 修复图形序列化时丢失海拔高度z
- 修复携带海拔数据图形的视野过滤
- 其他若干bug修复