openLayers 4 canvas图例绘制,canvas循环添加图片,解决图片闪烁问题
一、问题来源:
接触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) / ;
var resolutions = new Array(),
matrixIds = new Array(),
shapeArr = [];
for(var z = ; z <= ; ++z) {
resolutions[z] = size / Math.pow(, 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:
});
var view = new ol.View({
center: [118.77, 32.05],
zoom: 9.5,
projection: "EPSG:4326",
maxZoom:
});
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:
})
var shape = new ol.Feature({
geometry: new ol.geom.Point([removeData.tx, removeData.ty])
}); var ctx = canvas.getContext("2d");
var yheight = ;
yheight += dataObj.length * ; //计算canvas高度
canvas.width = ;
canvas.height = yheight; /*设置图例样式*/
ctx.fillStyle = "#fff";
ctx.fillRect(, , , yheight); //绘制底图
ctx.font = "16px Arial";
ctx.fillStyle = "#000";
ctx.fillText('图例', canvas.width / 2.5, );
for(var i = ; 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, , + (i - ) * ); //文字 //添加图片方法一,实现文字前面带图片,移动图例不会出现闪烁
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, , + (p * ), , );
} /*
* 绘制图例上的图片,方法一
* 此方法能解决重绘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, , + (p * ), , );
}
} /*
* 添加图例之前删除原来
* 引用类型。length会变化,for循环倒着删除
* @deType:要删除的覆盖物名称
*/
function addNewsChartsDelectOring(deType) {
var layersArr = map.getLayers().getArray(); //获取所有覆盖物
//移除全部
if(deType == 'all') {
for(var i = layersArr.length - ; i >= ; i--) {
var ltype = layersArr[i].get('type');
if(ltype == 'tuli') map.removeLayer(layersArr[i]);
}
return;
}
//移除具体
else {
for(var i = layersArr.length - ; i >= ; 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[];
removeData.ty = point[];
addNewsChartsDelectOring('all');
drawMapTuliMethod();
});
}
</script>
①文字前面带图片的图例,移动图例时canvas绘制图片频率和浏览器绘制频率不一导致图片不出来的效果图:
②文字前面带图片的效果图:
③文字前面带色块的效果图:
技术群 : 192713488
openLayers 4 canvas图例绘制,canvas循环添加图片,解决图片闪烁问题的更多相关文章
- Android 如何将Canvas上绘制的内容保存成本地图片(转)
效果如下图所示 保存在sd卡上的文件为 手机上显示效果为: 1>>在Manifest文件中增加相应权限 <!-- 在SDCard中创建与删除文件权限 --> <uses- ...
- canvas纯绘制雨伞、飞机、五角星、桃心,无逻辑
由于网上很多都是用很多算法和逻辑使用canvas进行绘制,但有时也无法解决一些小众需求 . 为了满足需求不能写运算纯手写,感觉真的很浪费时间,只有自己踩过的坑,才不想看到别人也被坑.我很懒,也想过弄个 ...
- canvas高效绘制10万图形,你必须知道的高效绘制技巧
最近的一个客户项目中,简化的需求是绘制按照行列绘制很多个圆圈.需求看起来不难,上手就可以做,写两个for循环. 原始绘制方法 首先定义了很多Circle对象,在遍历循环中调用该对象的draw方法.代码 ...
- HTML5 Canvas中绘制椭圆的几种方法
1.canvas自带的绘制椭圆的方法 ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)是后来 ...
- HTML5使用Canvas来绘制图形
一.Canvas标签: 1.HTML5<canvas>元素用于图形的绘制,通过脚本(通常是javascript)来完成. 2.<canvas>标签只是图形容器,必须使用脚本来绘 ...
- Canvas 实现绘制图表
这里用canvas实现了两个简单的图表,用到了canvas的基本用法,效果如下 新建 chart.js 文件,封装绘制方法 构造方法 function myChart(config){ this.wi ...
- canvas+js绘制序列帧动画+面向对象
效果: 素材: 源码:(一般的绘制方式) <!DOCTYPE html> <html lang="en"> <head> <meta ch ...
- 软件项目技术点(7)——在canvas上绘制自定义图形
AxeSlide软件项目梳理 canvas绘图系列知识点整理 图形种类 目前我们软件可以绘制出来的形状有如下这几种,作为开发者我们一直想支持用户可以拖拽的类似word里面图形库,但目前还没有找到比 ...
- Canvas:绘制路径
Canvas:绘制路径 绘制路径 图形的基本元素是路径.路径是[通过不同颜色和宽度的线段或曲线相连形成的不同形状的]点的集合.一个路径,甚至一个子路径,都是闭合的. 使用路径绘制图形需要一些额外的步骤 ...
随机推荐
- Bata冲刺 第一天
一.冲刺第一天完成任务情况及贡献小时数: 姓名 今日已完成任务 时间(h) 马仲山 代码调整 2 马婧(12) 整理需求文档 2 马婧(13) 整理设计文档 2 马世芳 编写测试文档 2 张俊逸 ...
- Java之美[从菜鸟到高手演变]系列之博文阅读导航
随着博文越来越多,为博客添加一个导航很有必要!本博客将相继开通Java.CloudFoundry.Linux.Ruby等专栏,都会设立目录,希望读者朋友们能更加方便的阅读! 在阅读的过程中有任何问题, ...
- scss 覆盖 原有变量
在scss的variables.scss 中会有很多的变量 $color: red !default; $body-color: $color !default; 这些!default 和我们理解的! ...
- 在 Confluence 6 中的 Jira 高级权限
启用嵌套用户组(Enable Nested Groups) 为嵌套组启用或禁用支持. 在启用嵌套用户组之前,你需要检查你在 JIRA 服务器中的嵌套用户组是否启用了.当嵌套用户组启用成功后,你可以将一 ...
- linux--多进程进行文件拷贝
学习IO的时候,我们都曾经利用文件IO函数,标准IO函数都实现了对文件的拷贝, 对某一个文件进行拷贝时,我们可以考虑一下几种方式: a.单进程拷贝: 假设某一文件需要拷贝100字节,每一个时间片可以完 ...
- 新学dfs(看懂了)
在N*N的迷宫内,“#”为墙,“.”为路,“s”为起点,“e”为终点,一共4个方向可以走.从左上角((0,0)“s”)位置处走到右下角((n-1,n-1)“e”)位置处,可以走通则输出YES,不可以走 ...
- Java IO流中的flush()
通过BufferedOutputStream或BufferedWriter 链接到底层流上来实现.因此,在写 完数据时,flush就显得尤为重要. 例如: 上图中WEB服务器通过输出流向客户端响应了一 ...
- Google浏览器设置变更默认搜索引擎为百度
- SQL TUNING——从近半小时到几十毫秒的一次优化
昨天,一个用户的现场人员打电话紧急求助,说他们的一个系统卡了,半天不出结果,严重的影响了他们的使用,我简单的问了几句:什么时候的事儿?答:就今天下午的事儿.问:数据库软硬件最近动过没?答:没动过.问: ...
- ES批量索引写入时的ID自动生成算法
对bulk request的处理流程: 1.遍历所有的request,对其做一些加工,主要包括:获取routing(如果mapping里有的话).指定的timestamp(如果没有带timestamp ...