UNPKG

ol-ext-datatable

Version:
294 lines (261 loc) 9.68 kB
/* Copyright (c) 2017 Jean-Marc VIGLINO, released under the CeCILL-B license (French BSD license) (http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt). */ import ol from 'ol' import ol_control_Control from 'ol/control/control' import ol_proj_Projection from 'ol/proj/projection' import ol_style_Style from 'ol/style/style' import ol_style_Stroke from 'ol/style/stroke' import ol_style_Fill from 'ol/style/fill' import ol_style_Text from 'ol/style/text' import ol_proj from 'ol/proj' /** * Draw a graticule on the map. * * @constructor * @extends {ol_control_Control} * @param {Object=} _ol_control_ options. * - projection {ol.projectionLike} projection to use for the graticule, default EPSG:4326 * - maxResolution {number} max resolution to display the graticule * - style {ol_style_Style} Style to use for drawing the graticule, default black. * - step {number} step beetween lines (in proj units), default 1 * - stepCoord {number} show a coord every stepCoord, default 1 * - spacing {number} spacing beetween lines (in px), default 40px * - borderWidth {number} width of the border (in px), default 5px * - margin {number} margin of the border (in px), default 0px */ var ol_control_Graticule = function(options) { var self = this; if (!options) options = {}; // Initialize parent var elt = document.createElement("div"); elt.className = "ol-graticule ol-unselectable ol-hidden"; ol_control_Control.call(this, { element: elt }); this.set('projection', options.projection || 'EPSG:4326'); // Use to limit calculation var p = new ol_proj_Projection({code:this.get('projection')}); var m = p.getMetersPerUnit(); this.fac = 1; while (m/this.fac>10) { this.fac *= 10; } this.fac = 10000/this.fac; this.set('maxResolution', options.maxResolution || Infinity); this.set('step', options.step || 0.1); this.set('stepCoord', options.stepCoord || 1); this.set('spacing', options.spacing || 40); this.set('margin', options.margin || 0); this.set('borderWidth', options.borderWidth || 5); this.set('stroke', options.stroke!==false); this.formatCoord = options.formatCoord || function(c){return c;}; if (options.style instanceof ol_style_Style) this.style = options.style; else this.style = new ol_style_Style( { stroke: new ol_style_Stroke({ color:"#000", width:1 }), fill: new ol_style_Fill({ color: "#fff" }), text: new ol_style_Text( { stroke: new ol_style_Stroke({ color:"#fff", width:2 }), fill: new ol_style_Fill({ color:"#000" }), }) }); }; ol.inherits(ol_control_Graticule, 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_Graticule.prototype.setMap = function (map) { var oldmap = this.getMap(); if (oldmap) oldmap.un('postcompose', this.drawGraticule_, this); ol_control_Control.prototype.setMap.call(this, map); if (oldmap) oldmap.renderSync(); // Get change (new layer added or removed) if (map) map.on('postcompose', this.drawGraticule_, this); }; ol_control_Graticule.prototype.setStyle = function (style) { this.style = style; }; ol_control_Graticule.prototype.getStyle = function (style) { return style; }; ol_control_Graticule.prototype.drawGraticule_ = function (e) { if (this.get('maxResolution')<e.frameState.viewState.resolution) return; var ctx = e.context; var canvas = ctx.canvas; var ratio = e.frameState.pixelRatio; var w = canvas.width/ratio; var h = canvas.height/ratio; var proj = this.get('projection'); var map = this.getMap(); var bbox = [ map.getCoordinateFromPixel([0,0]), map.getCoordinateFromPixel([w,0]), map.getCoordinateFromPixel([w,h]), map.getCoordinateFromPixel([0,h]) ]; var xmax = -Infinity; var xmin = Infinity; var ymax = -Infinity; var ymin = Infinity; for (var i=0, c; c=bbox[i]; i++) { bbox[i] = ol_proj.transform (c, map.getView().getProjection(), proj); xmax = Math.max (xmax, bbox[i][0]); xmin = Math.min (xmin, bbox[i][0]); ymax = Math.max (ymax, bbox[i][1]); ymin = Math.min (ymin, bbox[i][1]); } var spacing = this.get('spacing'); var step = this.get('step'); var step2 = this.get('stepCoord'); var borderWidth = this.get('borderWidth'); var margin = this.get('margin'); // Limit max line draw var ds = (xmax-xmin)/step*spacing; if (ds>w) { var dt = Math.round((xmax-xmin)/w*spacing /step); step *= dt; if (step>this.fac) step = Math.round(step/this.fac)*this.fac; } xmin = (Math.floor(xmin/step))*step -step; ymin = (Math.floor(ymin/step))*step -step; xmax = (Math.floor(xmax/step))*step +2*step; ymax = (Math.floor(ymax/step))*step +2*step; var extent = ol_proj.get(proj).getExtent(); if (extent) { if (xmin < extent[0]) xmin = extent[0]; if (ymin < extent[1]) ymin = extent[1]; if (xmax > extent[2]) xmax = extent[2]+step; if (ymax > extent[3]) ymax = extent[3]+step; } var hasLines = this.style.getStroke() && this.get("stroke"); var hasText = this.style.getText(); var hasBorder = this.style.getFill(); ctx.save(); ctx.scale(ratio,ratio); ctx.beginPath(); ctx.rect(margin, margin, w-2*margin, h-2*margin); ctx.clip(); ctx.beginPath(); var txt = {top:[],left:[],bottom:[], right:[]}; for (var x=xmin; x<xmax; x += step) { var p0 = ol_proj.transform ([x, ymin], proj, map.getView().getProjection()); p0 = map.getPixelFromCoordinate(p0); if (hasLines) ctx.moveTo(p0[0], p0[1]); var p = p0; for (var y=ymin+step; y<=ymax; y+=step) { var p1 = ol_proj.transform ([x, y], proj, map.getView().getProjection()); p1 = map.getPixelFromCoordinate(p1); if (hasLines) ctx.lineTo(p1[0], p1[1]); if (p[1]>0 && p1[1]<0) txt.top.push([x, p]); if (p[1]>h && p1[1]<h) txt.bottom.push([x,p]); p = p1; } } for (var y=ymin; y<ymax; y += step) { var p0 = ol_proj.transform ([xmin, y], proj, map.getView().getProjection()); p0 = map.getPixelFromCoordinate(p0); if (hasLines) ctx.moveTo(p0[0], p0[1]); var p = p0; for (var x=xmin+step; x<=xmax; x+=step) { var p1 = ol_proj.transform ([x, y], proj, map.getView().getProjection()); p1 = map.getPixelFromCoordinate(p1); if (hasLines) ctx.lineTo(p1[0], p1[1]); if (p[0]<0 && p1[0]>0) txt.left.push([y,p]); if (p[0]<w && p1[0]>w) txt.right.push([y,p]); p = p1; } } if (hasLines) { ctx.strokeStyle = this.style.getStroke().getColor(); ctx.lineWidth = this.style.getStroke().getWidth(); ctx.stroke(); } // Draw text if (hasText) { ctx.fillStyle = this.style.getText().getFill().getColor(); ctx.strokeStyle = this.style.getText().getStroke().getColor(); ctx.lineWidth = this.style.getText().getStroke().getWidth(); ctx.textAlign = 'center'; ctx.textBaseline = 'hanging'; var tf; var offset = (hasBorder ? borderWidth : 0) + margin + 2; for (var i=0, t; t = txt.top[i]; i++) if (!(Math.round(t[0]/this.get('step'))%step2)) { tf = this.formatCoord(t[0]); ctx.strokeText(tf, t[1][0], offset); ctx.fillText(tf, t[1][0], offset); } ctx.textBaseline = 'alphabetic'; for (var i=0, t; t = txt.bottom[i]; i++) if (!(Math.round(t[0]/this.get('step'))%step2)) { tf = this.formatCoord(t[0]); ctx.strokeText(tf, t[1][0], h-offset); ctx.fillText(tf, t[1][0], h-offset); } ctx.textBaseline = 'middle'; ctx.textAlign = 'left'; for (var i=0, t; t = txt.left[i]; i++) if (!(Math.round(t[0]/this.get('step'))%step2)) { tf = this.formatCoord(t[0]); ctx.strokeText(tf, offset, t[1][1]); ctx.fillText(tf, offset, t[1][1]); } ctx.textAlign = 'right'; for (var i=0, t; t = txt.right[i]; i++) if (!(Math.round(t[0]/this.get('step'))%step2)) { tf = this.formatCoord(t[0]); ctx.strokeText(tf, w-offset, t[1][1]); ctx.fillText(tf, w-offset, t[1][1]); } } // Draw border if (hasBorder) { var fillColor = this.style.getFill().getColor(); var color, stroke; if (stroke = this.style.getStroke()) { color = this.style.getStroke().getColor(); } else { color = fillColor; fillColor = "#fff"; } ctx.strokeStyle = color; ctx.lineWidth = stroke ? stroke.getWidth() : 1; // for (var i=1; i<txt.top.length; i++) { ctx.beginPath(); ctx.rect(txt.top[i-1][1][0], margin, txt.top[i][1][0]-txt.top[i-1][1][0], borderWidth); ctx.fillStyle = Math.round(txt.top[i][0]/step)%2 ? color: fillColor; ctx.fill(); ctx.stroke(); } for (var i=1; i<txt.bottom.length; i++) { ctx.beginPath(); ctx.rect(txt.bottom[i-1][1][0], h-borderWidth-margin, txt.bottom[i][1][0]-txt.bottom[i-1][1][0], borderWidth); ctx.fillStyle = Math.round(txt.bottom[i][0]/step)%2 ? color: fillColor; ctx.fill(); ctx.stroke(); } for (var i=1; i<txt.left.length; i++) { ctx.beginPath(); ctx.rect(margin, txt.left[i-1][1][1], borderWidth, txt.left[i][1][1]-txt.left[i-1][1][1]); ctx.fillStyle = Math.round(txt.left[i][0]/step)%2 ? color: fillColor; ctx.fill(); ctx.stroke(); } for (var i=1; i<txt.right.length; i++) { ctx.beginPath(); ctx.rect(w-borderWidth-margin, txt.right[i-1][1][1], borderWidth, txt.right[i][1][1]-txt.right[i-1][1][1]); ctx.fillStyle = Math.round(txt.right[i][0]/step)%2 ? color: fillColor; ctx.fill(); ctx.stroke(); } ctx.beginPath(); ctx.fillStyle = color; ctx.rect(margin,margin, borderWidth, borderWidth); ctx.rect(margin,h-borderWidth-margin, borderWidth,borderWidth); ctx.rect(w-borderWidth-margin,margin, borderWidth, borderWidth); ctx.rect(w-borderWidth-margin,h-borderWidth-margin, borderWidth,borderWidth); ctx.fill(); } ctx.restore(); }; export default ol_control_Graticule