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:绘制路径 绘制路径 图形的基本元素是路径.路径是[通过不同颜色和宽度的线段或曲线相连形成的不同形状的]点的集合.一个路径,甚至一个子路径,都是闭合的. 使用路径绘制图形需要一些额外的步骤 ...
随机推荐
- SPP Net(Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition)论文理解
论文地址:https://arxiv.org/pdf/1406.4729.pdf 论文翻译请移步:http://www.dengfanxin.cn/?p=403 一.背景: 传统的CNN要求输入图像尺 ...
- English trip -- VC(情景课)1 A Get ready
Meet your classmates 见见你的同学 Look at the picture. What do you see? 看图片.你看到了什么? calendar 日历 bookcase ...
- 20170709pptVBA递归删除LOGO图片与文字
Public Sub StartRecursionFolder() Dim Pre As Presentation Dim FolderPath As String Dim pp As String ...
- Android之封装好的异步网络请求框架
1.简介 Android中网络请求一般使用Apache HTTP Client或者采用HttpURLConnection,但是直接使用这两个类库需要写大量的代码才能完成网络post和get请求,而使 ...
- Confluence 6 的 Crowd 权限
只读(Read Only) 从 Crowd 上获取的用户,用户组和用户组成员信息只具有读取权限,你只能在 Crowd 上对你的配置进行修改.你不能通过你的应用程序管理员界面修改,用户,用户组,用足成员 ...
- 『Kaggle』分类任务_决策树&集成模型&DataFrame向量化操作
决策树这节中涉及到了很多pandas中的新的函数用法等,所以我单拿出来详细的理解一下这些pandas处理过程,进一步理解pandas背后的数据处理的手段原理. 决策树程序 数据载入 pd.read_c ...
- python-day6---运算符
#了解部分#字符串+,*#列表:+,*# l1=[1,2,3]# l2=[4,5]## print(l1+l2)# print(l1*3) #比较运算符# num1=3# num2=1 # print ...
- 最齐全的Android studio 快捷键(亲测可用)
Action Mac OSX Win/Linux 注释代码(//) Cmd + / Ctrl + / 注释代码(/**/) Cmd + Option + / Ctrl + Alt + / 格式化代码 ...
- Application 类
Application 类具有用于启动和停止应用程序和线程以及处理 Windows 消息的方法,如下所示: Run 在当前线程上启动应用程序消息循环,并可以选择使某窗体可见. Exit 或 ExitT ...
- OC 内存管理之手动内存管理MRC
一.基本原理 1.什么是内存管理 内存管理的重要性: 移动设备的内存极其有限,每个app所能占用的内存是有限制的 当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间. ...