上篇文章我们知道了怎么去绘制一个多边形,既然有了多边形,那么这篇文章就教大家使用来绘制一个中国地图。
基础知识-GeoJSON
在绘制之前,我们必须了解标准的地图地理位置json文件。
下面是一个示例:
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": {"type": "Point", "coordinates": [102.0, 0.5]}, "properties": {"prop0": "value0"} }, { "type": "Feature", "geometry": { "type": "LineString", "coordinates": [ [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0] ] }, "properties": { "prop0": "value0", "prop1": 0.0 } }, { "type": "Feature", "geometry": { "type": "Polygon", "coordinates": [ [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ] ] }, "properties": { "prop0": "value0", "prop1": {"this": "that"} } } ] }
简单的说,GeoJSON文件通过type字段定义了几种地图相关的图形:"Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon", "GeometryCollection", "Feature", "FeatureCollection"。
对于常见的地图来说,最常用的类型就是Polygon(多边形)和MultiPolygon(镂空多边形),这篇文章也只会用到这两类图形来绘制。
关于GeoJSON文件中各个字段更详细的含义,可以参考网上的其他文章,比如这篇译文:https://www.oschina.net/translate/geojson-spec
只要对文件有个大致的了解,我们就可以进行下一步的绘制了。
使用Ycc绘制地图
在Ycc框架中,封装了一个多边形类Ycc.UI.Polygon,它的绘制函数很简单:
Ycc.UI.Polygon.prototype.render = function (ctx) { var self = this; ctx = ctx || self.ctx; if(!self.ctx){ console.error("[Ycc error]:","ctx is null !"); return; } // 多边形的顶点坐标数组 var coordinates = this.coordinates; // 绘制的起点 var start = coordinates[0]; ctx.save(); ctx.fillStyle = this.fillStyle; ctx.strokeStyle = this.strokeStyle; ctx.beginPath(); ctx.moveTo(start.x,start.y); for(var i=0;i<this.coordinates.length-1;i++){ var dot = this.coordinates[i]; ctx.lineTo(dot.x,dot.y); } ctx.closePath(); this.fill?ctx.fill():ctx.stroke(); ctx.restore(); };
上面代码没什么特别的地方,就是上一篇文章介绍的绘制多边形的方法,只不过加入了颜色、是否填充、多边形坐标点数组等参数。
注意:在我们的GeoJSON文件中也有一个coordinates参数,它们是否一样呢?
事实上它们就是一样的,只不过在GeoJSON文件中使用数组的方式[x,y,z]这种方式表示x,y,z,而在Ycc框架中采用对象的方式{x,y,z}表示,差别仅此而已。
有了这个认识,我们只需要转换一下坐标就可以直接使用Polygon类进行绘制了。
代码量也不是很大,这里直接贴出来
var canvas = document.createElement("canvas"); canvas.width = 350; canvas.height = 250; document.getElementById("canvas").appendChild(canvas); // 地图的偏移量 var offsetX = 70; // 临界值为 73.4766 var offsetY = 60; // 临界值为 53.5693 // 缩放倍数 var scale=5; var ycc = new Ycc(); ycc.bindCanvas(canvas); // 新建图层 var layer = ycc.layerManager.newLayer({enableEventManager:true}); ycc.ajax.get('./china.json',function (data) { data = JSON.parse(data); data.features.forEach(function (item) { // 河北等省为MultiPolygon,取第一个多边形直接绘制 var provinceDots = item.geometry.type==="MultiPolygon"?item.geometry.coordinates[0][0]:item.geometry.coordinates[0]; var dots = provinceDots.map(function (dot) { //x坐标去除偏移量,y坐标加上偏移量,并做镜像处理 return new Ycc.Math.Dot((dot[0]-offsetX)*scale,(offsetY-dot[1])*scale); }); var polygon = new Ycc.UI.Polygon({ coordinates:dots, fill:false, fillStyle:"rgb(0,88,160)", noneZeroMode:2, userData:{area:item}, strokeStyle:"rgb(0,88,160)", ontap:onEvent, onmousemove:onEvent, }); layer.addUI(polygon); ycc.layerManager.reRenderAllLayerToStage(); // 事件处理:填充选中的省份 function onEvent(e) { this.belongTo.uiList.forEach(function (t) { t.fill=false; }); this.fill=true; ycc.layerManager.reRenderAllLayerToStage(); document.getElementById('area').innerHTML=this.userData.area.properties.name; } }); });
上面代码中的两个参数需要说明一下。
1、偏移量:
由于地图的坐标都是用经纬度来表示的,如果没有偏移量直接绘制,是不会出现在我们画面左上角的。这个临界值,实质就是地图经纬度的临界值。
2、缩放比例:
原因也一样,由于地图的坐标都是用经纬度来表示的,与我们实际像素坐标是有差别的,如果直接绘制,地图会非常小。
示例与总结
地图的绘制其实不算很难,难的是地图各个坐标数据的采集、更新、维护。
本例的区域地图相对来说是很简单的地图,更新维护只需要更新区域的坐标点。像百度高德这种成熟的地图,数据维护起来相当麻烦,区域信息、标记信息、道路信息、森林覆盖信息、河流信息等等,所以地图相关的一切都需要维护更新。
好在有开源的力量,帮我们维护更新区域信息和位置信息,https://github.com/modood/Administrative-divisions-of-China
文末惯例,贴上示例链接:https://www.lizhiqianduan.com/products/ycc/examples/map-of-china/
效果如下:
(本文完)
打赏作者
写的很好,支持一下