参考文档:CreateJS | A suite of JavaScript libraries and tools designed for working with HTML5
想要了解和下载更多关于 标准地图 的内容,欢迎访问中国地图出版集团官网和中国地图出版集团官方微博
本文用到的地图数据来源于《2021年日历 每日人文地图》
如有兴趣可自行购买
🎴 效果演示
愿祖国的首都,也都是绿水青山😀
📑 前言概述
先前在博文 《无道理的区划边界,不规则矢量图形Createjs绘制流程初探》 中,利用 Illustrator 的钢笔工具,勾绘不规则图形,并导出 svg <polygon>
后,通过 createjs.Graphics
依次点绘制形状,详细内容可点击查看。
不过这个逻辑中有一个重大问题,那就是真正的“地图”数据,是不容编辑直接通过钢笔工具去勾绘边界的。同时通过钢笔勾绘的点集,都是直线,并不包括贝塞尔曲线等内容。😓
那该是如何是好,本文来解答。🤭
🔠 数据获取
﹂ Illustrator中的操作
从《2021年日历 每日人文地图》编辑处,得到了北京区划的 .ai
文件,只选取底图的图层,保存成 .svg
文件。
﹂ Animate中的操作
将 .svg
文件导入 Animate 当中,将包含所有区域的元素进行 “分离” 和 “分散到图层”,然后将每个图层进行命名,用于后续可以从代码中找到对应。
然后通过 Animate 的 “发布” 操作,将内容发布为 “javascript/html” 代码。其中 .js
文件形式如下图。
根据 createjs
的语法,.p()
方法中的参数则为构建形状的 decodePath
参数,而 setTransform
中的两个数值,则是当前形状相对于画布的位置坐标。
﹂ 利用RegExp收集数据
通过 getPath
方法,抽取代码中的 decodePath
,x,y
以及 标识的名称
function getPath (str){
let reg = /\/\/ ([\u4e00-\u9fa5]+).+\.p\("(.*)"\).*form\((.*)\)/g
let result = []
while (true) {
let irr = reg.exec(str)
if (!irr) {
break
}
let res = {
name: irr[1],
path: irr[2],
bias: irr[3]
}
result.push(res)
}
return JSON.stringify(result)
}
执行后得到的结果如图所示:
💻 代码分释
其实后续代码就很简单了,在此为了美观,增加了区域随机填色、以及点击弹出区域名称的功能。也算是 Animate 动画在 H5 中的关联和功能扩展。
let stage, path, loader
let animate
let g = axios.get('data.json')
const init = () => {
stage = new createjs.Stage('examCanvas')
createjs.Ticker.timingMode = createjs.Ticker.RAF
createjs.Ticker.addEventListener('tick', tick)
animate = document.querySelector('.animate')
g.then(function (res) {
path = res.data
// 循环对每条路径进行绘制 & 设置坐标
path.forEach(item => {
let shape = new createjs.Shape(
new createjs.Graphics().s('#fff').f(`rgb(${rc()},200,100`).p(item.path)
)
let [x, y] = item.bias.split(',')
shape.setTransform(x, y)
// 增加点击事件
shape.addEventListener('click', e => {
animateCSS(animate, 'bounceIn')
animate.innerText = item.name
animate.style.color = e.target.graphics._fill.style
})
stage.addChild(shape)
})
})
}
const tick = e => {
stage.update()
}
const rc = () => Math.random() * 255
// animate动画执行方法
const animateCSS = (element, animation, prefix = '') =>
new Promise((resolve, reject) => {
const animationName = `${prefix}${animation}`;
const node = element.nodeType == 1 ? element : document.querySelector(element);
node.classList.add(`${prefix}animated`, animationName);
function handleAnimationEnd(event) {
event.stopPropagation();
node.classList.remove(`${prefix}animated`, animationName);
resolve('Animation ended');
}
node.addEventListener('animationend', handleAnimationEnd, { once: true });
});
window.onload = init
🐈 完整代码
码字不易,如果喜欢,不用三连,点个赞👍便是最大的鼓励
欢迎关注微信公众号 "书咖里的曼基康"