通过canvas加载geojson深入解析添加矢量数据本质
// 自行获取json数据
const [state, rs, err] = await getData('./sx.json')
//公共数据
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext("2d"); // canvas元素的contex对象
let width = window.innerWidth; // 画布宽度
let height = window.innerHeight; // 画布高度
canvas.width = width;
canvas.height = height;
let center = [108, 36]
let scale = 100
let zoom = 5
let zooms = {
5: 100,
6: 110,
7: 130,
8: 170,
9: 250,
10: 410,
11: 730,
12: 1470,
13: 2600,
14: 5000,
15: 10000,
16: 20000,
17: 40000
}
// 坐标转换
function coordTrans(coord, center) {
// coord和center传入的都要是原始经纬度坐标
// 经纬度坐标,纬度大的点在canvas的坐标系中会处于下方,而现实中应该处于上方,
// 所以对所有点纬度坐标进行取反修正
coord = [coord[0], -coord[1]]
center = [center[0], -center[1]]
// 然后把中心点已到坐标系原点,重新计算其他点坐标
return [coord[0] - center[0], coord[1] - center[1]]
}
// 渲染地图
function draw() {
//清除画布
ctx.clearRect(0, 0, width, height);
ctx.save(); //保存初始状态
ctx.translate(width / 2, height / 2) // 移动坐标系原点到canvas画布中心
ctx.strokeStyle = '#00ff00'
ctx.strokeWidth = '1px'
// 开始设置路径
ctx.beginPath();
// 陕西地市
rs.features.forEach((feature, featureIndex) => {
feature.geometry.coordinates.forEach((subCoordss, index) => {
subCoordss.forEach((subCoords, index1) => {
ctx.beginPath();
//
subCoords.forEach((coord, index1) => {
// 坐标转换
const real_coord = coordTrans(coord, center)
if(index1 == 0) {
// 设置成跳跃点
ctx.moveTo(real_coord[0] * scale, real_coord[1] * scale);
} else {
// 非起点
ctx.lineTo(real_coord[0] * scale, real_coord[1] * scale);
}
})
ctx.closePath(); //当前路径封闭
ctx.fillStyle = 'skyblue'; //颜色填充
ctx.fill(); //执行
ctx.strokeStyle = 'red';
ctx.stroke();
})
})
if(zoom <= 8) {
ctx.textAlign = 'center'
ctx.font = "normal bold 20px 楷体"
ctx.textBaseline = 'middle'
ctx.fillStyle = 'black'
const real_coordt = coordTrans(feature.properties.centroid, center)
ctx.fillText(feature.properties.name, real_coordt[0] * scale, real_coordt[1] * scale)
}
})
ctx.restore(); //回退状态
window.requestAnimationFrame(draw)
}
// 请求关键帧
window.requestAnimationFrame(draw)
canvas.addEventListener('mousewheel', function(e) {
if(e.wheelDelta > 0) { //当滑轮向上滚动时
if(zoom < 17) {
zoom++
}
} else if(e.wheelDelta < 0) { //当滑轮向下滚动时
if(zoom > 5) {
zoom--
}
}
scale = zooms[zoom]
})
window.addEventListener('resize', function(e) {
width = window.innerWidth; // 画布宽度
height = window.innerHeight; // 画布高度
canvas.width = width;
canvas.height = height;
});
let ppxy = [0, 0]
let ppcenter = [108, 36]
canvas.addEventListener('mousedown', function(e) {
if(e.buttons==1){
ppxy = [e.offsetX, e.offsetY]
ppcenter = [center[0], center[1]]
canvas.addEventListener('mousemove', movto, false)
canvas.addEventListener('mouseup', moup, false)
}
})
canvas.addEventListener('click', mapclick, false)
function moup(e) {
ppxy = [0, 0]
e.stopPropagation()
canvas.removeEventListener('mousemove', movto)
}
function movto(e) {
let offx = ppcenter[0] - (e.offsetX - ppxy[0]) / scale
let offy = ppcenter[1] + (e.offsetY - ppxy[1]) / scale
center = [offx, offy]
}
function mapclick(e) {
if(e.button==0){
console.log(center[0] - (e.offsetX - canvas.width / 2) / scale, center[1] - (e.offsetY - canvas.height / 2) / scale)
}
}
加载完成如图所示: