当前位置:   article > 正文

Openlayers利用原生Canvas绘制闪烁样式_openlayers canvas

openlayers canvas

背景

项目需要地图上实现不断报警的闪烁样式,之前是通过Overlay来处理的,但Overlay遮挡要素,无法很好的触发事件,所以就转而使用Canvas原生实现。过程主要参考:openlayers4中闪烁点的实现canvas-flashMarker-RunJS

改造

原flashMarker的使用

原本的做法是通过构造新的对象new FlashMarker(map, citys),每次构造新增一个Canvas,没有办法清除,那么我针对这些问题进行适应性的修改。

改造版本的使用

  • 通过构造CanvasLayer进行使用,只需使用一个Canvas的可以只new一个对象。
  • 得到图层对象后调用addMarkers方法,一批批地将闪烁样式加入到Canvas里。
  • 清除Canvas调用clear方法,直接对图层进行清空。

不足

经测试,过多的样式绘制会有卡顿,目前没有太好的方法解决,不过Canvas绘制仍然效果比Openlayers好。

代码

这里效果就不展示了,效果可以在背景贴的原文那里看,我只是改动调用和优化实现。

  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  3. typeof define === 'function' && define.amd ? define(factory) :
  4. (global.CanvasLayer = factory());
  5. }(this, (function () { 'use strict';
  6. //封装一个兼容性良好的方法
  7. window.requestAnimFrame= (function(){
  8. return window.requestAnimationFrame ||
  9. window.webkitRequestAnimationFrame ||
  10. window.mozRequestAnimationFrame ||
  11. function(callback){
  12. window.setTimeout(callback, 1000 / 60);
  13. }
  14. })();
  15. window.cancelAnimFrame = (function(){
  16. return window.cancelAnimationFrame ||
  17. window.webkitCancelAnimationFrame ||
  18. window.mozCancelAnimationFrame ||
  19. function(id){
  20. window.clearTimeout(id);
  21. }
  22. })();
  23. function CanvasLayer(options) {
  24. this.options = options || {};
  25. this.paneName = this.options.paneName || 'labelPane';
  26. this.zIndex = this.options.zIndex || 0;
  27. this._map = options.map;
  28. this._lastDrawTime = null;
  29. this.show();
  30. }
  31. CanvasLayer.prototype.initialize = function () {
  32. var map = this._map;
  33. var canvas = this.canvas = document.createElement('canvas');
  34. var ctx = this.ctx = this.canvas.getContext('2d');
  35. canvas.style.cssText = 'position:absolute;' + 'left:0;' + 'top:0;' + 'z-index:' + this.zIndex + ';';
  36. this.animationIds = [];
  37. this.adjustSize();
  38. this.adjustRatio(ctx);
  39. map.getViewport().appendChild(canvas);
  40. var that = this;
  41. map.getView().on('propertychange',function(){
  42. $(canvas).hide();
  43. });
  44. map.on("moveend",function(){
  45. $(canvas).show();
  46. that.adjustSize();
  47. //that._draw();
  48. });
  49. };
  50. // Wilson
  51. CanvasLayer.prototype.clear = function () {
  52. var animationCtx = this.ctx;
  53. var width = this._map.getSize()[0];
  54. var height = this._map.getSize()[1];
  55. var animationIds = this.animationIds;
  56. for (var i = 0; i < animationIds.length; i++) {
  57. window.cancelAnimationFrame(animationIds[i]);
  58. }
  59. this.animationIds = [];
  60. animationCtx.clearRect(0, 0, width, height);
  61. };
  62. // Wilson
  63. CanvasLayer.prototype.addMarkers = function (dataSet) {
  64. var animationCtx = this.ctx;
  65. var width = this._map.getSize()[0];
  66. var height = this._map.getSize()[1];
  67. var markers = [];
  68. var length = this.animationIds.length;
  69. var that = this;
  70. for (var i = 0; i < dataSet.length; i++) {
  71. markers.push(new Marker(dataSet[i]));
  72. }
  73. //开始动画
  74. var startAnim = function() {
  75. var animationId = window.requestAnimFrame(render);
  76. that.animationIds[length] = animationId;
  77. }
  78. function render() {
  79. startAnim();
  80. animationCtx.fillStyle = 'rgba(0,0,0,.95)';
  81. var prev = animationCtx.globalCompositeOperation;
  82. animationCtx.globalCompositeOperation = 'destination-in';
  83. animationCtx.fillRect(0, 0, width, height);
  84. animationCtx.globalCompositeOperation = prev;
  85. for (var i = 0; i < markers.length; i++) {
  86. var marker = markers[i];
  87. marker.draw(animationCtx);
  88. }
  89. };
  90. startAnim();
  91. };
  92. CanvasLayer.prototype.adjustSize = function () {
  93. var size = this._map.getSize();
  94. var canvas = this.canvas;
  95. canvas.width = size[0];
  96. canvas.height = size[1];
  97. canvas.style.width = canvas.width + 'px';
  98. canvas.style.height = canvas.height + 'px';
  99. };
  100. CanvasLayer.prototype.adjustRatio = function (ctx) {
  101. var backingStore = ctx.backingStorePixelRatio || ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
  102. var pixelRatio = (window.devicePixelRatio || 1) / backingStore;
  103. var canvasWidth = ctx.canvas.width;
  104. var canvasHeight = ctx.canvas.height;
  105. ctx.canvas.width = canvasWidth * pixelRatio;
  106. ctx.canvas.height = canvasHeight * pixelRatio;
  107. ctx.canvas.style.width = canvasWidth + 'px';
  108. ctx.canvas.style.height = canvasHeight + 'px';
  109. ctx.scale(pixelRatio, pixelRatio);
  110. };
  111. /*CanvasLayer.prototype._draw = function () {
  112. var map = this._map;
  113. var size = map.getSize();
  114. var center = map.getView().getCenter();
  115. if (center) {
  116. var pixel = map.getPixelFromCoordinate(center);
  117. this.canvas.style.left = pixel[0] - size[0] / 2 + 'px';
  118. this.canvas.style.top = pixel[1] - size[1] / 2 + 'px';
  119. //this.options.update && this.options.update.call(this);
  120. }
  121. };*/
  122. CanvasLayer.prototype.getContainer = function () {
  123. return this.canvas;
  124. };
  125. CanvasLayer.prototype.show = function () {
  126. this.initialize();
  127. this.canvas.style.display = 'block';
  128. };
  129. CanvasLayer.prototype.hide = function () {
  130. this.canvas.style.display = 'none';
  131. };
  132. CanvasLayer.prototype.setZIndex = function (zIndex) {
  133. this.canvas.style.zIndex = zIndex;
  134. };
  135. CanvasLayer.prototype.getZIndex = function () {
  136. return this.zIndex;
  137. };
  138. CanvasLayer.prototype.getZIndex = function () {
  139. return this.zIndex;
  140. };
  141. function Marker(opts) {
  142. this.city = opts.name;
  143. this.location = [opts.lnglat[0], opts.lnglat[1]];
  144. this.color = opts.color;
  145. this.type = opts.type || 'circle';
  146. this.speed = opts.speed || 0.15;
  147. this.size = 0;
  148. this.max = opts.max || 20;
  149. }
  150. Marker.prototype.draw = function (context) {
  151. context.save();
  152. context.beginPath();
  153. switch (this.type) {
  154. case 'circle':
  155. this._drawCircle(context);
  156. break;
  157. case 'ellipse':
  158. this._drawEllipse(context);
  159. break;
  160. default:
  161. break;
  162. }
  163. context.closePath();
  164. context.restore();
  165. this.size += this.speed;
  166. if (this.size > this.max) {
  167. this.size = 0;
  168. }
  169. };
  170. Marker.prototype._drawCircle = function (context) {
  171. var pixel = this.pixel||map.getPixelFromCoordinate(this.location);
  172. if(pixel) {
  173. context.strokeStyle = this.color;
  174. context.moveTo(pixel[0] + pixel.size, pixel[1]);
  175. context.arc(pixel[0], pixel[1], this.size, 0, Math.PI * 2);
  176. context.stroke();
  177. }
  178. };
  179. Marker.prototype._drawEllipse = function (context) {
  180. var pixel = this.pixel || map.getPixelFromCoordinate(this.location);
  181. if(pixel) {
  182. var x = pixel[0],
  183. y = pixel[1],
  184. w = this.size,
  185. h = this.size / 2,
  186. kappa = 0.5522848,
  187. // control point offset horizontal
  188. ox = w / 2 * kappa,
  189. // control point offset vertical
  190. oy = h / 2 * kappa,
  191. // x-start
  192. xs = x - w / 2,
  193. // y-start
  194. ys = y - h / 2,
  195. // x-end
  196. xe = x + w / 2,
  197. // y-end
  198. ye = y + h / 2;
  199. context.strokeStyle = this.color;
  200. context.moveTo(xs, y);
  201. context.bezierCurveTo(xs, y - oy, x - ox, ys, x, ys);
  202. context.bezierCurveTo(x + ox, ys, xe, y - oy, xe, y);
  203. context.bezierCurveTo(xe, y + oy, x + ox, ye, x, ye);
  204. context.bezierCurveTo(x - ox, ye, xs, y + oy, xs, y);
  205. context.stroke();
  206. }
  207. };
  208. return CanvasLayer;
  209. })));

 

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/728110
推荐阅读
  

闽ICP备14008679号