UNPKG

ol-ext-datatable

Version:
414 lines (373 loc) 12.9 kB
/* Copyright (c) 2015 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_style_RegularShape from 'ol/style/regularshape' import ol_style_Fill from 'ol/style/fill' import ol_style_Image from 'ol/style/image' import ol_color from 'ol/color' /** * @requires ol.style.Circle * @requires ol.structs.IHasChecksum */ /** * @classdesc * A marker style to use with font symbols. * * @constructor * @param {} options Options. * @param {number} options.glyph the glyph name or a char to display as symbol. * The name must be added using the {@link ol.style.FontSymbol.addDefs} function. * @param {string} options.form * none|circle|poi|bubble|marker|coma|shield|blazon|bookmark|hexagon|diamond|triangle|sign|ban|lozenge|square * a form that will enclose the glyph, default none * @param {number} options.radius * @param {number} options.rotation * @param {number} options.rotateWithView * @param {number} options.opacity * @param {number} options.fontSize, default 1 * @param {boolean} options.gradient true to display a gradient on the symbol * @param {_ol_style_Fill_} options.fill * @param {_ol_style_Stroke_} options.stroke * @extends {ol_style_RegularShape} * @implements {ol.structs.IHasChecksum} * @api */ var ol_style_FontSymbol = function(options) { options = options || {}; var strokeWidth = 0; if (options.stroke) strokeWidth = options.stroke.getWidth(); ol_style_RegularShape.call (this,{ radius: options.radius, fill:options.fill, rotation:options.rotation, rotateWithView: options.rotateWithView }); if (typeof(options.opacity)=="number") this.setOpacity(options.opacity); this.color_ = options.color; this.fontSize_ = options.fontSize || 1; this.stroke_ = options.stroke; this.fill_ = options.fill; this.radius_ = options.radius -strokeWidth; this.form_ = options.form || "none"; this.gradient_ = options.gradient; this.offset_ = [options.offsetX ? options.offsetX :0, options.offsetY ? options.offsetY :0]; this.glyph_ = this.getGlyph(options.glyph) || ""; this.renderMarker_(); }; ol.inherits(ol_style_FontSymbol, ol_style_RegularShape); /** Cool stuff to get the image symbol for a style */ ol_style_Image.prototype.getImagePNG = function() { var canvas = this.getImage(); if (canvas) { try { return canvas.toDataURL("image/png"); } catch(e) { return false; } } else return false; } /** * Font defs */ ol_style_FontSymbol.prototype.defs = { 'fonts':{}, 'glyphs':{} }; /** Static function : add new font defs * @param {String|Object} font the font desciption * @param {} glyphs a key / value list of glyph definitions. * Each key is the name of the glyph, * the value is an object that code the font, the caracter code, * the name and a search string for the glyph. */ ol_style_FontSymbol.addDefs = function(font, glyphs) { var thefont = font; if (typeof(font) == "string") thefont = {"font":font, "name":font, "copyright":"" }; if (!thefont.font || typeof(thefont.font) != "string") { console.log("bad font def"); return; } var fontname = thefont.font; ol_style_FontSymbol.prototype.defs.fonts[fontname] = thefont; for (var i in glyphs) { var g = glyphs[i]; if (typeof(g) == "string" && g.length==1) g = { char: g }; ol_style_FontSymbol.prototype.defs.glyphs[i] = { font: thefont.font, char: g.char || ""+String.fromCharCode(g.code) || "", theme: g.theme || thefont.name, name: g.name || i, search: g.search || "" }; } }; /** * Clones the style. * @return {ol_style_FontSymbol} */ ol_style_FontSymbol.prototype.clone = function() { var g = new ol_style_FontSymbol( { glyph: "", color: this.color_, fontSize: this.fontSize_, stroke: this.stroke_, fill: this.fill_, radius: this.radius_ + (this.stroke_ ? this.stroke_.getWidth():0), form: this.form_, gradient: this.gradient_, offsetX: this.offset_[0], offsetY: this.offset_[1], opacity: this.getOpacity(), rotation: this.getRotation(), rotateWithView: this.getRotateWithView() }); g.setScale(this.getScale()); g.glyph_ = this.glyph_; g.renderMarker_(); return g; }; /** * Get the fill style for the symbol. * @return {ol_style_Fill} Fill style. * @api */ ol_style_FontSymbol.prototype.getFill = function() { return this.fill_; }; /** * Get the stroke style for the symbol. * @return {_ol_style_Stroke_} Stroke style. * @api */ ol_style_FontSymbol.prototype.getStroke = function() { return this.stroke_; }; /** * Get the glyph definition for the symbol. * @param {string|undefined} name a glyph name to get the definition, default return the glyph definition for the style. * @return {_ol_style_Stroke_} Stroke style. * @api */ ol_style_FontSymbol.prototype.getGlyph = function(name) { if (name) return ol_style_FontSymbol.prototype.defs.glyphs[name] || { "font":"none","char":name.charAt(0),"theme":"none","name":"none", "search":""}; else return this.glyph_; }; /** * Get the glyph name. * @return {string} the name * @api */ ol_style_FontSymbol.prototype.getGlyphName = function() { for (var i in ol_style_FontSymbol.prototype.defs.glyphs) { if (ol_style_FontSymbol.prototype.defs.glyphs[i] === this.glyph_) return i; } return ""; }; /** * Get the stroke style for the symbol. * @return {_ol_style_Stroke_} Stroke style. * @api */ ol_style_FontSymbol.prototype.getFontInfo = function(glyph) { return ol_style_FontSymbol.prototype.defs.fonts[glyph.font]; } /** @private */ ol_style_FontSymbol.prototype.renderMarker_ = function(atlasManager) { var strokeStyle; var strokeWidth = 0; if (this.stroke_) { strokeStyle = ol_color.asString(this.stroke_.getColor()); strokeWidth = this.stroke_.getWidth(); } // no atlas manager is used, create a new canvas var canvas = this.getImage(); //console.log(this.getImage().width+" / "+(2 * (this.radius_ + strokeWidth) + 1)); /** @type {ol_style_FontSymbol.RenderOptions} */ var renderOptions = { strokeStyle: strokeStyle, strokeWidth: strokeWidth, size: canvas.width, }; // draw the circle on the canvas var context = (canvas.getContext('2d')); context.clearRect(0, 0, canvas.width, canvas.height); this.drawMarker_(renderOptions, context, 0, 0); // Set Anchor var a = this.getAnchor(); a[0] = canvas.width / 2 - this.offset_[0]; a[1] = canvas.width / 2 - this.offset_[1]; //this.createMarkerHitDetectionCanvas_(renderOptions); }; /** * @private * @param {ol_style_FontSymbol.RenderOptions} renderOptions * @param {CanvasRenderingContext2D} context */ ol_style_FontSymbol.prototype.drawPath_ = function(renderOptions, context) { var s = 2*this.radius_+renderOptions.strokeWidth+1; var w = renderOptions.strokeWidth/2; var c = renderOptions.size / 2; // Transfo to place the glyph at the right place var transfo = { fac:1, posX:renderOptions.size / 2, posY:renderOptions.size / 2 }; context.lineJoin = 'round'; context.beginPath(); // Draw the path with the form switch (this.form_) { case "none": transfo.fac=1; break; case "circle": case "ban": context.arc ( c, c, s/2, 0, 2 * Math.PI, true); break; case "poi": context.arc ( c, c -0.4*this.radius_, 0.6*this.radius_, 0.15*Math.PI, 0.85*Math.PI, true); context.lineTo ( c-0.89*0.05*s, (0.95+0.45*0.05)*s+w); context.arc ( c, 0.95*s+w, 0.05*s, 0.85*Math.PI, 0.15*Math.PI, true); transfo = { fac:0.45, posX:c, posY:c -0.35*this.radius_ }; break; case "bubble": context.arc ( c, c -0.2*this.radius_, 0.8*this.radius_, 0.4*Math.PI, 0.6*Math.PI, true); context.lineTo ( 0.5*s+w, s+w); transfo = { fac:0.7, posX:c, posY:c -0.2*this.radius_ }; break; case "marker": context.arc ( c, c -0.2*this.radius_, 0.8*this.radius_, 0.25*Math.PI, 0.75*Math.PI, true); context.lineTo ( 0.5*s+w, s+w); transfo = { fac:0.7, posX: c, posY: c -0.2*this.radius_ }; break; case "coma": /* context.arc( renderOptions.size / 2, renderOptions.size / 2 +0.2*this.radius_, 0.8*this.radius_, 0.5*Math.PI, 0, true); context.arc( renderOptions.size / 2, renderOptions.size / 2 -0.2*this.radius_, 0.8*this.radius_, 0, 0.5*Math.PI, true); */ context.moveTo ( c + 0.8*this.radius_, c -0.2*this.radius_); context.quadraticCurveTo ( 0.95*s+w, 0.75*s+w, 0.5*s+w, s+w); context.arc ( c, c -0.2*this.radius_, 0.8*this.radius_, 0.45*Math.PI, 0, false); transfo = { fac:0.7, posX: c, posY: c -0.2*this.radius_ }; break; default: { var pts; switch (this.form_) { case "shield": pts = [ 0.05,0, 0.95,0, 0.95,0.8, 0.5,1, 0.05,0.8, 0.05,0 ]; transfo.posY = 0.45*s+w ; break; case "blazon": pts = [ 0.1,0, 0.9,0, 0.9,0.8, 0.6,0.8, 0.5,1, 0.4,0.8, 0.1,0.8, 0.1,0 ]; transfo.fac = 0.8; transfo.posY = 0.4*s+w ; break; case "bookmark": pts = [ 0.05,0, 0.95,0, 0.95,1, 0.5,0.8, 0.05,1, 0.05,0 ]; transfo.fac = 0.9; transfo.posY = 0.4*s+w ; break; case "hexagon": pts = [ 0.05,0.2, 0.5,0, 0.95,0.2, 0.95,0.8, 0.5,1, 0.05,0.8, 0.05,0.2 ]; transfo.fac = 0.9; transfo.posY = 0.5*s+w ; break; case "diamond": pts = [ 0.25,0, 0.75,0, 1,0.2, 1,0.4, 0.5,1, 0,0.4, 0,0.2, 0.25,0 ]; transfo.fac = 0.75 ; transfo.posY = 0.35*s+w ; break; case "triangle": pts = [ 0,0, 1,0, 0.5,1, 0,0 ]; transfo.fac = 0.6 ; transfo.posY = 0.3*s+w ; break; case "sign": pts = [ 0.5,0.05, 1,0.95, 0,0.95, 0.5,0.05 ]; transfo.fac = 0.7 ; transfo.posY = 0.65*s+w ; break; case "lozenge": pts = [ 0.5,0, 1,0.5, 0.5,1, 0,0.5, 0.5,0 ]; transfo.fac = 0.7; break; case "square": default: pts = [ 0,0, 1,0, 1,1, 0,1, 0,0 ]; break; } for (var i=0; i<pts.length; i+=2) context.lineTo ( pts[i]*s+w, pts[i+1]*s+w); } } context.closePath(); return transfo; } /** * @private * @param {ol_style_FontSymbol.RenderOptions} renderOptions * @param {CanvasRenderingContext2D} context * @param {number} x The origin for the symbol (x). * @param {number} y The origin for the symbol (y). */ ol_style_FontSymbol.prototype.drawMarker_ = function(renderOptions, context, x, y) { var fcolor = this.fill_ ? this.fill_.getColor() : "#000"; var scolor = this.stroke_ ? this.stroke_.getColor() : "#000"; if (this.form_ == "none" && this.stroke_ && this.fill_) { scolor = this.fill_.getColor(); fcolor = this.stroke_.getColor(); } // reset transform context.setTransform(1, 0, 0, 1, 0, 0); // then move to (x, y) context.translate(x, y); var tr = this.drawPath_(renderOptions, context); if (this.fill_) { if (this.gradient_ && this.form_!="none") { var grd = context.createLinearGradient(0,0,renderOptions.size/2,renderOptions.size); grd.addColorStop (1, ol_color.asString(fcolor)); grd.addColorStop (0, ol_color.asString(scolor)); context.fillStyle = grd; } else context.fillStyle = ol_color.asString(fcolor); context.fill(); } if (this.stroke_ && renderOptions.strokeWidth) { context.strokeStyle = renderOptions.strokeStyle; context.lineWidth = renderOptions.strokeWidth; context.stroke(); } // Draw the symbol if (this.glyph_.char) { context.font = (2*tr.fac*(this.radius_)*this.fontSize_)+"px "+this.glyph_.font; context.strokeStyle = context.fillStyle; context.lineWidth = renderOptions.strokeWidth * (this.form_ == "none" ? 2:1); context.fillStyle = ol_color.asString(this.color_ || scolor); context.textAlign = "center"; context.textBaseline = "middle"; var t = this.glyph_.char; if (renderOptions.strokeWidth && scolor!="transparent") context.strokeText(t, tr.posX, tr.posY); context.fillText(t, tr.posX, tr.posY); } if (this.form_=="ban" && this.stroke_ && renderOptions.strokeWidth) { context.strokeStyle = renderOptions.strokeStyle; context.lineWidth = renderOptions.strokeWidth; var r = this.radius_ + renderOptions.strokeWidth; var d = this.radius_ * Math.cos(Math.PI/4); context.moveTo(r + d, r - d); context.lineTo(r - d, r + d); context.stroke(); } }; /** * @inheritDoc */ ol_style_FontSymbol.prototype.getChecksum = function() { var strokeChecksum = (this.stroke_!==null) ? this.stroke_.getChecksum() : '-'; var fillChecksum = (this.fill_!==null) ? this.fill_.getChecksum() : '-'; var recalculate = (this.checksums_===null) || (strokeChecksum != this.checksums_[1] || fillChecksum != this.checksums_[2] || this.radius_ != this.checksums_[3] || this.form_+"-"+this.glyphs_ != this.checksums_[4]); if (recalculate) { var checksum = 'c' + strokeChecksum + fillChecksum + ((this.radius_ !== void 0) ? this.radius_.toString() : '-') + this.form_+"-"+this.glyphs_; this.checksums_ = [checksum, strokeChecksum, fillChecksum, this.radius_, this.form_+"-"+this.glyphs_]; } return this.checksums_[0]; }; export default ol_style_FontSymbol