效果图:
leaflet 有imageOverlay图层根据两个点坐标生成图像,但体验感不太好,设计上传一张图片后,常常不能对齐,就尝试自己封装个图层。如上图所示,图片有两种方式,一种方式是使用canvas createPattern方法平铺纹理,另一种是通过canvas clip剪切方法,
这个方法对图片尺寸有些要求,图片尺寸必须和裁剪的矩形宽高成比例且不能有空白区域,不然不能对齐。
代码如下:
<!DOCTYPE html> <html> <head> <title>Leaflet debug page</title> <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9+580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ==" crossorigin="" /> <script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ==" crossorigin=""></script> <script src="../dist/leaflet.polygonImage.js"></script> <script src="./data/index.js"></script> </head> <body> <div id="map" style="width: 1920px; height: 1080px; border: 1px solid #ccc"></div> <script> var map = L.map('map').setView([37, 102], 4.2); L.tileLayer('http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}', { attribution: '' }).addTo(map); let coordinates = L.geoJSON(boundaries).getLayers()[0]._latlngs; var polygonimg = L.polygonimg(coordinates, { img: "./img/map.png", // 裁剪图片 // img: "./img/img1.png", // 平铺纹理图片 type: "clip", //clip repeat }).addTo(map); </script> </body> </html>leaflet.polygonImage.js:
(function (root, plugin) { /** * UMD wrapper. * When used directly in the Browser it expects Leaflet to be globally * available as `L`. The plugin then adds itself to Leaflet. * When used as a CommonJS module (e.g. with browserify) only the plugin * factory gets exported, so one hast to call the factory manually and pass * Leaflet as the only parameter. * @see {@link https://github.com/umdjs/umd} */ if (typeof define === 'function' && define.amd) { define(['leaflet'], plugin); } else if (typeof exports === 'object') { module.exports = plugin; } else { plugin(root.L); } }(this, function (L) { // Plugin is already added to Leaflet if (L.Polygonimg) { return L; } /** * Core renderer. * @constructor * @param {HTMLElement | string} canvas - <canvas> element or its id * to initialize the instance on. */ var Polygonimg = function (canvas) { if (!(this instanceof Polygonimg)) { return new Polygonimg(canvas); } this._canvas = canvas = typeof canvas === 'string' ? document.getElementById(canvas) : canvas; this._ctx = canvas.getContext('2d'); this._width = canvas.width; this._height = canvas.height; this._data = []; this._img = ''; this._type = "cover" // this.draw(); }; Polygonimg.prototype = { /** * Sets the width of the canvas. Used when clearing the canvas. * @param {number} width - Width of the canvas. */ width: function (width) { this._width = width; return this; }, /** * Sets the height of the canvas. Used when clearing the canvas. * @param {number} height - Height of the canvas. */ height: function (height) { this._height = height; return this; }, img: function (img) { this._img = img; return this; }, type: function (type) { this._type = type; return this }, size: function (size) { this._size = size; return this; }, bounds: function (bounds) { this._bounds = bounds; return this; }, /** * Sets the data that gets drawn on the canvas. * @param {(Path|Path[])} data - A single path or an array of paths. */ data: function (data) { this._data = data; return this; }, /** * Draws the currently set paths. */ draw: function () { console.log(this) this._ctx.globalCompositeOperation = 'source-over'; this._ctx.lineCap = 'round'; var ctx = this._ctx; var data = this._data; let that = this; var bounds = this._bounds; var size = this._size; var canvasImage = new Image(); //赋值图片地址 canvasImage.src = this._img; //开始一个新的绘制路径 // this._ctx.beginPath(); //设置路径起点坐标 canvasImage.onload = function () { if (that._type == 'clip') { //保存画布当前状态 ctx.save(); //开始一个新的绘制路径 ctx.beginPath(); //设置路径起点坐标 for (let i = 0; i < data.length; i++) { for (let j = 0; j < data[i].length; j++) { if (j == 0) { ctx.moveTo(data[i][j].x, data[i][j].y); } else { ctx.lineTo(data[i][j].x, data[i][j].y); } } } //先关闭绘制路径。注意,此时将会使用直线连接当前端点和起始端点。 ctx.closePath(); // 剪切,将在面积内的图片显示 ctx.clip(); ctx.drawImage(this, bounds.min.x, bounds.min.y, size.x, size.y); ctx.restore(); } else if (that._type == 'repeat') { //开始一个新的绘制路径 ctx.beginPath(); //设置路径起点坐标 for (let i = 0; i < data.length; i++) { for (let j = 0; j < data[i].length; j++) { if (j == 0) { ctx.moveTo(data[i][j].x, data[i][j].y); } else { ctx.lineTo(data[i][j].x, data[i][j].y); } } } //先关闭绘制路径。注意,此时将会使用直线连接当前端点和起始端点。 ctx.closePath(); ctx.stroke(); //使用createPattern平铺 ctx.fillStyle = ctx.createPattern(canvasImage, 'repeat') ctx.fill() } }; }, }; var Renderer = L.Canvas.extend({ _initContainer: function () { L.Canvas.prototype._initContainer.call(this); this._polygonimg = new Polygonimg(this._container); }, _update: function () { L.Canvas.prototype._update.call(this); this._polygonimg.width(this._container.width); this._polygonimg.height(this._container.height); }, _updatePoly: function (layer) { if (!this._drawing) { return; } var parts = layer._parts; // console.log(layer, 'parts') var bounds = layer._rawPxBounds var size = bounds.getSize() if (!parts.length) { return; } this._updateOptions(layer); this._polygonimg .data(parts) .bounds(bounds) .size(size) .draw(); }, _updateOptions: function (layer) { if (layer.options.img) { this._polygonimg.img(layer.options.img); } if (layer.options.type) { this._polygonimg.type(layer.options.type); } } }); var renderer = function (options) { return L.Browser.canvas ? new Renderer(options) : null; }; L.Polygonimg = L.Polygon.extend({ statics: { Renderer: Renderer, renderer: renderer }, options: { renderer: renderer(), } }); L.polygonimg = function (latlngs, options) { return new L.Polygonimg(latlngs, options); }; return L; }));
data为leaflet多边形数据,平铺纹理我想通过修改canvas像素点位置来自定义纹理的宽高,奈何能力有限没搞出来,感兴趣的朋友欢迎交流。
标签:function,canvas,多边形,填充,ctx,leaflet,._,return,data From: https://www.cnblogs.com/hardmeng/p/17099473.html