UNPKG

kmap-ui

Version:

A components of zmap base on vue2.X

299 lines (272 loc) 10.2 kB
import ol_ext_inherits from '../util/ext' import {DEVICE_PIXEL_RATIO as ol_has_DEVICE_PIXEL_RATIO} from 'ol/has' import ol_control_Control from 'ol/control/Control' import {toContext as ol_render_toContext} from 'ol/render' import ol_Feature from 'ol/Feature' import ol_geom_Point from 'ol/geom/Point' import ol_geom_LineString from 'ol/geom/LineString'; import ol_geom_Polygon from 'ol/geom/Polygon' import {extend as ol_extent_extend} from 'ol/extent' /** Create a legend for styles * @constructor * @fires select * @param {*} options * @param {String} options.className class of the control * @param {String} options.title Legend title * @param {ol.size | undefined} options.size Size of the symboles in the legend, default [40, 25] * @param {int | undefined} options.margin Size of the symbole's margin, default 10 * @param {boolean | undefined} options.collapsed Specify if attributions should be collapsed at startup. Default is true. * @param {boolean | undefined} options.collapsible Specify if attributions can be collapsed, default true. * @param {Element | string | undefined} options.target Specify a target if you want the control to be rendered outside of the map's viewport. * @param { ol.style.Style | Array<ol.style.Style> | ol.StyleFunction | undefined } options.style a style or a style function to use with features * @extends {ol_control_Control} */ var ol_control_Legend = function(options) { options = options || {}; var element = document.createElement('div'); if (options.target) { element.className = options.className || "ol-legend"; } else { element.className = (options.className || "ol-legend") +" ol-unselectable ol-control ol-collapsed" +(options.collapsible===false ? ' ol-uncollapsible': ''); // Show on click var button = document.createElement('button'); button.setAttribute('type', 'button'); button.addEventListener('click', function() { element.classList.toggle('ol-collapsed'); }); element.appendChild(button); // Hide on click button = document.createElement('button'); button.setAttribute('type', 'button'); button.className = 'ol-closebox'; button.addEventListener('click', function() { element.classList.toggle('ol-collapsed'); }); element.appendChild(button); } // The legend this._imgElement = document.createElement('div'); this._imgElement.className = 'ol-legendImg'; element.appendChild(this._imgElement); this._tableElement = document.createElement('ul'); element.appendChild(this._tableElement); ol_control_Control.call(this, { element: element, target: options.target }); this._rows = []; this.set('size', options.size || [40, 25]); this.set('margin', options.margin===0 ? 0 : options.margin || 10); this.set('title', options.title || ''); // Set the style this._style = options.style; if (options.collapsed===false) this.show(); this.refresh(); }; ol_ext_inherits(ol_control_Legend, ol_control_Control); /** Set the style * @param { ol.style.Style | Array<ol.style.Style> | ol.StyleFunction | undefined } style a style or a style function to use with features */ ol_control_Legend.prototype.setStyle = function(style) { this._style = style; this.refresh(); }; /** Add a new row to the legend * * You can provide in options: * - a feature width a style * - or a feature that will use the legend style function * - or properties ans a geometry type that will use the legend style function * - or a style and a geometry type * @param {*} options a list of parameters * @param {ol.Feature} options.feature a feature to draw * @param {ol.style.Style} options.style the style to use if no feature is provided * @param {*} options.properties properties to use with a style function * @param {string} options.typeGeom type geom to draw with the style or the properties */ ol_control_Legend.prototype.addRow = function(row) { this._rows.push(row||{}); this.refresh(); }; /** Remove a row from the legend * @param {int} index */ ol_control_Legend.prototype.removeRow = function(index) { this._rows.splice(index,1); this.refresh(); }; /** Get a legend row * @param {int} index * @return {*} */ ol_control_Legend.prototype.getRow = function(index) { return this._rows[index]; }; /** Get a legend row * @return {int} */ ol_control_Legend.prototype.getLength = function() { return this._rows.length; }; /** Refresh the legend */ ol_control_Legend.prototype.refresh = function() { var self = this; var table = this._tableElement table.innerHTML = ''; var width = this.get('size')[0] + 2*this.get('margin'); var height = this.get('size')[1] + 2*this.get('margin'); // Add a new row function addRow(str, title, r, i){ var row = document.createElement('li'); row.style.height = height + 'px'; row.addEventListener('click', function() { self.dispatchEvent({ type:'select', title: str, row: r, index: i }); }); var col = document.createElement('div'); row.appendChild(col); col.style.height = height + 'px'; col = document.createElement('div'); if (title) { row.className = 'ol-title'; } else { col.style.paddingLeft = width + 'px'; } col.innerHTML = str || ''; row.appendChild(col); table.appendChild(row); } if (this.get('title')) { addRow(this.get('title'), true, {}, -1); } var canvas = document.createElement('canvas'); canvas.width = 5*width; canvas.height = (this._rows.length+1) * height * ol_has_DEVICE_PIXEL_RATIO; this._imgElement.innerHTML = ''; this._imgElement.appendChild(canvas); this._imgElement.style.height = (this._rows.length+1)*height + 'px'; for (var i=0, r; r = this._rows[i]; i++) { addRow(r.title, false, r, i); canvas = this.getStyleImage(r, canvas, i+(this.get('title')?1:0)); } }; /** Show control */ ol_control_Legend.prototype.show = function() { this.element.classList.remove('ol-collapsed'); }; /** Hide control */ ol_control_Legend.prototype.hide = function() { this.element.classList.add('ol-collapsed'); }; /** Toggle control */ ol_control_Legend.prototype.toggle = function() { this.element.classList.toggle('ol-collapsed'); }; /** Get the image for a style * You can provide in options: * - a feature width a style * - or a feature that will use the legend style function * - or properties and a geometry type that will use the legend style function * - or a style and a geometry type * @param {*} options * @param {ol.Feature} options.feature a feature to draw * @param {ol.style.Style} options.style the style to use if no feature is provided * @param {*} options.properties properties to use with a style function * @param {string} options.typeGeom type geom to draw with the style or the properties * @param {Canvas|undefined} canvas a canvas to draw in * @param {int|undefined} row row number to draw in canvas * @return {CanvasElement} */ ol_control_Legend.prototype.getStyleImage = function(options, theCanvas, row) { options = options || {}; var size = this.get('size'); var width = size[0] + 2*this.get('margin'); var height = size[1] + 2*this.get('margin'); var canvas = theCanvas; var ratio = ol_has_DEVICE_PIXEL_RATIO; if (!canvas) { canvas = document.createElement('canvas'); canvas.width = width * ratio; canvas.height = height * ratio; } var ctx = canvas.getContext('2d'); ctx.save(); var vectorContext = ol_render_toContext(ctx); var typeGeom = options.typeGeom; var style; var feature = options.feature; if (!feature && options.properties && typeGeom) { if (/Point/.test(typeGeom)) feature = new ol_Feature(new ol_geom_Point([0,0])); else if (/LineString/.test(typeGeom)) feature = new ol_Feature(new ol_geom_LineString([0,0])); else feature = new ol_Feature(new ol_geom_Polygon([[0,0]])); feature.setProperties(options.properties); } if (feature) { style = feature.getStyle(); if (typeof(style)==='function') style = style(feature); if (!style) { style = typeof(this._style) === 'function' ? this._style(feature) : this._style || []; } typeGeom = feature.getGeometry().getType(); } else { style = options.style; } if (!(style instanceof Array)) style = [style]; var cx = width/2; var cy = height/2; var sx = size[0]/2; var sy = size[1]/2; var i, s; // Get point offset if (typeGeom === 'Point') { var extent = null; for (i=0; s= style[i]; i++) { var img = s.getImage(); if (img && img.getAnchor) { var anchor = img.getAnchor(); var si = img.getSize(); var dx = anchor[0] - si[0]; var dy = anchor[1] - si[1]; if (!extent) { extent = [dx, dy, dx+si[0], dy+si[1]]; } else { ol_extent_extend(extent, [dx, dy, dx+si[0], dy+si[1]]); } } } if (extent) { cx = cx + (extent[2] + extent[0])/2; cy = cy + (extent[3] + extent[1])/2; } } // Draw image cy += (theCanvas ? row*height : 0); for (i=0; s= style[i]; i++) { vectorContext.setStyle(s); switch (typeGeom) { case ol_geom_Point: case 'Point': vectorContext.drawGeometry(new ol_geom_Point([cx, cy])); break; case ol_geom_LineString: case 'LineString': ctx.save(); ctx.rect(this.get('margin') * ratio, 0, size[0] * ratio, canvas.height); ctx.clip(); vectorContext.drawGeometry(new ol_geom_LineString([[cx-sx, cy], [cx+sx, cy]])); ctx.restore(); break; case ol_geom_Polygon: case 'Polygon': vectorContext.drawGeometry(new ol_geom_Polygon([[[cx-sx, cy-sy], [cx+sx, cy-sy], [cx+sx, cy+sy], [cx-sx, cy+sy], [cx-sx, cy-sy]]])); break; } } ctx.restore(); return canvas; }; export default ol_control_Legend