UNPKG

kmap-ui

Version:

A components of zmap base on vue2.X

328 lines (297 loc) 10.3 kB
import ol_ext_inherits from '../util/ext' import {unByKey as ol_Observable_unByKey} from 'ol/Observable' import ol_control_Control from 'ol/control/Control' import ol_ext_element from '../util/element' import ol_ext_getMapCanvas from '../util/getMapCanvas' /** Image line control * * @constructor * @extends {ol.control.Control} * @fires select * @fires collapse * @param {Object=} options Control options. * @param {String} options.className class of the control * @param {ol.source.Vector} options.source a vector source that contains the images * @param {function} options.getImage a function that gets a feature and return the image url, default return the img propertie * @param {function} options.getTitle a function that gets a feature and return the title, default return an empty string * @param {boolean} options.collapsed the line is collapse, default false * @param {boolean} options.collapsible the line is collapsible, default false * @param {number} options.maxFeatures the maximum image element in the line, default 100 * @param {boolean} options.hover select image on hover, default false * @param {string|boolean} options.linkColor link color or false if no link, default false */ var ol_control_Imageline = function(options) { var element = ol_ext_element.create('DIV', { className: (options.className || '') + ' ol-imageline' + (options.target ? '': ' ol-unselectable ol-control') + (options.collapsed && options.collapsible ? 'ol-collapsed' : '') + ('ontouchstart' in window ? ' ol-touch' : '') }); if (!options.target && options.collapsible) { ol_ext_element.create('BUTTON', { type: 'button', click: function() { this.toggle(); }.bind(this), parent: element }); } // Source this._source = options.source; // Initialize ol_control_Control.call(this, { element: element, target: options.target }); // Scroll imageline this._setScrolling(); this._scrolldiv.addEventListener("scroll", function() { if (this.getMap()) this.getMap().render(); }.bind(this)); // Parameters if (typeof(options.getImage)==='function') this._getImage = options.getImage; if (typeof(options.getTitle)==='function') this._getTitle = options.getTitle; this.set('maxFeatures', options.maxFeatures || 100); this.set('linkColor', options.linkColor || false); this.set('hover', options.hover || false); this.set('useExtent', options.useExtent || false); this.refresh(); }; ol_ext_inherits(ol_control_Imageline, ol_control_Control); /** * Remove the control from its current map and attach it to the new map. * @param {ol.Map} map Map. * @api stable */ ol_control_Imageline.prototype.setMap = function (map) { if (this._listener) { this._listener.forEach(function(l) { ol_Observable_unByKey(l); }.bind(this)); } this._listener = null; ol_control_Control.prototype.setMap.call(this, map); if (map) { this._listener = [ map.on('postcompose', this._drawLink.bind(this)), map.on('moveend', function() { if (this.get('useExtent')) this.refresh(); }.bind(this)) ] } }; /** Set useExtent param and refresh the line * @param {boolean} b */ ol_control_Imageline.prototype.useExtent = function(b) { this.set('useExtent', b); this.refresh(); }; /** Is the line collapsed * @return {boolean} */ ol_control_Imageline.prototype.isCollapsed = function() { return this.element.classList.contains('ol-collapsed'); }; /** Collapse the line * @param {boolean} b */ ol_control_Imageline.prototype.collapse = function(b) { if (b) this.element.classList.add('ol-collapsed'); else this.element.classList.remove('ol-collapsed'); if (this.getMap()) { setTimeout ( function() { this.getMap().render(); }.bind(this), this.isCollapsed() ? 0 : 250); } this.dispatchEvent({ type: 'collapse', collapsed: this.isCollapsed() }); }; /** Collapse the line */ ol_control_Imageline.prototype.toggle = function() { this.element.classList.toggle('ol-collapsed'); if (this.getMap()) { setTimeout ( function() { this.getMap().render(); }.bind(this), this.isCollapsed() ? 0 : 250); } this.dispatchEvent({ type: 'collapse', collapsed: this.isCollapsed() }); }; /** Default function to get an image of a feature * @param {ol.Feature} f * @private */ ol_control_Imageline.prototype._getImage = function(f) { return f.get('img'); }; /** Default function to get an image title * @param {ol.Feature} f * @private */ ol_control_Imageline.prototype._getTitle = function(/* f */) { return ''; }; /** * Get features * @return {Array<ol.Feature>} */ ol_control_Imageline.prototype.getFeatures = function() { var map = this.getMap(); if (!this.get('useExtent') || !map) { return this._source.getFeatures(); } else { var extent = map.getView().calculateExtent(map.getSize()); return this._source.getFeaturesInExtent(extent); } }; /** Set element scrolling with a acceleration effect on desktop * (on mobile it uses the scroll of the browser) * @private */ ol_control_Imageline.prototype._setScrolling = function() { var elt = this._scrolldiv = ol_ext_element.create('DIV', { parent: this.element }); ol_ext_element.scrollDiv(elt, { // Prevent selection when moving onmove: function(b) { this._moving=b; }.bind(this) }); }; /** * Refresh the imageline with new data */ ol_control_Imageline.prototype.refresh = function() { this._scrolldiv.innerHTML = ''; var features = this.getFeatures(); var current = this._select ? this._select.feature : null; if (this._select) this._select.elt = null; this._iline = []; if (this.getMap()) this.getMap().render(); // Add a new image var addImage = function(f) { if (this._getImage(f)) { var img = ol_ext_element.create('DIV', { className: 'ol-image', parent: this._scrolldiv }); ol_ext_element.create('IMG', { src: this._getImage(f), parent: img }).addEventListener('load', function(){ this.classList.add('ol-loaded'); }); ol_ext_element.create('SPAN', { html: this._getTitle(f), parent: img }); // Current image var sel = { elt: img, feature: f }; // On click > dispatch event img.addEventListener('click', function(){ if (!this._moving) { this.dispatchEvent({type: 'select', feature: f }); this._scrolldiv.scrollLeft = img.offsetLeft + ol_ext_element.getStyle(img, 'width')/2 - ol_ext_element.getStyle(this.element, 'width')/2; if (this._select) this._select.elt.classList.remove('select'); this._select = sel; this._select.elt.classList.add('select'); } }.bind(this)); // Show link img.addEventListener('mouseover', function(e) { if (this.get('hover')) { if (this._select) this._select.elt.classList.remove('select'); this._select = sel; this._select.elt.classList.add('select'); this.getMap().render(); e.stopPropagation(); } }.bind(this)); // Remove link img.addEventListener('mouseout', function(e) { if (this.get('hover')) { if (this._select) this._select.elt.classList.remove('select'); this._select = false; this.getMap().render(); e.stopPropagation(); } }.bind(this)); // Prevent image dragging img.ondragstart = function(){ return false; }; // Add image this._iline.push(sel); if (current===f) { this._select = sel; sel.elt.classList.add('select'); } } }.bind(this); // Add images var nb = this.get('maxFeatures'); for (var i=0, f; f=features[i]; i++) { if (nb--<0) break; addImage(f); } // Add the selected one if (this._select && this._select.feature && !this._select.elt) { addImage(this._select.feature); } }; /** Center image line on a feature * @param {ol.feature} feature * @param {boolean} scroll scroll the line to center on the image, default true * @api */ ol_control_Imageline.prototype.select = function(feature, scroll) { this._select = false; // Find the image this._iline.forEach(function (f) { if (f.feature === feature) { f.elt.classList.add('select'); this._select = f; if (scroll!==false) { this._scrolldiv.scrollLeft = f.elt.offsetLeft + ol_ext_element.getStyle(f.elt, 'width')/2 - ol_ext_element.getStyle(this.element, 'width')/2; } } else { f.elt.classList.remove('select'); } }.bind(this)); }; /** Draw link on the map * @private */ ol_control_Imageline.prototype._drawLink = function(e) { if (!this.get('linkColor') | this.isCollapsed()) return; var map = this.getMap(); if (map && this._select && this._select.elt) { var ctx = e.context || ol_ext_getMapCanvas(this.getMap()).getContext('2d'); var ratio = e.frameState.pixelRatio; var pt = [ this._select.elt.offsetLeft - this._scrolldiv.scrollLeft + ol_ext_element.getStyle(this._select.elt, 'width')/2, parseFloat(ol_ext_element.getStyle(this.element, 'top')) || this.getMap().getSize()[1] ]; var geom = this._select.feature.getGeometry().getFirstCoordinate(); geom = this.getMap().getPixelFromCoordinate(geom); ctx.save(); ctx.fillStyle = this.get('linkColor'); ctx.beginPath(); if (geom[0]>pt[0]) { ctx.moveTo((pt[0]-5)*ratio, pt[1]*ratio); ctx.lineTo((pt[0]+5)*ratio, (pt[1]+5)*ratio); } else { ctx.moveTo((pt[0]-5)*ratio, (pt[1]+5)*ratio); ctx.lineTo((pt[0]+5)*ratio, pt[1]*ratio); } ctx.lineTo(geom[0]*ratio, geom[1]*ratio); ctx.fill(); ctx.restore(); } }; export default ol_control_Imageline