地图上的一小寸,是人类实际跨越的一大大大大……步
根据地图经纬度绘制 canvas 电子围栏
第二版代码
根据地图经纬度绘制 canvas 电子围栏【2】
画个坐标轴
坐标转换
把输入的经纬度坐标转换为显示在 canvas 上的坐标
坐标放大
地图上的一小寸,是人类实际跨越的一大大大大……步
比如 A [39.075069,117.22905]
和 B [39.074902,117.22673]
,两个坐标点的值相差的量级只有 0.001
。
而 canvas 是最小显示是1像素
。
所以要把坐标放大,比如 100 万倍: 39.075069117 × 1000000 - 39.074902117 × 1000000 = 167,就可以在 canvas 上显示出两个点的距离了。
1 2 3 4
| area = area.map(p => { return [p.x * scale + x0, (y0 - p.y) * scale]; });
|
这样,解决了坐标值的差距问题,又出现了另一个问题:_ 看不见点了!_
因为 canvas 的可见视野就是预设的 1000*800,如上图所示:蓝色框外都不可见!!
原点移动
通过 ctx.translate(-xoffset, -yoffset);
平移坐标原点,把经纬点所在的区域显示在视野里!
结果展示
最终结果是这样的(测试红点是不是在电子围栏内?)
在线 DEMO
经纬度转直角坐标-根据地图经纬度绘制 canvas 电子围栏
核心代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| let myCanvas = document.querySelector('canvas'); let ctx = myCanvas.getContext('2d');
let points = [{"x":39.047335,"y":117.203573}]; let area = [{"x":39.075069,"y":117.22905},{"x":39.074902,"y":117.22673}...]
const ALL_POINT = [...points, ...area]; let xMax = Math.max(...ALL_POINT.map(e => e.x)); let xMin = Math.min(...ALL_POINT.map(e => e.x)); let yMax = Math.max(...ALL_POINT.map(e => e.y)); let yMin = Math.min(...ALL_POINT.map(e => e.y));
let xScale = ((canvasWidth / 3) * 2) / (xMax - xMin); let yScale = ((canvasHeight / 3) * 2) / (yMax - yMin); let scale = Math.min(xScale, yScale);
let xoffset = xMin * scale - canvasWidth / 3 / 2; let yoffset = (y0 - yMax) * scale - canvasHeight / 3 / 2; ctx.translate(-xoffset, -yoffset);
const X00 = x0 + xoffset; const Y00 = y0 + yoffset;
console.log('X00,Y00 放大:', X00, Y00); console.log('X00,Y00 实际', X00 / scale, y0 - Y00 / scale); ctx.font = '14px Arial'; ctx.strokeText(`坐标原点:${X00 / scale},${y0 - Y00 / scale}`, X00 - 16, Y00 + 16);
area = area.map(p => { return [p.x * scale + x0, (y0 - p.y) * scale]; });
drawArea(area);
points.forEach(p => { const xx = p.x * scale + x0; const yy = (y0 - p.y) * scale; drawPoint(xx, yy); }); function drawArea(area) { ctx.beginPath(); ctx.lineWidth = 2; ctx.strokeStyle = 'blue'; area.forEach(([xx, yy], i) => { if (i == 0) { ctx.moveTo(xx, yy); } else { ctx.lineTo(xx, yy); } }); ctx.closePath(); ctx.stroke(); } function drawPoint(xxx, yyy) { ctx.beginPath(); ctx.lineWidth = 4; ctx.strokeStyle = 'red'; ctx.moveTo(xxx, yyy); ctx.lineTo(xxx + 2, yyy + 2); ctx.closePath(); ctx.stroke(); }
|