openLayers 4 canvas图例绘制,canvas循环添加图片,解决图片闪烁问题
2018-01-24 10:22
591 查看
一、问题来源:
接触Openlayers 一段时间了,最近做了一个农业产业系统,项目中涉及到产业图例,最后考虑用canvas来绘制图例图像。当中带图片的图例移动时,图片会实现闪烁留白情况。闪烁是因为绘制图片本身的复杂性,导致canvas绘制频率和浏览器绘制频率不同步,出现图片出不来或者延迟出现,这过程中间就出现了空白显示为canvas底图颜色白色的情况。这里说的闪烁是,在单击地图移动图例时,文字前面的图片并没有出来。但是单击地图准备移动图例时别松开鼠标图片能出来,这个有点奇怪....有些解决方案是用一个叫双缓冲的技术实现,这种办法确实能行,这里就不写了,用我们的办法实现。
双缓冲实现原理:创建一个临时canvas,先把下一帧动画绘制到临时canvas上。在每次真正绘制的时候,擦除正式canvas后,马上drawImage把临时canvas的内容copy过去,而这个copy过程是非常非常高效的,所以基本可以杜绝闪烁。
二 、实现步骤
1、new一个layer层,new一个Feature要素。2、绘制一个canvas图像。
3、new一个样式,设置样式的Icon图片为上一步绘制好的canvas,并设置Icon宽高为canvas宽高。
4、设置要素Feature的样式为上一步new的样式,将要素Feature添加到layer层上。
5、最后将layer层添加到地图中。
三、加载ol地图,加载天地图矢量图为底图
<script type="text/javascript"> var projection = ol.proj.get('EPSG:4326'); var projectionExtent = projection.getExtent(); var size = ol.extent.getWidth(projectionExtent) / 256; var resolutions = new Array(18), matrixIds = new Array(18), shapeArr = []; for(var z = 1; z <= 18; ++z) { resolutions[z] = size / Math.pow(2, z); matrixIds[z] = z; } //天地图矢量图 var tdt_road_layer = new ol.layer.Tile({ name: '矢量底图', source: new ol.source.WMTS({ url: 'http://t1.tianditu.com/vec_c/wmts', layer: 'vec', matrixSet: 'c', format: 'tiles', projection: projection, tileGrid: new ol.tilegrid.WMTS({ origin: ol.extent.getTopLeft(projectionExtent), resolutions: resolutions, matrixIds: matrixIds }), style: 'default' }), visible: true, zIndex: 1 }); var view = new ol.View({ center: [118.77, 32.05], zoom: 9.5, projection: "EPSG:4326", maxZoom: 18 }); var map = new ol.Map({ // 设置地图控件,默认的三个控件都不显示 controls: ol.control.defaults({ attribution: true, rotate: true, zoom: true }).extend([ new ol.control.FullScreen(), new ol.control.ScaleLine() ]), layers: [ tdt_road_layer ], target: 'map', loadTilesWhileAnimating: true, view: view }); </script>
四、实现代码,实现文字前面带图片和带色块图例,有背景色的代码为方法调用,调用即可
<script type="text/javascript"> window.onload = function() { getMapPoint(); drawMapTuliMethod(); } /* * 图例数据 */ var dataObj = [{ tname: '国家级文物保护建筑', color: '#365e96', }, { tname: '省级文物保护建筑', color: '#d1702f', }, { tname: '市级级文物保护建筑', color: '#4fa1dc', }, { tname: '区县级文物保护建筑', color: '#368829', }] /* * 图例经纬度坐标,地图绑定了单击事件 * 单击返回经纬度并重新绘制canvas */ var removeData = { tx: 118.82368355230953, ty: 32.2359887979324 } var canvas = document.createElement('canvas'); //绘制图例 function drawMapTuliMethod() { var layers = new ol.layer.Vector({ type: 'tuli', source: new ol.source.Vector(), zIndex: 9 }) var shape = new ol.Feature({ geometry: new ol.geom.Point([removeData.tx, removeData.ty]) }); var ctx = canvas.getContext("2d"); var yheight = 30; yheight += dataObj.length * 27; //计算canvas高度 canvas.width = 180; canvas.height = yheight; /*设置图例样式*/ ctx.fillStyle = "#fff"; ctx.fillRect(0, 0, 200, yheight); //绘制底图 ctx.font = "16px Arial"; ctx.fillStyle = "#000"; ctx.fillText('图例', canvas.width / 2.5, 25); for(var i = 0; i < dataObj.length; i++) { //实现文字前面带色块 //ctx.fillStyle = dataObj[i].color; //块颜色 //ctx.fillRect(10, 60 + (i - 1) * 25, 15, 15); //颜色块:x,y,w,h ctx.font = "12px Arial"; ctx.fillStyle = "#555"; ctx.fillText(dataObj[i].tname, 30, 72 + (i - 1) * 25); //文字 //添加图片方法一,实现文字前面带图片,移动图例不会出现闪烁 drawImg_first('xiushan.png', i); //添加图片方法二,移动图例会出现闪烁 //drawImg_Second(ctx, 'xiushan.png', i); } //将canvas添加到样式中 var style = new ol.style.Style({ image: new ol.style.Icon({ img: canvas, imgSize: [canvas.width, canvas.height], }) }); shape.setStyle(style); layers.getSource().addFeature(shape); map.addLayer(layers); } /* * 将绘制完成的图片添加到canvas上 * @imgObj:图片对象 * @p:循环序号,确定图片坐标 */ function drawTuliImage(imgObj, p) { var ctxImge = canvas.getContext("2d"); ctxImge.drawImage(imgObj, 5, 30 + (p * 25), 24, 26); } /* * 绘制图例上的图片,方法一 * 此方法能解决重绘canvas时图片闪烁留白的问题 * @imgs:图片名称 * @p:序号 * @complete:HTMLImageElement对象的一个属性,可以判断图片加载完成 */ function drawImg_first(imgs, p) { var imgObj = new Image(); imgObj.src = 'img/' + imgs; //如果图片加载完成 if(imgObj.complete) { drawTuliImage(imgObj, p); } else { //onload:重绘,重新加载 imgObj.onload = function() { drawTuliImage(imgObj, p); }; //加载失败 imgObj.onerror = function() { console.log('canvas图片加载失败,请重试!') }; } } /* * 添加数据前面的图片,方法二 * 此方法绘制图片会出现闪烁留白情况, * @ctx:绘图环境 * @imgs:图片名称 * @p:循环序号 */ function drawImg_Second(ctx, imgs, p) { var imgObj = new Image(); imgObj.src = 'img/' + imgs; imgObj.onload = function() { ctx.drawImage(imgObj, 5, 30 + (p * 25), 25, 27); } } /* * 添加图例之前删除原来 * 引用类型。length会变化,for循环倒着删除 * @deType:要删除的覆盖物名称 */ function addNewsChartsDelectOring(deType) { var layersArr = map.getLayers().getArray(); //获取所有覆盖物 //移除全部 if(deType == 'all') { for(var i = layersArr.length - 1; i >= 0; i--) { var ltype = layersArr[i].get('type'); if(ltype == 'tuli') map.removeLayer(layersArr[i]); } return; } //移除具体 else { for(var i = layersArr.length - 1; i >= 0; i--) { var ltype = layersArr[i].get('type'); if(ltype == deType) map.removeLayer(layersArr[i]); } return; } } //地图单击事件 function getMapPoint() { map.on('click', function(evt) { var point = evt.coordinate; //鼠标单击点坐标 removeData.tx = point[0]; removeData.ty = point[1]; addNewsChartsDelectOring('all'); drawMapTuliMethod(); }); } </script>
①文字前面带图片的图例,移动图例时canvas绘制图片频率和浏览器绘制频率不一导致图片不出来的效果图:
②文字前面带图片的效果图:
③文字前面带色块的效果图:
技术群 : 192713488
相关文章推荐
- 解决html5 canvas 绘制字体、图片与图形模糊问题
- canvas 使绘制的图片在div 居中显示 ,解决绘图模糊问题
- 解决Html5用canvas绘制不出来图片的问题
- 解决Html5用canvas绘制不出来图片的问题
- 谷歌浏览器canvas画图片不显示问题解决
- html5 canvas绘制图片模糊的问题
- 解决图片错位闪烁问题
- 解决Vue2.0中使用less给元素添加背景图片出现的问题
- Android ListView滑动过程中图片显示重复错乱闪烁问题解决
- 图片左右循环连续滚动代码,解决marquee的留白问题
- Android ListView滑动过程中图片显示重复错乱闪烁问题解决
- ListView滑动过程中图片显示重复错位闪烁问题解决
- [转]Android ListView滑动过程中图片显示重复错乱闪烁问题解决
- RecyclerView中ViewHolder重用机制理解(解决图片错乱和闪烁问题)
- 解决自绘制控件闪烁的问题
- Android ListView滑动过程中图片显示重复错位闪烁问题解决
- listView异步加载图片导致图片错位、闪烁、重复的问题的解决
- 图片左右循环连续滚动代码,解决marquee的留白问题
- 解决使用drawRect绘制界面,图片拉伸问题
- Android ListView滑动过程中图片显示重复错位闪烁问题解决