一、问题来源:
接触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:绘制路径 绘制路径 图形的基本元素是路径.路径是[通过不同颜色和宽度的线段或曲线相连形成的不同形状的]点的集合.一个路径,甚至一个子路径,都是闭合的. 使用路径绘制图形需要一些额外的步骤 ...
随机推荐
-
js在IE和FF下的兼容性问题
本文出自前端档案,以作学习参考之用.自己也补充了一些内容 长久以来JavaScript兼容性一直是Web开发者的一个主要问题.在正式规范.事实标准以及各种实现之间的存在的差异让许多开发者日夜煎熬.为此 ...
-
IOS开发--仿制网易新闻
学习来源:袁峥老师的<快速集成App中顶部标题滚动条> 此次博文写的是按需求分析写代码,思路条理性杠杠的,可以提高的编码实现速度哦. 效果: 根据这个网易新闻的界面,需求分析: ...
-
make与makefile
Linux makefile 教程 非常详细,且易懂 make与makefile GNU make体系Linux 环境下的程序员如果不会使用GNU make来构建和管理自己的工程,应该不能算是一个合格 ...
-
连接查询中on and和on where的区别
一.区别 1. and条件是在生成临时表时使用的条件,它不管and中的条件是否为真,都会返回左(或者右)边表中的记录. 2.where条件是在临时表生成好后,再对临时表进行过滤的条件.这时已经没有le ...
-
[Reactive Programming] Using an event stream of double clicks -- buffer()
See a practical example of reactive programming in JavaScript and the DOM. Learn how to detect doubl ...
-
十条很实用的jQuery代码片段
本文转自:http://developer.51cto.com/art/201604/509093.htm 作者:核子可乐译来源:51CTO 原文标题:10 jQuery Snippets for E ...
-
PHP Ajax JavaScript Json 实现天气信息获取
使用第三方服务 间接方式 思路 使用到的服务 实现代码 前端完整代码 总结 要在自己的网站上添加一个天气预报功能,是一个很普通的需求,实现起来也不是很难.今天来介绍几个简单的方法. 使用第三方服务 有 ...
-
可遇不可求的Question之MySqlClient的Guid 类型的映射篇
关于 Guid 类型的映射 MySql 没有原生的 Guid 类型,一般使用 binary(16) 或者 char(36) 这两个类型.早期版本的 Connector/Net 将 binary(16) ...
-
python学习 day017打卡 类与类之间的关系
本节主要的内容: 1.依赖关系 2.关联关系,组合关系,聚合关系 3.继承关系,self到底是什么? 4.类中的特殊成员 一.类与类之间的依赖关系 在面向对象的世界中,类与类中存在以下关系: 1.依赖 ...
-
centos6.5+python2.7+flask+apache+mod-wsgi部署
flask部署,使用的是centos6.5,python2.7,版本很重要.基本步骤如下: 一.创建虚拟环境,创建目录把项目拷进去 二.安装mod-wsgi和apache easy_install m ...