diff --git a/Gruntfile.js b/Gruntfile.js index 74d6194..a580b37 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -16,6 +16,7 @@ module.exports = function(grunt){ 'src/sketch/d3.mappu.Sketch.js', 'src/layer/d3.mappu.Layer.js', 'src/layer/d3.mappu.VectorLayer.js', + 'src/layer/d3.mappu.VectorCanvasLayer.js', 'src/layer/d3.mappu.VectorTileLayer.js', 'src/layer/d3.mappu.TWKBLayer.js', 'src/layer/d3.mappu.RasterDivLayer.js', diff --git a/dist/d3.mappu.js b/dist/d3.mappu.js index 3bd4b75..fe74c9b 100644 --- a/dist/d3.mappu.js +++ b/dist/d3.mappu.js @@ -332,6 +332,9 @@ d3_mappu_Map = function( id, config ) { else if (d.type == 'vector' || d.type == 'vectortile'){ return document.createElementNS("http://www.w3.org/2000/svg", 'svg'); } + else if (d.type == 'canvas'){ + return document.createElement('canvas'); + } else throw 'No valid type (' + d.type + ' )specified for layer'; }) .attr( 'id', function( d ) { return d.id;} ) @@ -915,7 +918,7 @@ d3_mappu_Layer = function(name, config){ map.orderLayers(); layer.draw(); var event = new CustomEvent("layeradded", { "detail": layer}); - layer.map.mapdiv.dispatchEvent(event); + layer.map.mapdiv.dispatchEvent(event); }; layer._onRemove = function(){ //Removes the layer from the map object var event = new CustomEvent("layerremoved"); @@ -999,6 +1002,7 @@ d3_mappu_Layer = function(name, config){ if (style){ for (var key in style) { entity.select('path').style(key, style[key]); + entity.select('circle').style(key, style[key]); } } @@ -1006,6 +1010,7 @@ d3_mappu_Layer = function(name, config){ if (d.style){ for (var key in d.style) { entity.select('path').style(key, d.style[key]); + entity.select('circle').style(key, d.style[key]); } } @@ -1030,24 +1035,37 @@ d3_mappu_Layer = function(name, config){ if (d.geometry.type == 'Point' && d.style){ var x = project(d.geometry.coordinates)[0]; var y = project(d.geometry.coordinates)[1]; - var width = d.style && d.style.width ? d.style.width : - (style.width ? style.width : 32); - var height = d.style && d.style.height ? d.style.height : - (style.height ? style.height : 37); - var img = d3.select(this).append('g').append("image") - .attr("width", width) - .attr("height", height) - //.attr("x",x-12.5) //No need setting x and y, since it's reset later - //.attr("y",y-25) - .style('pointer-events','visiblepainted') - .attr("xlink:href", function(d){ - if (d.style['iconimg']){ - return 'data:image/' + d.style['iconimg_encoding'] +','+ d.style['iconimg_bytearray']; - } - else if (d.style['marker-url']){ - return d.style['marker-url']; - }; - }); + + if (d.style['iconimg_encoding'] || d.style['marker-url']){ + var width = d.style && d.style.width ? d.style.width : + (style.width ? style.width : 32); + var height = d.style && d.style.height ? d.style.height : + (style.height ? style.height : 37); + var img = d3.select(this).append('g').append("image") + .attr("width", width) + .attr("height", height) + .style('pointer-events','visiblepainted') + .attr("xlink:href", function(d){ + if (d.style['iconimg']){ + return 'data:image/' + d.style['iconimg_encoding'] +','+ d.style['iconimg_bytearray']; + } + else if (d.style['marker-url']){ + return d.style['marker-url']; + }; + }); + } + else { + d3.select(this).append("circle") + .attr("cx", x) + .attr("cy", y) + .attr("r", function(d){ + return style.radius ? style.radius : + (d.style && d.style.radius) ? d.style.radius : + 5; + }) + .classed(name, true) + .style('pointer-events','visiblepainted');//make clickable + } } else { if (d.geometry.type == 'Polygon' && !ringIsClockwise(d.geometry.coordinates[0])){ @@ -1113,6 +1131,7 @@ d3_mappu_Layer = function(name, config){ newentity.each(function(){ d3.select(this).select('path').on(d.event, d.action); d3.select(this).select('image').on(d.event, d.action); + d3.select(this).select('circle').on(d.event, d.action); }); }); } @@ -1130,6 +1149,11 @@ d3_mappu_Layer = function(name, config){ if (config.reproject){//the slow way var project = layer.map.projection; entities.select('path').transition().duration(duration).attr("d", _path); + entities.select('circle').transition().duration(duration).each(function(d){ + var x = project(d.geometry.coordinates)[0]; + var y = project(d.geometry.coordinates)[1]; + d3.select(this).attr('cx',x).attr('cy',y); + }); entities.select('image').transition().duration(duration).each(function(d){ //TODO: create something nice customizable for widh-height calculations var width = d.style && d.style.width ? d.style.width : @@ -1176,9 +1200,9 @@ d3_mappu_Layer = function(name, config){ if (labelStyle){ for (var key in labelStyle) { d3.select(this).selectAll('.vectorLabel').style(key, labelStyle[key]); - //shadowtext only sensitive to the opacity style - if (key == 'opacity'){ - d3.select(this).select('.shadowtext').style('opacity', labelStyle[key]); + //shadowtext only sensitive to the opacity style or font params + if (key == 'opacity' || key.indexOf('font') > -1 ){ + d3.select(this).select('.shadowtext').style(key, labelStyle[key]); } } } @@ -1252,6 +1276,181 @@ d3_mappu_Layer = function(name, config){ d3_mappu_VectorLayer.prototype = Object.create(d3_mappu_Layer.prototype); + // マップ +; /** + + **/ + d3.mappu.VectorCanvasLayer = function(name, config){ + return d3_mappu_VectorCanvasLayer(name, config); + }; + + d3_mappu_VectorCanvasLayer = function(name, config) { + /*Work in progress for webworker + var builder = new Worker("../src/layer/builder.js"); + builder.onmessage = function(e) { + console.log('Message received from worker', e.data.aap); + }; + var obj = {project:'noot'}; + builder.postMessage(obj); + console.log('Message posted to worker'); + */ + config = config || {}; + d3_mappu_Layer.call(this,name, config); + var layer = d3_mappu_Layer(name, config); + layer.type = 'canvas'; + var _data = []; + layer.zindex = 100; //vectors always on top + var _duration = config.duration || 0; + var _path; + var _projection; + var _style = config.style || {}; + var labelStyle = config.labelStyle || {}; + var _events = config.events; + + /* exposed properties*/ + Object.defineProperty(layer, 'data', { + get: function() { + return _data; + }, + set: function(array) { + _data = array; + draw(false); + } + }); + + Object.defineProperty(layer, 'style', { + get: function() { + return _style; + }, + set: function(val) { + _style = val; + layer.drawboard.selectAll('.tile').remove(); + layer.refresh(0); + } + }); + + + Object.defineProperty(layer, 'events', { + get: function() { + return _events; + }, + set: function(array) { + _events = array; + } + }); + + + + //Function taken from terraformer + function ringIsClockwise(ringToTest) { + var total = 0,i = 0; + var rLength = ringToTest.length; + var pt1 = ringToTest[i]; + var pt2; + for (i; i < rLength - 1; i++) { + pt2 = ringToTest[i + 1]; + total += (pt2[0] - pt1[0]) * (pt2[1] + pt1[1]); + pt1 = pt2; + } + return (total >= 0); + } + + function setStyle(d){ + var self = this; + var entity = d3.select(this); + //Do generic layer style + if (style){ + for (var key in style) { + entity.select('path').style(key, style[key]); + entity.select('circle').style(key, style[key]); + } + } + + //Now use per-feature styling + if (d.style){ + for (var key in d.style) { + entity.select('path').style(key, d.style[key]); + entity.select('circle').style(key, d.style[key]); + } + } + + + + if (d._selected){ + //make halo around entity to show as selected + entity + .append('path').attr("d", _path) + .style('stroke', 'none') + .style('fill', 'red') + .classed('halo', true); + } + else { + entity.selectAll('.halo').remove(); + } + } + //Build is only called on entry + function build(d){ + if (d.geometry.type == 'Polygon' && !ringIsClockwise(d.geometry.coordinates[0])){ + d.geometry.coordinates[0].reverse(); + } + var project = _projection; + _projection = d3.geoMercator(); + _path = d3.geoPath().projection(_projection); + var canvas = layer.drawboard; + var context = canvas.node().getContext("2d"); + _path.context(context); + context.save(); + context.beginPath(); + _path(d); + context.fillStyle = typeof(_style.fill)=='function'?_style.fill(d.properties[_style.column]):_style.fill; + context.fill(); + context.closePath(); + context.lineWidth = 1; + context.restore(); + } + + + + var draw = function(rebuild){ + if (config.reproject){ + _projection = layer.map.projection; + _path = d3.geoPath() + .projection(_projection) + } + else { + //TODO: this should be depending on the projection given ins the config, no? + _projection = d3.geoMercator() + .scale(1 / 2 / Math.PI) + .translate([0, 0]); + _path = d3.geoPath() + .projection(_projection); + } + var drawboard = layer.drawboard; + if (rebuild){ + //drawboard.selectAll('.entity').remove(); + } + _data.forEach(build); + }; + + function refresh() { + var canvas = layer.drawboard; + canvas.save(); + canvas.clearRect(0, 0, width, height); + canvas.translate(d3.event.translate[0], d3.event.translate[1]); + canvas.scale(d3.event.scale, d3.event.scale); + draw(); + canvas.restore(); + } + + + /* Exposed functions*/ + layer.refresh = refresh; + layer.draw = draw; + return layer; + }; + + d3_mappu_VectorCanvasLayer.prototype = Object.create(d3_mappu_Layer.prototype); + // マップ ; /** @@ -1304,7 +1503,7 @@ d3_mappu_Layer = function(name, config){ if (style){ for (var key in style) { if (key == 'fill' && d.geometry.type.indexOf('Polygon') == -1){ - style[key] = 'none'; + entity.style(key, 'none'); } entity.style(key, style[key]); } @@ -1314,7 +1513,7 @@ d3_mappu_Layer = function(name, config){ if (d.style){ for (var key in d.style) { if (key == 'fill' && d.geometry.type.indexOf('Polygon') == -1){ - d.style[key] = 'none'; + entity.style(key, 'none'); } entity.style(key, d.style[key]); } @@ -1322,9 +1521,9 @@ d3_mappu_Layer = function(name, config){ } function tileurl(d){ - var x = d[0], - y = d[1], - z = d[2]; + var x = d.x, + y = d.y, + z = d.z; if (tms) { y = Math.pow(2, z) - y - 1; //TMS reverse for Y-down } @@ -1347,66 +1546,107 @@ d3_mappu_Layer = function(name, config){ _projection = d3.geoMercator(); _path = d3.geoPath().projection(_projection); - this._xhr = d3.json(url, function(error, json) { - if (error) throw error; - - var k = Math.pow(2, d[2]) * 256; // size of the world in pixels - - _path.projection() - .translate([k / 2 - d[0] *256, k / 2 - d[1] *256]) // [0�,0�] in pixels - .scale(k / 2 / Math.PI); - /* TT: WORK IN PROGRESS FOR ALREADY PROJECTED DATA - function matrix(a, b, c, d, tx, ty) { - return d3.geoTransform({ - point: function(x, y) { - this.stream.point(a * x + b * y + tx, c * x + d * y + ty); + /* Test with MVT */ + if (url.indexOf('.mvt') > -1){ + this._xhr = d3.request(url).responseType('arraybuffer').get(function(error, json) { + var layers = [layername]; + var vtile = new VectorTile( new pbf( new Uint8Array(json.response) ) ); + var extents = 4096; + var data = {}; + + for (var key in vtile.layers) { + data[key] = vtile.layers[layername].toGeoJSON(); } - }); - } - var tx = 0; //k / 2 - d[0] *256; - var ty = 0 ; //k / 2 - d[0] *256; - - - var scale = 1/256; - var path = d3.geoPath() - .projection(matrix(scale, 0, 0, scale, tx, ty)); - /* END OF WORK IN PROGRESS */ - - if (json.objects){ - var features = topojson.feature(json,json.objects[layername]).features; - } else if (json.features){ - var features = json.features; - } else { - throw "Can't work with this vectortile data"; - } - - if (typeof _filter === 'function'){ - features = features.filter(_filter); - } - - var entities = tile.selectAll('path').data(features, function(d){ - return d.id; + if (!data[layername]){return;} + var features = data[layername].features; + var entities = tile.selectAll('path').data(features, function(d){ + return d.id; + }); + var tile_projection = d3.geoTransform({ + point: function(x, y) { + // Sometimes PBF points in a mixed-geometry layer are corrupted + if(!isNaN(y)){ + x = x/extents*256; + y = y/extents*256; + } else { + y = x[0][1]/extents * 256; + x = x[0][0]/extents * 256; + } + this.stream.point(x, y); + } + }); + var tilePath = d3.geoPath() + .projection(tile_projection) + var newentity = entities.enter().append('path') + .attr('id',function(d){ + return 'entity'+ d.properties.id; + }) + .attr('class',function(d){return d.properties.kind;}) + .attr("d", tilePath) + .style('pointer-events','visiblepainted');//make clickable; + newentity.each(setStyle); + entities.exit().remove(); + + // Add events from config + if (_events){ + _events.forEach(function(d){ + newentity.each(function(){ + d3.select(this).on(d.event, d.action); + }); + }); + } }); - - var newentity = entities.enter().append('path') - .attr('id',function(d){ - return 'entity'+ d.properties.id; - }) - .attr('class',function(d){return d.properties.kind;}) - .attr("d", _path) - .style('pointer-events','visiblepainted');//make clickable; - newentity.each(setStyle); - entities.exit().remove(); - - // Add events from config - if (_events){ - _events.forEach(function(d){ - newentity.each(function(){ - d3.select(this).on(d.event, d.action); - }); - }); - } - }); + } + + + /* END of test with mvt */ + else { + + this._xhr = d3.json(url, function(error, json) { + if (error) throw error; + + var k = Math.pow(2, d[2]) * 256; // size of the world in pixels + + _path.projection() + .translate([k / 2 - d[0] *256, k / 2 - d[1] *256]) // [0�,0�] in pixels + .scale(k / 2 / Math.PI); + + if (json.objects){ + var features = topojson.feature(json,json.objects[layername]).features; + } else if (json.features){ + var features = json.features; + } else { + throw "Can't work with this vectortile data"; + } + + if (typeof _filter === 'function'){ + features = features.filter(_filter); + } + + var entities = tile.selectAll('path').data(features, function(d){ + return d.id; + }); + + var newentity = entities.enter().append('path') + .attr('id',function(d){ + return 'entity'+ d.properties.id; + }) + .attr('class',function(d){return d.properties.kind;}) + .attr("d", _path) + .style('pointer-events','visiblepainted');//make clickable; + newentity.each(setStyle); + entities.exit().remove(); + + // Add events from config + if (_events){ + _events.forEach(function(d){ + newentity.each(function(){ + d3.select(this).on(d.event, d.action); + }); + }); + } + }); + } } @@ -1699,9 +1939,11 @@ d3_mappu_Layer = function(name, config){ var _options = config; //Te be leaflet compatible in g-layercatalogus layer.options = _options; layer.visibility = layer.visible; //leaflet compat + var _opacity = config.opacity; var _layers = config.layers; var _duration = 0; var _cqlfilter = null; + var _time = null; Object.defineProperty(layer, 'url', { get: function() { @@ -1709,6 +1951,7 @@ d3_mappu_Layer = function(name, config){ }, set: function(val) { _url = val; + clear(); draw(); } }); @@ -1719,6 +1962,7 @@ d3_mappu_Layer = function(name, config){ }, set: function(val) { _layers = val; + clear(); draw(); } }); @@ -1729,19 +1973,29 @@ d3_mappu_Layer = function(name, config){ }, set: function(val) { _cqlfilter = val; + clear(); draw(); } }); - //Clear all tiles - layer.clear = function(){ - }; + Object.defineProperty(layer, 'time', { + get: function() { + return _time; + }, + set: function(val) { + _time = val; + clear(); + draw(); + } + }); + + var getbbox = function(d){ - var numtiles = 2 << (d[2]-1); + var numtiles = 2 << (d.z-1); var tilesize = (20037508.34 * 2) / (numtiles); - var x = -20037508.34 + (d[0] * tilesize); - var y = 20037508.34 - ((d[1]+1) * tilesize);//shift 1 down, because we want LOWER left + var x = -20037508.34 + (d.x * tilesize); + var y = 20037508.34 - ((d.y+1) * tilesize);//shift 1 down, because we want LOWER left var bbox = x + ","+ y + "," + (x + tilesize) + "," + (y + tilesize); return bbox; }; @@ -1751,14 +2005,14 @@ d3_mappu_Layer = function(name, config){ if (_ogc_type == 'tms') { url = _url .replace('{s}',["a", "b", "c", "d"][Math.random() * 3 | 0]) - .replace('{z}',d[2]) - .replace('{x}',d[0]) - .replace('{y}',d[1]) + .replace('{z}',d.z) + .replace('{x}',d.x) + .replace('{y}',d.y) //FIXME: why are these curly brackets killed when used with polymer? .replace('%7Bs%7D',["a", "b", "c", "d"][Math.random() * 3 | 0]) - .replace('%7Bz%7D',d[2]) - .replace('%7Bx%7D',d[0]) - .replace('%7By%7D',d[1]); + .replace('%7Bz%7D',d.z) + .replace('%7Bx%7D',d.x) + .replace('%7By%7D',d.y); } else if (_ogc_type == 'wmts'){ //TODO: working on this @@ -1778,7 +2032,7 @@ d3_mappu_Layer = function(name, config){ } url = _url + "&layer=" + _layers + - "&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&STYLE=default&TILEMATRIXSET=nltilingschema&TILEMATRIX="+d[2]+ "&TILEROW="+d[0]+"&TILECOL="+d[1]+"&FORMAT=image%2Fpng"; + "&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&STYLE=default&TILEMATRIXSET=nltilingschema&TILEMATRIX="+d.z+ "&TILEROW="+d.x+"&TILECOL="+d.y+"&FORMAT=image%2Fpng"; } else if (_ogc_type == 'wms'){ if (_url.indexOf('?') < 0){ @@ -1790,10 +2044,13 @@ d3_mappu_Layer = function(name, config){ "&bbox=" + bbox + "&styles=" + _style + "&layers=" + _layers + - "&service=WMS&version=1.1.0&request=GetMap&tiled=true&width=256&height=256&srs=EPSG:3857&transparent=TRUE&format=image%2Fpng"; + "&service=WMS&version=1.3.0&request=GetMap&CRS=EPSG:3857&tiled=true&width=256&height=256&srs=EPSG:3857&transparent=TRUE&format=image%2Fpng"; if (_cqlfilter){ url += '&cql_filter='+_cqlfilter; - } + } + if (_time){ + url += '&time='+_time; + } } else if(_ogc_type == 'esri'){ if (_url.indexOf('?') < 0){ @@ -1880,19 +2137,25 @@ d3_mappu_Layer = function(name, config){ } }; function matrix3d(scale, translate) { - var k = scale / 256, r = scale % 1 ? Number : Math.round; - return "matrix3d(" + [k, 0, 0, 0, 0, k, 0, 0, 0, 0, k, 0, r(translate[0] * scale), r(translate[1] * scale), 0, 1 ] + ")"; - } - + var k = scale / 256, r = scale % 1 ? Number : Math.round; + /* + return "matrix3d(" + [ + k, 0, 0, 0, + 0, k, 0, 0, + 0, 0, k, 0, + r(translate[0] * scale), r(translate[1] * scale), 0, 1 + ] + ")";*/ + return "matrix(" + [k,0,0,k,r(translate[0] * scale), r(translate[1] * scale)]+")"; + } //Draw the tiles (based on data-update) var draw = function(){ var drawboard = layer.drawboard; var tiles = layer.map.tiles; var image = drawboard - .style("transform", matrix3d(tiles.scale, tiles.translate)) + .style("transform", matrix3d(tiles.scale, tiles.translate)) .selectAll(".tile") - .data(tiles, function(d) { return d; }); + .data(tiles, function(d) { return [d.tx, d.ty, d.z]; }); var imageEnter = image.enter(); if (layer.visible){ @@ -1903,9 +2166,15 @@ d3_mappu_Layer = function(name, config){ .style('width','256px') .style('height','256px') .style('position','absolute') - .attr('opacity', this.opacity) - .style("left", function(d) { return (d[0] << 8) + "px"; }) - .style("top", function(d) { return (d[1] << 8) + "px"; }) + .style('opacity', _opacity) + .style("left", function(d) { + //return (d.x << 8) + "px"; + return d.tx + "px"; + }) + .style("top", function(d) { + //return (d.y << 8) + "px"; + return d.ty + "px"; + }) //TODO: working on this .on('click', getFeatureInfo); } @@ -1917,9 +2186,14 @@ d3_mappu_Layer = function(name, config){ var refresh = function(){ draw(); - layer.drawboard.style('opacity', this.opacity).style('display',this.visible?'block':'none'); + layer.drawboard.style('opacity', _opacity).style('display',this.visible?'block':'none'); + }; + //Clear all tiles + var clear = function(){ + layer.drawboard.selectAll('.tile').remove(); }; + layer.clear = clear; layer.refresh = refresh; layer.draw = draw; return layer; diff --git a/dist/d3.mappu.min.js b/dist/d3.mappu.min.js index 5db9547..f332e8c 100644 --- a/dist/d3.mappu.min.js +++ b/dist/d3.mappu.min.js @@ -1,2 +1,3 @@ -/*! d3.mappu VERSION: 0.0.1 06-02-2017 */ -!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g>1:-(a>>1)-1}c.ReadVarInt64=d,c.ReadVarSInt64=e,c.unzigzag=f},{}],3:[function(a,b,c){function d(a,b,c){c=c||Number.MAX_VALUE;for(var d={buffer:a,cursor:void 0===b?0:b,bufferLength:a.byteLength||a.length,refpoint:new Int32Array(4)},f=[],g=0;d.cursorg;){var h=e(d,c);h.length>0?f.push({type:d.type,offset:c>4);a.type=15&c,a.factors=[],a.factors[0]=a.factors[1]=Math.pow(10,g),c=a.buffer[a.cursor],a.cursor++,a.has_bbox=1&c,a.has_size=(2&c)>>1,a.has_idlist=(4&c)>>2,a.is_empty=(16&c)>>4;var h=(8&c)>>3;if(h){var i=a.buffer[a.cursor];a.cursor++,d=1&i,f=(2&i)>>1;var j=(28&i)>>2,k=(224&i)>>5;d&&(a.factors[2]=Math.pow(10,j)),f&&(a.factors[2+d]=Math.pow(10,k)),a.has_z=d,a.has_m=f}var l=2+d+f;if(a.ndims=l,a.has_size&&(a.size=n(a)),a.has_bbox){for(var m=[],q=0;l-1>=q;q++){var r=o(a),s=r+o(a);m[q]=r,m[q+l]=s}a.bbox=m}return e(a,b)}function e(a,b){for(var c=a.type,d=0;dd;++d)b[d]=g(a);return b}function i(a,b){var c=a.type,d=n(a),e=[],f=[];a.has_idlist&&(f=l(a,d));for(var g=0;d>g;g++){var h=b(a);e.push(h)}return{type:c,ids:f,geoms:e}}function j(a,b){var c=a.type,e=n(a),f=[],g=[];a.has_idlist&&(g=l(a,e));for(var h=0;e>h&&b>h;h++){var i=d(a);f.push({type:a.type,coordinates:i})}return{type:c,ids:g,ndims:a.ndims,offset:bc;c++)for(d=0;e>d;d++)a.refpoint[d]+=o(a),g[e*c+d]=a.refpoint[d]/f[d];if(a.include_bbox&&!a.has_bbox)for(c=0;b>c;c++)for(d=0;e>d;d++){const h=g[d*e+c];ha.bbox.max[d]&&(a.bbox.max[d]=h)}return g}function l(a,b){const c=[];for(var d=0;b>d;d++)c.push(o(a));return c}var m=a("./constants"),n=a("./protobuf").ReadVarInt64,o=a("./protobuf").ReadVarSInt64,p=a("./protobuf").unzigzag;b.exports=d},{"./constants":1,"./protobuf":2}],5:[function(a,b,c){function d(a,b){return{type:l[a],coordinates:b}}function e(a,b,c,d){return{type:"Feature",id:c,geometry:m[a](b,d)}}function f(a,b,c,d){return b.map(function(b,f){return e(a,b,c?c[f]:void 0,d)})}function g(a,b,c){return a.map(function(a,d){return e(a.type,a.coordinates,b?b[d]:void 0,c)})}function h(a,b){for(var c=[],d=0,e=a.length;e>d;d+=b){for(var f=[],g=0;b>g;++g)f.push(a[d+g]);c.push(f)}return c}function i(a){for(var b={buffer:a,cursor:0,bufferLength:a.byteLength||a.length,refpoint:new Int32Array(4)},c=[];b.cursor=a&&a>=p||console.log("Zoomlevel exceeded",a,"Min:",p,"Max:",o)}}),Object.defineProperty(f,"minZoom",{get:function(){return p},set:function(a){p=a}}),Object.defineProperty(f,"maxZoom",{get:function(){return o},set:function(a){o=a}}),Object.defineProperty(f,"maxView",{get:function(){return q},set:function(a){q=a}}),Object.defineProperty(f,"projection",{get:function(){return m},set:function(a){m=a}}),Object.defineProperty(f,"extent",{get:function(){return k},set:function(a){k=a}}),Object.defineProperty(f,"tiles",{get:function(){return _tiles},set:function(){console.warn("No setting allowed for tile")}}),Object.defineProperty(f,"transform",{get:function(){return h},set:function(){console.warn("No setting allowed for transform")}}),Object.defineProperty(f,"zoombehaviour",{get:function(){return u},set:function(){console.warn("No setting allowed for zoombehaviour")}}),Object.defineProperty(f,"layers",{get:function(){return g},set:function(){console.warn("No setting allowed for layers")}});var w=function(a){if(!a.id)return console.warn("Not a valid layer. (No ID)"),!1;var b=g.indexOf(a);return b>-1&&g.splice(b,1),g.push(a),a._onAdd(f),f},x=function(a){var b=g.indexOf(a);return b>-1&&g.splice(b,1),y(),a._onRemove(f),f},y=function(){var a=d3.select(c).selectAll(".drawboard").data(g,function(a){return a.id});a.enter().append(function(a){if("raster"==a.type)return document.createElement("div");if("vector"==a.type||"vectortile"==a.type)return document.createElementNS("http://www.w3.org/2000/svg","svg");throw"No valid type ("+a.type+" )specified for layer"}).attr("id",function(a){return a.id}).style("position","absolute").style("pointer-events","none").classed("drawboard",!0).each(function(a){a.drawboard=d3.select(this),"vector"!=a.type&&"vectortile"!=a.type||a.drawboard.append("g")}),a.exit().remove(),a.sort(function(a,b){return a.zindex-b.zindex})};return f.addLayer=w,f.removeLayer=x,f.orderLayers=y,f.redraw=r,f.resize=s,f},d3.mappu=d3.mappu||{},d3.mappu.Sketch=function(a,b){return d3_mappu_Sketch(a,b)},d3_mappu_Sketch=function(a,b){function c(){p.selectAll(".sketch").remove(),p.append("path").attr("d",function(){return q(u)}).classed("sketch",!0).style("stroke","blue").style("fill",function(){return"LineString"==t?"none":"blue"}).style("fill-opacity",.4)}function d(a){var b=d3.mouse(this);s.push(o.projection.invert(b)),u.geometry.type="LineString",u.geometry.coordinates=s,c()}function e(){var a=d3.mouse(this);s=r.invert(a),u.id=(new Date).getTime().toString(),u.geometry.coordinates=s,c(),x()}function f(){s.pop(),s.pop(),u.geometry.type="LineString",u.geometry.coordinates=s,u.id=(new Date).getTime().toString(),c(),x()}function g(){u.geometry.type="Polygon",s.pop(),s.pop(),s.push(s[0]),u.geometry.coordinates=[s],u.id=(new Date).getTime().toString(),c(),x()}function h(){var a=u.geometry.coordinates.length,b=d3.mouse(this),d=o.projection.invert(b);a>=1&&(1==a?s[a]=d:s[a-1]=d,u.geometry.coordinates=s,c())}function i(a){d3.event.sourceEvent.stopPropagation(),d3.select(this).classed("dragging",!0)}function j(a){var b=d3.mouse(o.mapdiv);d3.select(this).attr("cx",b[0]).attr("cy",b[1]),"Polygon"==t?d3.select(this).classed("sketchPointInter")?(d3.select(this).classed("sketchPointInter",!1).classed("sketchPoint",!0),a.index+1==u.geometry.coordinates[0].length?u.geometry.coordinates[0].splice(1,0,a):u.geometry.coordinates[0].splice(a.index+1,0,a)):(u.geometry.coordinates[0][a.index]=r.invert(b),0===a.index&&(u.geometry.coordinates[0].pop(),u.geometry.coordinates[0].push(r.invert(b))),a.index+1==u.geometry.coordinates[0].length&&(u.geometry.coordinates[0][0]=r.invert(b))):"LineString"==t?d3.select(this).classed("sketchPointInter")?(d3.select(this).classed("sketchPointInter",!1).classed("sketchPoint",!0),u.geometry.coordinates.splice(a.index+1,0,a)):u.geometry.coordinates[a.index]=r.invert(b):"Point"==t&&(u.geometry.coordinates=r.invert(b)),l()}function k(a){d3.select(this).classed("dragging",!1),l()}function l(){if(p.selectAll(".sketch").remove(),p.append("path").attr("d",function(){return q(u)}).classed("sketch",!0).style("stroke","red").style("fill",function(){return"LineString"==t?"none":"red"}).style("fill-opacity",.4),"Point"==t)var a=[u.geometry.coordinates],b=[];else{switch(t){case"Polygon":var a=u.geometry.coordinates[0];break;case"LineString":var a=u.geometry.coordinates;break;default:console.warn(t," not supported")}a.forEach(function(a,b){a.index=b,a.fid=a.id});var b=a.map(function(b,c){if(c+11&&f(a),window.setTimeout(function(){v=0},300)})):"Polygon"==t&&(u.style.fill="blue",u.style.stroke="blue",d3.select(o.mapdiv).on("mousedown",d),d3.select(o.mapdiv).on("mousemove",h),d3.select(o.mapdiv).on("mousedown.doublemousedown",function(a){v++,v>1&&g(a),window.setTimeout(function(){v=0},300)}),d3.select(o.mapdiv).on("touchstart",function(a){pressTimer=window.setTimeout(function(){g()},500)}).on("touchmove",function(a,b){console.log(a,b)}).on("touchend",function(){clearTimeout(pressTimer)}))})},x=function(){self.resolve(u),E()},y=d3.drag().subject(function(a){return a}).on("start",i).on("drag",j).on("end",k),z=function(a){return p=d3.select(o.mapdiv).append("svg").attr("id","sketch").style("position","absolute").attr("width",o.mapdiv.clientWidth).attr("height",o.mapdiv.clientHeight).append("g"),new Promise(function(b,c){self.resolve=b,event.stopPropagation(),d3.select(o.mapdiv).on("click",function(){l(),B()}),u=a,t=a.geometry.type,l()})},A=function(){},B=function(){self.resolve(u),E()},C=function(a){return new Promise(function(b,c){b(a),E()})},D=function(){},E=function(){p&&(p.selectAll(".sketch").remove(),p.selectAll(".sketchPoint").remove(),p.selectAll(".sketchPointInter").remove(),d3.select(o.mapdiv).select("#sketch").remove(),u=null,s=[],d3.select(o.mapdiv).on("mousemove",null),d3.select(o.mapdiv).on("click",null),d3.select(o.mapdiv).on("mousedown",null),d3.select(o.mapdiv).on("doublemousedown",null),d3.select(o.mapdiv).on("touchstart",null),d3.select(o.mapdiv).on("touchend",null))};return n.draw=w,n.startEdit=A,n.startRemove=D,n.remove=C,n.finish=E,n.edit=z,n.addTo=m,n},d3.mappu.Layer=function(a,b){return d3_mappu_Layer(a,b)},d3_mappu_Layer=function(a,b){b=b||{};var c,d={},e=d3.mappu.util.createID(),f=a,g=1;g=b.opacity||1;var h=!0;"boolean"!=typeof b.visible&&"true"!=b.visible&&"false"!=b.visible||(h=b.visible);var i=0,j=function(){},k=function(){},l=function(){},m=function(a){d.zindex=a},n=function(a){return a.addLayer(d),a.resize(),d};return Object.defineProperty(d,"id",{get:function(){return e},set:function(){console.warn("setting ID not allowed for layer")}}),Object.defineProperty(d,"name",{get:function(){return f},set:function(a){f=a}}),Object.defineProperty(d,"map",{get:function(){return c},set:function(a){c=a}}),Object.defineProperty(d,"opacity",{get:function(){return g},set:function(a){g=a,d.refresh(0)}}),Object.defineProperty(d,"visible",{get:function(){return h},set:function(a){h=a,d.draw(!0),d.refresh(0)}}),Object.defineProperty(d,"zindex",{get:function(){return i},set:function(a){i=a,d.map&&d.map.orderLayers()}}),d.refresh=j,d.moveUp=k,d.moveDown=l,d.addTo=n,d.setZIndex=m,d._onAdd=function(a){c=a,a.orderLayers(),d.draw();var b=new CustomEvent("layeradded",{detail:d});d.map.mapdiv.dispatchEvent(b)},d._onRemove=function(){var a=new CustomEvent("layerremoved");d.map.mapdiv.dispatchEvent(a)},d},d3.mappu.VectorLayer=function(a,b){return d3_mappu_VectorLayer(a,b)},d3_mappu_VectorLayer=function(a,b){function c(a){var b,c=0,d=0,e=a.length,f=a[d];for(d;e-1>d;d++)b=a[d+1],c+=(b[0]-f[0])*(b[1]+f[1]),f=b;return c>=0}function d(a){var b=d3.select(this);if(k)for(var c in k)b.select("path").style(c,k[c]);if(a.style)for(var c in a.style)b.select("path").style(c,a.style[c]);a._selected?b.append("path").attr("d",h).style("stroke","none").style("fill","red").classed("halo",!0):b.selectAll(".halo").remove()}function e(b){var d=i;if("Point"==b.geometry.type&&b.style){var e=(d(b.geometry.coordinates)[0],d(b.geometry.coordinates)[1],b.style&&b.style.width?b.style.width:k.width?k.width:32),f=b.style&&b.style.height?b.style.height:k.height?k.height:37;d3.select(this).append("g").append("image").attr("width",e).attr("height",f).style("pointer-events","visiblepainted").attr("xlink:href",function(a){return a.style.iconimg?"data:image/"+a.style.iconimg_encoding+","+a.style.iconimg_bytearray:a.style["marker-url"]?a.style["marker-url"]:void 0})}else"Polygon"!=b.geometry.type||c(b.geometry.coordinates[0])||b.geometry.coordinates[0].reverse(),d3.select(this).append("path").attr("d",h).classed(a,!0).style("pointer-events","visiblepainted");d3.select(this).append("text").classed("shadowtext",!0).attr("text-anchor","middle"),d3.select(this).append("text").classed("vectorLabel",!0).attr("text-anchor","middle")}b=b||{},d3_mappu_Layer.call(this,a,b);var f=d3_mappu_Layer(a,b);f.type="vector";var g=[];f.zindex=100;var h,i,j=b.duration||0,k=b.style||{},l=b.labelStyle||{},m=b.events;Object.defineProperty(f,"data",{get:function(){return g},set:function(a){g=a,n(!1)}}),Object.defineProperty(f,"events",{get:function(){return m},set:function(a){m=a}});var n=function(a){b.reproject?(i=f.map.projection,h=d3.geoPath().projection(i).pointRadius(function(a){return a.style&&a.style.radius?a.style.radius:4.5})):(i=d3.geoMercator().scale(.5/Math.PI).translate([0,0]),h=d3.geoPath().projection(i));var c=f.drawboard;a&&c.selectAll(".entity").remove();var k=c.select("g").selectAll(".entity").data(g,function(a){return a.id}),l=k.enter().append("g").classed("entity",!0).attr("id",function(a){return"entity"+a.id});l.each(e),l.each(d),k.exit().remove(),m&&m.forEach(function(a){l.each(function(){d3.select(this).select("path").on(a.event,a.action),d3.select(this).select("image").on(a.event,a.action)})}),f.refresh(a?0:j)},o=(d3.scaleLinear().range([20,20,32,32]).domain([0,21,24,30]),d3.scaleLinear().range([20,20,37,37]).domain([0,21,24,30]),function(a){var c=f.drawboard;if(c.select("g").style("opacity",this.opacity).style("display",this.visible?"block":"none"),f.visible){var e=c.select("g").selectAll(".entity");if(b.reproject){var g=f.map.projection;e.select("path").transition().duration(a).attr("d",h),e.select("image").transition().duration(a).each(function(a){var b=a.style&&a.style.width?a.style.width:k.width?k.width:32,c=a.style&&a.style.height?a.style.height:k.height?k.height:37,d=g(a.geometry.coordinates)[0],e=g(a.geometry.coordinates)[1],f=b/2,h=c/2;d3.select(this).attr("x",d).attr("y",e).attr("width",b).attr("height",c),a.style&&a.style.rotate?d3.select(this.parentElement).attr("transform","translate("+-f+" "+-h+") rotate("+a.style.rotate+" "+Math.round(d+f)+" "+Math.round(e+h)+")"):d3.select(this.parentElement).attr("transform","translate("+-f+" "+-h+")")}),b.labelfield&&e.each(function(a){var c=h.centroid(a.geometry),d=a.properties[b.labelfield];if(d3.select(this).selectAll("text").attr("x",c[0]).attr("y",c[1]-20).text(d),d3.select(this).select(".shadowtext").style("stroke-width","2.5px").style("stroke","white").style("opacity",.8),l)for(var e in l)d3.select(this).selectAll(".vectorLabel").style(e,l[e]),"opacity"==e&&d3.select(this).select(".shadowtext").style("opacity",l[e])}),e.each(d)}else{var i=f.map.transform;c.select("g").attr("transform",i).style("stroke-width",1/i.k)}}else c.selectAll(".entity").remove()}),p=function(a){var b=d3.map(g,function(a){return a.id});b.set(a.id,a),g=b.values(),f.draw(!0)},q=function(a){var b=null;g.forEach(function(c,d){c.id==a.id&&(b=d)}),g.splice(b,1),f.draw()},r=function(a){var b=i.invert(h.centroid(a));f.map.center=b,f.map.redraw()};return f.refresh=o,f.draw=n,f.addFeature=p,f.removeFeature=q,f.zoomToFeature=r,f},d3_mappu_VectorLayer.prototype=Object.create(d3_mappu_Layer.prototype),d3.mappu.VectorTileLayer=function(a,b){return d3_mappu_VectorTileLayer(a,b)},d3_mappu_VectorTileLayer=function(a,b){function c(a){var b=d3.select(this);if(l)for(var c in l)"fill"==c&&-1==a.geometry.type.indexOf("Polygon")&&(l[c]="none"),b.style(c,l[c]);if(a.style)for(var c in a.style)"fill"==c&&-1==a.geometry.type.indexOf("Polygon")&&(a.style[c]="none"),b.style(c,a.style[c])}function d(a){var b=a[0],c=a[1],d=a[2];return j&&(c=Math.pow(2,d)-c-1),i.replace("{s}",["a","b","c","d"][3*Math.random()|0]).replace("{z}",d).replace("{x}",b).replace("{y}",c).replace("%7Bs%7D",["a","b","c","d"][3*Math.random()|0]).replace("%7Bz%7D",d).replace("%7Bx%7D",b).replace("%7By%7D",c)}function e(a){var b=d3.select(this),e=d(a);h=d3.geoMercator(),g=d3.geoPath().projection(h),this._xhr=d3.json(e,function(d,e){if(d)throw d;var f=256*Math.pow(2,a[2]);if(g.projection().translate([f/2-256*a[0],f/2-256*a[1]]).scale(f/2/Math.PI),e.objects)var h=topojson.feature(e,e.objects[k]).features;else{if(!e.features)throw"Can't work with this vectortile data";var h=e.features}"function"==typeof n&&(h=h.filter(n));var i=b.selectAll("path").data(h,function(a){return a.id}),j=i.enter().append("path").attr("id",function(a){return"entity"+a.properties.id}).attr("class",function(a){return a.properties.kind}).attr("d",g).style("pointer-events","visiblepainted");j.each(c),i.exit().remove(),m&&m.forEach(function(a){j.each(function(){d3.select(this).on(a.event,a.action)})})})}b=b||{},d3_mappu_Layer.call(this,a,b);var f=d3_mappu_Layer(a,b);f.type="vectortile";var g,h,i=(Math.PI,b.url),j=(b.duration||0,b.tms),k=b.layername,l=b.style||{},m=(b.labelStyle||{},b.events),n=b.filter;Object.defineProperty(f,"url",{get:function(){return i},set:function(a){i=a,o()}}),Object.defineProperty(f,"events",{get:function(){return m},set:function(a){m=a}});var o=function(){var a=f.drawboard,b=f.map.tiles,c=f.map.transform,d=a.select("g").attr("transform","scale("+b.scale+")translate("+b.translate+")").style("stroke-width",1/c.k*100).selectAll(".tile").data(b,function(a){return a});d.exit().each(function(a){this._xhr&&this._xhr.abort()}).remove();var g=d.enter();if(f.visible){var h=1/256,i=g.append("g").attr("class","tile").attr("transform",function(a){return"translate("+a[0]+" "+a[1]+")scale("+h+")"});i.each(e)}},p=function(){o(),f.drawboard.style("opacity",this.opacity).style("display",this.visible?"block":"none")};return f.refresh=p,f.draw=o,f},d3_mappu_VectorTileLayer.prototype=Object.create(d3_mappu_Layer.prototype),d3.mappu.TWKBLayer=function(a,b){return d3_mappu_TWKBLayer(a,b)},d3_mappu_TWKBLayer=function(a,b){function c(a,b){var c=d3.select("#T"+e.id+"_"+a[0]+"_"+a[1]+"_"+a[2]);if(c[0][0]){i=d3.geo.mercator(),h=d3.geo.path().projection(i);var d=(e.map.tiles,256*Math.pow(2,a[2]));h.projection().translate([d/2-256*a[0],d/2-256*a[1]]).scale(d/2/Math.PI);var f=c.append("canvas").attr("width",256).attr("height",256),g=f.node().getContext("2d");h.context(g),g.save(),b.forEach(function(a){g.beginPath(),h(a),g.fillStyle="function"==typeof o.fill?o.fill(a.properties[o.column]):o.fill,g.fill(),g.closePath()}),g.lineWidth=1,g.restore()}}function d(a,b){var c=a/256,d=a%1?Number:Math.round;return"matrix3d("+[c,0,0,0,0,c,0,0,0,0,c,0,d(b[0]*a),d(b[1]*a),0,1]+")"}b=b||{};var e=d3_mappu_Layer(a,b);e.type="raster";var f=b.url,g=b;e.options=g,e.visibility=e.visible;var h,i,j=b.layers,k=(b.classproperty,b.id_column),l=b.geom_column,m=b.srid,n=b.attributes,o=b.style,p=(b.duration||0,b.style||{},[]);Object.defineProperty(e,"url",{get:function(){return f},set:function(a){f=a,t()}}),Object.defineProperty(e,"layers",{get:function(){return j},set:function(a){j=a,t()}}),Object.defineProperty(e,"style",{get:function(){return o},set:function(a){o=a,e.drawboard.selectAll(".tile").remove(),e.refresh(0)}}),e.clear=function(){};var q=function(a){var b=2<>1:-(a>>1)-1}c.ReadVarInt64=d,c.ReadVarSInt64=e,c.unzigzag=f},{}],3:[function(a,b,c){function d(a,b,c){c=c||Number.MAX_VALUE;for(var d={buffer:a,cursor:void 0===b?0:b,bufferLength:a.byteLength||a.length,refpoint:new Int32Array(4)},f=[],g=0;d.cursorg;){var h=e(d,c);h.length>0?f.push({type:d.type,offset:c>4);a.type=15&c,a.factors=[],a.factors[0]=a.factors[1]=Math.pow(10,g),c=a.buffer[a.cursor],a.cursor++,a.has_bbox=1&c,a.has_size=(2&c)>>1,a.has_idlist=(4&c)>>2,a.is_empty=(16&c)>>4;var h=(8&c)>>3;if(h){var i=a.buffer[a.cursor];a.cursor++,d=1&i,f=(2&i)>>1;var j=(28&i)>>2,k=(224&i)>>5;d&&(a.factors[2]=Math.pow(10,j)),f&&(a.factors[2+d]=Math.pow(10,k)),a.has_z=d,a.has_m=f}var l=2+d+f;if(a.ndims=l,a.has_size&&(a.size=n(a)),a.has_bbox){for(var m=[],q=0;l-1>=q;q++){var r=o(a),s=r+o(a);m[q]=r,m[q+l]=s}a.bbox=m}return e(a,b)}function e(a,b){for(var c=a.type,d=0;dd;++d)b[d]=g(a);return b}function i(a,b){var c=a.type,d=n(a),e=[],f=[];a.has_idlist&&(f=l(a,d));for(var g=0;d>g;g++){var h=b(a);e.push(h)}return{type:c,ids:f,geoms:e}}function j(a,b){var c=a.type,e=n(a),f=[],g=[];a.has_idlist&&(g=l(a,e));for(var h=0;e>h&&b>h;h++){var i=d(a);f.push({type:a.type,coordinates:i})}return{type:c,ids:g,ndims:a.ndims,offset:bc;c++)for(d=0;e>d;d++)a.refpoint[d]+=o(a),g[e*c+d]=a.refpoint[d]/f[d];if(a.include_bbox&&!a.has_bbox)for(c=0;b>c;c++)for(d=0;e>d;d++){const h=g[d*e+c];ha.bbox.max[d]&&(a.bbox.max[d]=h)}return g}function l(a,b){const c=[];for(var d=0;b>d;d++)c.push(o(a));return c}var m=a("./constants"),n=a("./protobuf").ReadVarInt64,o=a("./protobuf").ReadVarSInt64,p=a("./protobuf").unzigzag;b.exports=d},{"./constants":1,"./protobuf":2}],5:[function(a,b,c){function d(a,b){return{type:l[a],coordinates:b}}function e(a,b,c,d){return{type:"Feature",id:c,geometry:m[a](b,d)}}function f(a,b,c,d){return b.map(function(b,f){return e(a,b,c?c[f]:void 0,d)})}function g(a,b,c){return a.map(function(a,d){return e(a.type,a.coordinates,b?b[d]:void 0,c)})}function h(a,b){for(var c=[],d=0,e=a.length;e>d;d+=b){for(var f=[],g=0;b>g;++g)f.push(a[d+g]);c.push(f)}return c}function i(a){for(var b={buffer:a,cursor:0,bufferLength:a.byteLength||a.length,refpoint:new Int32Array(4)},c=[];b.cursor=a&&a>=p||console.log("Zoomlevel exceeded",a,"Min:",p,"Max:",o)}}),Object.defineProperty(f,"minZoom",{get:function(){return p},set:function(a){p=a}}),Object.defineProperty(f,"maxZoom",{get:function(){return o},set:function(a){o=a}}),Object.defineProperty(f,"maxView",{get:function(){return q},set:function(a){q=a}}),Object.defineProperty(f,"projection",{get:function(){return m},set:function(a){m=a}}),Object.defineProperty(f,"extent",{get:function(){return k},set:function(a){k=a}}),Object.defineProperty(f,"tiles",{get:function(){return _tiles},set:function(){console.warn("No setting allowed for tile")}}),Object.defineProperty(f,"transform",{get:function(){return h},set:function(){console.warn("No setting allowed for transform")}}),Object.defineProperty(f,"zoombehaviour",{get:function(){return u},set:function(){console.warn("No setting allowed for zoombehaviour")}}),Object.defineProperty(f,"layers",{get:function(){return g},set:function(){console.warn("No setting allowed for layers")}});var w=function(a){if(!a.id)return console.warn("Not a valid layer. (No ID)"),!1;var b=g.indexOf(a);return b>-1&&g.splice(b,1),g.push(a),a._onAdd(f),f},x=function(a){var b=g.indexOf(a);return b>-1&&g.splice(b,1),y(),a._onRemove(f),f},y=function(){var a=d3.select(c).selectAll(".drawboard").data(g,function(a){return a.id});a.enter().append(function(a){if("raster"==a.type)return document.createElement("div");if("vector"==a.type||"vectortile"==a.type)return document.createElementNS("http://www.w3.org/2000/svg","svg");if("canvas"==a.type)return document.createElement("canvas");throw"No valid type ("+a.type+" )specified for layer"}).attr("id",function(a){return a.id}).style("position","absolute").style("pointer-events","none").classed("drawboard",!0).each(function(a){a.drawboard=d3.select(this),"vector"!=a.type&&"vectortile"!=a.type||a.drawboard.append("g")}),a.exit().remove(),a.sort(function(a,b){return a.zindex-b.zindex})};return f.addLayer=w,f.removeLayer=x,f.orderLayers=y,f.redraw=r,f.resize=s,f},d3.mappu=d3.mappu||{},d3.mappu.Sketch=function(a,b){return d3_mappu_Sketch(a,b)},d3_mappu_Sketch=function(a,b){function c(){p.selectAll(".sketch").remove(),p.append("path").attr("d",function(){return q(u)}).classed("sketch",!0).style("stroke","blue").style("fill",function(){return"LineString"==t?"none":"blue"}).style("fill-opacity",.4)}function d(a){var b=d3.mouse(this);s.push(o.projection.invert(b)),u.geometry.type="LineString",u.geometry.coordinates=s,c()}function e(){var a=d3.mouse(this);s=r.invert(a),u.id=(new Date).getTime().toString(),u.geometry.coordinates=s,c(),x()}function f(){s.pop(),s.pop(),u.geometry.type="LineString",u.geometry.coordinates=s,u.id=(new Date).getTime().toString(),c(),x()}function g(){u.geometry.type="Polygon",s.pop(),s.pop(),s.push(s[0]),u.geometry.coordinates=[s],u.id=(new Date).getTime().toString(),c(),x()}function h(){var a=u.geometry.coordinates.length,b=d3.mouse(this),d=o.projection.invert(b);a>=1&&(1==a?s[a]=d:s[a-1]=d,u.geometry.coordinates=s,c())}function i(a){d3.event.sourceEvent.stopPropagation(),d3.select(this).classed("dragging",!0)}function j(a){var b=d3.mouse(o.mapdiv);d3.select(this).attr("cx",b[0]).attr("cy",b[1]),"Polygon"==t?d3.select(this).classed("sketchPointInter")?(d3.select(this).classed("sketchPointInter",!1).classed("sketchPoint",!0),a.index+1==u.geometry.coordinates[0].length?u.geometry.coordinates[0].splice(1,0,a):u.geometry.coordinates[0].splice(a.index+1,0,a)):(u.geometry.coordinates[0][a.index]=r.invert(b),0===a.index&&(u.geometry.coordinates[0].pop(),u.geometry.coordinates[0].push(r.invert(b))),a.index+1==u.geometry.coordinates[0].length&&(u.geometry.coordinates[0][0]=r.invert(b))):"LineString"==t?d3.select(this).classed("sketchPointInter")?(d3.select(this).classed("sketchPointInter",!1).classed("sketchPoint",!0),u.geometry.coordinates.splice(a.index+1,0,a)):u.geometry.coordinates[a.index]=r.invert(b):"Point"==t&&(u.geometry.coordinates=r.invert(b)),l()}function k(a){d3.select(this).classed("dragging",!1),l()}function l(){if(p.selectAll(".sketch").remove(),p.append("path").attr("d",function(){return q(u)}).classed("sketch",!0).style("stroke","red").style("fill",function(){return"LineString"==t?"none":"red"}).style("fill-opacity",.4),"Point"==t)var a=[u.geometry.coordinates],b=[];else{switch(t){case"Polygon":var a=u.geometry.coordinates[0];break;case"LineString":var a=u.geometry.coordinates;break;default:console.warn(t," not supported")}a.forEach(function(a,b){a.index=b,a.fid=a.id});var b=a.map(function(b,c){if(c+11&&f(a),window.setTimeout(function(){v=0},300)})):"Polygon"==t&&(u.style.fill="blue",u.style.stroke="blue",d3.select(o.mapdiv).on("mousedown",d),d3.select(o.mapdiv).on("mousemove",h),d3.select(o.mapdiv).on("mousedown.doublemousedown",function(a){v++,v>1&&g(a),window.setTimeout(function(){v=0},300)}),d3.select(o.mapdiv).on("touchstart",function(a){pressTimer=window.setTimeout(function(){g()},500)}).on("touchmove",function(a,b){console.log(a,b)}).on("touchend",function(){clearTimeout(pressTimer)}))})},x=function(){self.resolve(u),E()},y=d3.drag().subject(function(a){return a}).on("start",i).on("drag",j).on("end",k),z=function(a){return p=d3.select(o.mapdiv).append("svg").attr("id","sketch").style("position","absolute").attr("width",o.mapdiv.clientWidth).attr("height",o.mapdiv.clientHeight).append("g"),new Promise(function(b,c){self.resolve=b,event.stopPropagation(),d3.select(o.mapdiv).on("click",function(){l(),B()}),u=a,t=a.geometry.type,l()})},A=function(){},B=function(){self.resolve(u),E()},C=function(a){return new Promise(function(b,c){b(a),E()})},D=function(){},E=function(){p&&(p.selectAll(".sketch").remove(),p.selectAll(".sketchPoint").remove(),p.selectAll(".sketchPointInter").remove(),d3.select(o.mapdiv).select("#sketch").remove(),u=null,s=[],d3.select(o.mapdiv).on("mousemove",null),d3.select(o.mapdiv).on("click",null),d3.select(o.mapdiv).on("mousedown",null),d3.select(o.mapdiv).on("doublemousedown",null),d3.select(o.mapdiv).on("touchstart",null),d3.select(o.mapdiv).on("touchend",null))};return n.draw=w,n.startEdit=A,n.startRemove=D,n.remove=C,n.finish=E,n.edit=z,n.addTo=m,n},d3.mappu.Layer=function(a,b){return d3_mappu_Layer(a,b)},d3_mappu_Layer=function(a,b){b=b||{};var c,d={},e=d3.mappu.util.createID(),f=a,g=1;g=b.opacity||1;var h=!0;"boolean"!=typeof b.visible&&"true"!=b.visible&&"false"!=b.visible||(h=b.visible);var i=0,j=function(){},k=function(){},l=function(){},m=function(a){d.zindex=a},n=function(a){return a.addLayer(d),a.resize(),d};return Object.defineProperty(d,"id",{get:function(){return e},set:function(){console.warn("setting ID not allowed for layer")}}),Object.defineProperty(d,"name",{get:function(){return f},set:function(a){f=a}}),Object.defineProperty(d,"map",{get:function(){return c},set:function(a){c=a}}),Object.defineProperty(d,"opacity",{get:function(){return g},set:function(a){g=a,d.refresh(0)}}),Object.defineProperty(d,"visible",{get:function(){return h},set:function(a){h=a,d.draw(!0),d.refresh(0)}}),Object.defineProperty(d,"zindex",{get:function(){return i},set:function(a){i=a,d.map&&d.map.orderLayers()}}),d.refresh=j,d.moveUp=k,d.moveDown=l,d.addTo=n,d.setZIndex=m,d._onAdd=function(a){c=a,a.orderLayers(),d.draw();var b=new CustomEvent("layeradded",{detail:d});d.map.mapdiv.dispatchEvent(b)},d._onRemove=function(){var a=new CustomEvent("layerremoved");d.map.mapdiv.dispatchEvent(a)},d},d3.mappu.VectorLayer=function(a,b){return d3_mappu_VectorLayer(a,b)},d3_mappu_VectorLayer=function(a,b){function c(a){var b,c=0,d=0,e=a.length,f=a[d];for(d;e-1>d;d++)b=a[d+1],c+=(b[0]-f[0])*(b[1]+f[1]),f=b;return c>=0}function d(a){var b=d3.select(this);if(k)for(var c in k)b.select("path").style(c,k[c]),b.select("circle").style(c,k[c]);if(a.style)for(var c in a.style)b.select("path").style(c,a.style[c]),b.select("circle").style(c,a.style[c]);a._selected?b.append("path").attr("d",h).style("stroke","none").style("fill","red").classed("halo",!0):b.selectAll(".halo").remove()}function e(b){var d=i;if("Point"==b.geometry.type&&b.style){var e=d(b.geometry.coordinates)[0],f=d(b.geometry.coordinates)[1];if(b.style.iconimg_encoding||b.style["marker-url"]){var g=b.style&&b.style.width?b.style.width:k.width?k.width:32,j=b.style&&b.style.height?b.style.height:k.height?k.height:37;d3.select(this).append("g").append("image").attr("width",g).attr("height",j).style("pointer-events","visiblepainted").attr("xlink:href",function(a){return a.style.iconimg?"data:image/"+a.style.iconimg_encoding+","+a.style.iconimg_bytearray:a.style["marker-url"]?a.style["marker-url"]:void 0})}else d3.select(this).append("circle").attr("cx",e).attr("cy",f).attr("r",function(a){return k.radius?k.radius:a.style&&a.style.radius?a.style.radius:5}).classed(a,!0).style("pointer-events","visiblepainted")}else"Polygon"!=b.geometry.type||c(b.geometry.coordinates[0])||b.geometry.coordinates[0].reverse(),d3.select(this).append("path").attr("d",h).classed(a,!0).style("pointer-events","visiblepainted");d3.select(this).append("text").classed("shadowtext",!0).attr("text-anchor","middle"),d3.select(this).append("text").classed("vectorLabel",!0).attr("text-anchor","middle")}b=b||{},d3_mappu_Layer.call(this,a,b);var f=d3_mappu_Layer(a,b);f.type="vector";var g=[];f.zindex=100;var h,i,j=b.duration||0,k=b.style||{},l=b.labelStyle||{},m=b.events;Object.defineProperty(f,"data",{get:function(){return g},set:function(a){g=a,n(!1)}}),Object.defineProperty(f,"events",{get:function(){return m},set:function(a){m=a}});var n=function(a){b.reproject?(i=f.map.projection,h=d3.geoPath().projection(i).pointRadius(function(a){return a.style&&a.style.radius?a.style.radius:4.5})):(i=d3.geoMercator().scale(.5/Math.PI).translate([0,0]),h=d3.geoPath().projection(i));var c=f.drawboard;a&&c.selectAll(".entity").remove();var k=c.select("g").selectAll(".entity").data(g,function(a){return a.id}),l=k.enter().append("g").classed("entity",!0).attr("id",function(a){return"entity"+a.id});l.each(e),l.each(d),k.exit().remove(),m&&m.forEach(function(a){l.each(function(){d3.select(this).select("path").on(a.event,a.action),d3.select(this).select("image").on(a.event,a.action),d3.select(this).select("circle").on(a.event,a.action)})}),f.refresh(a?0:j)},o=(d3.scaleLinear().range([20,20,32,32]).domain([0,21,24,30]),d3.scaleLinear().range([20,20,37,37]).domain([0,21,24,30]),function(a){var c=f.drawboard;if(c.select("g").style("opacity",this.opacity).style("display",this.visible?"block":"none"),f.visible){var e=c.select("g").selectAll(".entity");if(b.reproject){var g=f.map.projection;e.select("path").transition().duration(a).attr("d",h),e.select("circle").transition().duration(a).each(function(a){var b=g(a.geometry.coordinates)[0],c=g(a.geometry.coordinates)[1];d3.select(this).attr("cx",b).attr("cy",c)}),e.select("image").transition().duration(a).each(function(a){var b=a.style&&a.style.width?a.style.width:k.width?k.width:32,c=a.style&&a.style.height?a.style.height:k.height?k.height:37,d=g(a.geometry.coordinates)[0],e=g(a.geometry.coordinates)[1],f=b/2,h=c/2;d3.select(this).attr("x",d).attr("y",e).attr("width",b).attr("height",c),a.style&&a.style.rotate?d3.select(this.parentElement).attr("transform","translate("+-f+" "+-h+") rotate("+a.style.rotate+" "+Math.round(d+f)+" "+Math.round(e+h)+")"):d3.select(this.parentElement).attr("transform","translate("+-f+" "+-h+")")}),b.labelfield&&e.each(function(a){var c=h.centroid(a.geometry),d=a.properties[b.labelfield];if(d3.select(this).selectAll("text").attr("x",c[0]).attr("y",c[1]-20).text(d),d3.select(this).select(".shadowtext").style("stroke-width","2.5px").style("stroke","white").style("opacity",.8),l)for(var e in l)d3.select(this).selectAll(".vectorLabel").style(e,l[e]),("opacity"==e||e.indexOf("font")>-1)&&d3.select(this).select(".shadowtext").style(e,l[e])}),e.each(d)}else{var i=f.map.transform;c.select("g").attr("transform",i).style("stroke-width",1/i.k)}}else c.selectAll(".entity").remove()}),p=function(a){var b=d3.map(g,function(a){return a.id});b.set(a.id,a),g=b.values(),f.draw(!0)},q=function(a){var b=null;g.forEach(function(c,d){c.id==a.id&&(b=d)}),g.splice(b,1),f.draw()},r=function(a){var b=i.invert(h.centroid(a));f.map.center=b,f.map.redraw()};return f.refresh=o,f.draw=n,f.addFeature=p,f.removeFeature=q,f.zoomToFeature=r,f},d3_mappu_VectorLayer.prototype=Object.create(d3_mappu_Layer.prototype),d3.mappu.VectorCanvasLayer=function(a,b){return d3_mappu_VectorCanvasLayer(a,b)},d3_mappu_VectorCanvasLayer=function(a,b){function c(a){var b,c=0,d=0,e=a.length,f=a[d];for(d;e-1>d;d++)b=a[d+1],c+=(b[0]-f[0])*(b[1]+f[1]),f=b;return c>=0}function d(a){"Polygon"!=a.geometry.type||c(a.geometry.coordinates[0])||a.geometry.coordinates[0].reverse();i=d3.geoMercator(),h=d3.geoPath().projection(i);var b=f.drawboard,d=b.node().getContext("2d");h.context(d),d.save(),d.beginPath(),h(a),d.fillStyle="function"==typeof j.fill?j.fill(a.properties[j.column]):j.fill,d.fill(),d.closePath(),d.lineWidth=1,d.restore()}function e(){var a=f.drawboard;a.save(),a.clearRect(0,0,width,height),a.translate(d3.event.translate[0],d3.event.translate[1]),a.scale(d3.event.scale,d3.event.scale),l(),a.restore()}b=b||{},d3_mappu_Layer.call(this,a,b);var f=d3_mappu_Layer(a,b);f.type="canvas";var g=[];f.zindex=100;var h,i,j=(b.duration||0,b.style||{}),k=(b.labelStyle||{},b.events);Object.defineProperty(f,"data",{get:function(){return g},set:function(a){g=a,l(!1)}}),Object.defineProperty(f,"style",{get:function(){return j},set:function(a){j=a,f.drawboard.selectAll(".tile").remove(),f.refresh(0)}}),Object.defineProperty(f,"events",{get:function(){return k},set:function(a){k=a}});var l=function(a){b.reproject?(i=f.map.projection,h=d3.geoPath().projection(i)):(i=d3.geoMercator().scale(.5/Math.PI).translate([0,0]),h=d3.geoPath().projection(i));f.drawboard;g.forEach(d)};return f.refresh=e,f.draw=l,f},d3_mappu_VectorCanvasLayer.prototype=Object.create(d3_mappu_Layer.prototype),d3.mappu.VectorTileLayer=function(a,b){return d3_mappu_VectorTileLayer(a,b)},d3_mappu_VectorTileLayer=function(a,b){function c(a){var b=d3.select(this);if(l)for(var c in l)"fill"==c&&-1==a.geometry.type.indexOf("Polygon")&&b.style(c,"none"),b.style(c,l[c]);if(a.style)for(var c in a.style)"fill"==c&&-1==a.geometry.type.indexOf("Polygon")&&b.style(c,"none"),b.style(c,a.style[c])}function d(a){var b=a.x,c=a.y,d=a.z;return j&&(c=Math.pow(2,d)-c-1),i.replace("{s}",["a","b","c","d"][3*Math.random()|0]).replace("{z}",d).replace("{x}",b).replace("{y}",c).replace("%7Bs%7D",["a","b","c","d"][3*Math.random()|0]).replace("%7Bz%7D",d).replace("%7Bx%7D",b).replace("%7By%7D",c)}function e(a){var b=d3.select(this),e=d(a);h=d3.geoMercator(),g=d3.geoPath().projection(h),e.indexOf(".mvt")>-1?this._xhr=d3.request(e).responseType("arraybuffer").get(function(a,d){var e=new VectorTile(new pbf(new Uint8Array(d.response))),f=4096,g={};for(var h in e.layers)g[h]=e.layers[k].toGeoJSON();if(g[k]){var i=g[k].features,j=b.selectAll("path").data(i,function(a){return a.id}),l=d3.geoTransform({point:function(a,b){isNaN(b)?(b=a[0][1]/f*256,a=a[0][0]/f*256):(a=a/f*256,b=b/f*256),this.stream.point(a,b)}}),n=d3.geoPath().projection(l),o=j.enter().append("path").attr("id",function(a){return"entity"+a.properties.id}).attr("class",function(a){return a.properties.kind}).attr("d",n).style("pointer-events","visiblepainted");o.each(c),j.exit().remove(),m&&m.forEach(function(a){o.each(function(){d3.select(this).on(a.event,a.action)})})}}):this._xhr=d3.json(e,function(d,e){if(d)throw d;var f=256*Math.pow(2,a[2]);if(g.projection().translate([f/2-256*a[0],f/2-256*a[1]]).scale(f/2/Math.PI),e.objects)var h=topojson.feature(e,e.objects[k]).features;else{if(!e.features)throw"Can't work with this vectortile data";var h=e.features}"function"==typeof n&&(h=h.filter(n));var i=b.selectAll("path").data(h,function(a){return a.id}),j=i.enter().append("path").attr("id",function(a){return"entity"+a.properties.id}).attr("class",function(a){return a.properties.kind}).attr("d",g).style("pointer-events","visiblepainted");j.each(c),i.exit().remove(),m&&m.forEach(function(a){j.each(function(){d3.select(this).on(a.event,a.action)})})})}b=b||{},d3_mappu_Layer.call(this,a,b);var f=d3_mappu_Layer(a,b);f.type="vectortile";var g,h,i=(Math.PI,b.url),j=(b.duration||0,b.tms),k=b.layername,l=b.style||{},m=(b.labelStyle||{},b.events),n=b.filter;Object.defineProperty(f,"url",{get:function(){return i},set:function(a){i=a,o()}}),Object.defineProperty(f,"events",{get:function(){return m},set:function(a){m=a}});var o=function(){var a=f.drawboard,b=f.map.tiles,c=f.map.transform,d=a.select("g").attr("transform","scale("+b.scale+")translate("+b.translate+")").style("stroke-width",1/c.k*100).selectAll(".tile").data(b,function(a){return a});d.exit().each(function(a){this._xhr&&this._xhr.abort()}).remove();var g=d.enter();if(f.visible){var h=1/256,i=g.append("g").attr("class","tile").attr("transform",function(a){return"translate("+a[0]+" "+a[1]+")scale("+h+")"});i.each(e)}},p=function(){o(),f.drawboard.style("opacity",this.opacity).style("display",this.visible?"block":"none")};return f.refresh=p,f.draw=o,f},d3_mappu_VectorTileLayer.prototype=Object.create(d3_mappu_Layer.prototype),d3.mappu.TWKBLayer=function(a,b){return d3_mappu_TWKBLayer(a,b)},d3_mappu_TWKBLayer=function(a,b){function c(a,b){var c=d3.select("#T"+e.id+"_"+a[0]+"_"+a[1]+"_"+a[2]);if(c[0][0]){i=d3.geo.mercator(),h=d3.geo.path().projection(i);var d=(e.map.tiles,256*Math.pow(2,a[2]));h.projection().translate([d/2-256*a[0],d/2-256*a[1]]).scale(d/2/Math.PI);var f=c.append("canvas").attr("width",256).attr("height",256),g=f.node().getContext("2d");h.context(g),g.save(),b.forEach(function(a){g.beginPath(),h(a),g.fillStyle="function"==typeof o.fill?o.fill(a.properties[o.column]):o.fill,g.fill(),g.closePath()}),g.lineWidth=1,g.restore()}}function d(a,b){var c=a/256,d=a%1?Number:Math.round;return"matrix3d("+[c,0,0,0,0,c,0,0,0,0,c,0,d(b[0]*a),d(b[1]*a),0,1]+")"}b=b||{};var e=d3_mappu_Layer(a,b);e.type="raster";var f=b.url,g=b;e.options=g,e.visibility=e.visible;var h,i,j=b.layers,k=(b.classproperty,b.id_column),l=b.geom_column,m=b.srid,n=b.attributes,o=b.style,p=(b.duration||0,b.style||{},[]);Object.defineProperty(e,"url",{get:function(){return f},set:function(a){f=a,t()}}),Object.defineProperty(e,"layers",{get:function(){return j},set:function(a){j=a,t()}}),Object.defineProperty(e,"style",{get:function(){return o},set:function(a){o=a,e.drawboard.selectAll(".tile").remove(),e.refresh(0)}}),e.clear=function(){};var q=function(a){var b=2<= 0); + } + + function setStyle(d){ + var self = this; + var entity = d3.select(this); + //Do generic layer style + if (style){ + for (var key in style) { + entity.select('path').style(key, style[key]); + entity.select('circle').style(key, style[key]); + } + } + + //Now use per-feature styling + if (d.style){ + for (var key in d.style) { + entity.select('path').style(key, d.style[key]); + entity.select('circle').style(key, d.style[key]); + } + } + + + + if (d._selected){ + //make halo around entity to show as selected + entity + .append('path').attr("d", _path) + .style('stroke', 'none') + .style('fill', 'red') + .classed('halo', true); + } + else { + entity.selectAll('.halo').remove(); + } + } + //Build is only called on entry + function build(d){ + if (d.geometry.type == 'Polygon' && !ringIsClockwise(d.geometry.coordinates[0])){ + d.geometry.coordinates[0].reverse(); + } + var project = _projection; + _projection = d3.geoMercator(); + _path = d3.geoPath().projection(_projection); + var canvas = layer.drawboard; + var context = canvas.node().getContext("2d"); + _path.context(context); + context.save(); + context.beginPath(); + _path(d); + context.fillStyle = typeof(_style.fill)=='function'?_style.fill(d.properties[_style.column]):_style.fill; + context.fill(); + context.closePath(); + context.lineWidth = 1; + context.restore(); + } + + + + var draw = function(rebuild){ + if (config.reproject){ + _projection = layer.map.projection; + _path = d3.geoPath() + .projection(_projection) + } + else { + //TODO: this should be depending on the projection given ins the config, no? + _projection = d3.geoMercator() + .scale(1 / 2 / Math.PI) + .translate([0, 0]); + _path = d3.geoPath() + .projection(_projection); + } + var drawboard = layer.drawboard; + if (rebuild){ + //drawboard.selectAll('.entity').remove(); + } + _data.forEach(build); + }; + + function refresh() { + var canvas = layer.drawboard; + canvas.save(); + canvas.clearRect(0, 0, width, height); + canvas.translate(d3.event.translate[0], d3.event.translate[1]); + canvas.scale(d3.event.scale, d3.event.scale); + draw(); + canvas.restore(); + } + + + /* Exposed functions*/ + layer.refresh = refresh; + layer.draw = draw; + return layer; + }; + + d3_mappu_VectorCanvasLayer.prototype = Object.create(d3_mappu_Layer.prototype); + + // マップ diff --git a/src/layer/d3.mappu.VectorLayer.js b/src/layer/d3.mappu.VectorLayer.js index facb526..7de92bf 100644 --- a/src/layer/d3.mappu.VectorLayer.js +++ b/src/layer/d3.mappu.VectorLayer.js @@ -71,6 +71,7 @@ if (style){ for (var key in style) { entity.select('path').style(key, style[key]); + entity.select('circle').style(key, style[key]); } } @@ -78,6 +79,7 @@ if (d.style){ for (var key in d.style) { entity.select('path').style(key, d.style[key]); + entity.select('circle').style(key, d.style[key]); } } @@ -102,24 +104,37 @@ if (d.geometry.type == 'Point' && d.style){ var x = project(d.geometry.coordinates)[0]; var y = project(d.geometry.coordinates)[1]; - var width = d.style && d.style.width ? d.style.width : - (style.width ? style.width : 32); - var height = d.style && d.style.height ? d.style.height : - (style.height ? style.height : 37); - var img = d3.select(this).append('g').append("image") - .attr("width", width) - .attr("height", height) - //.attr("x",x-12.5) //No need setting x and y, since it's reset later - //.attr("y",y-25) - .style('pointer-events','visiblepainted') - .attr("xlink:href", function(d){ - if (d.style['iconimg']){ - return 'data:image/' + d.style['iconimg_encoding'] +','+ d.style['iconimg_bytearray']; - } - else if (d.style['marker-url']){ - return d.style['marker-url']; - }; - }); + + if (d.style['iconimg_encoding'] || d.style['marker-url']){ + var width = d.style && d.style.width ? d.style.width : + (style.width ? style.width : 32); + var height = d.style && d.style.height ? d.style.height : + (style.height ? style.height : 37); + var img = d3.select(this).append('g').append("image") + .attr("width", width) + .attr("height", height) + .style('pointer-events','visiblepainted') + .attr("xlink:href", function(d){ + if (d.style['iconimg']){ + return 'data:image/' + d.style['iconimg_encoding'] +','+ d.style['iconimg_bytearray']; + } + else if (d.style['marker-url']){ + return d.style['marker-url']; + }; + }); + } + else { + d3.select(this).append("circle") + .attr("cx", x) + .attr("cy", y) + .attr("r", function(d){ + return style.radius ? style.radius : + (d.style && d.style.radius) ? d.style.radius : + 5; + }) + .classed(name, true) + .style('pointer-events','visiblepainted');//make clickable + } } else { if (d.geometry.type == 'Polygon' && !ringIsClockwise(d.geometry.coordinates[0])){ @@ -185,6 +200,7 @@ newentity.each(function(){ d3.select(this).select('path').on(d.event, d.action); d3.select(this).select('image').on(d.event, d.action); + d3.select(this).select('circle').on(d.event, d.action); }); }); } @@ -202,6 +218,11 @@ if (config.reproject){//the slow way var project = layer.map.projection; entities.select('path').transition().duration(duration).attr("d", _path); + entities.select('circle').transition().duration(duration).each(function(d){ + var x = project(d.geometry.coordinates)[0]; + var y = project(d.geometry.coordinates)[1]; + d3.select(this).attr('cx',x).attr('cy',y); + }); entities.select('image').transition().duration(duration).each(function(d){ //TODO: create something nice customizable for widh-height calculations var width = d.style && d.style.width ? d.style.width : @@ -248,9 +269,9 @@ if (labelStyle){ for (var key in labelStyle) { d3.select(this).selectAll('.vectorLabel').style(key, labelStyle[key]); - //shadowtext only sensitive to the opacity style - if (key == 'opacity'){ - d3.select(this).select('.shadowtext').style('opacity', labelStyle[key]); + //shadowtext only sensitive to the opacity style or font params + if (key == 'opacity' || key.indexOf('font') > -1 ){ + d3.select(this).select('.shadowtext').style(key, labelStyle[key]); } } } diff --git a/src/layer/d3.mappu.VectorTileLayer.js b/src/layer/d3.mappu.VectorTileLayer.js index cf450d8..cf10d91 100644 --- a/src/layer/d3.mappu.VectorTileLayer.js +++ b/src/layer/d3.mappu.VectorTileLayer.js @@ -49,7 +49,7 @@ if (style){ for (var key in style) { if (key == 'fill' && d.geometry.type.indexOf('Polygon') == -1){ - style[key] = 'none'; + entity.style(key, 'none'); } entity.style(key, style[key]); } @@ -59,7 +59,7 @@ if (d.style){ for (var key in d.style) { if (key == 'fill' && d.geometry.type.indexOf('Polygon') == -1){ - d.style[key] = 'none'; + entity.style(key, 'none'); } entity.style(key, d.style[key]); } @@ -67,9 +67,9 @@ } function tileurl(d){ - var x = d[0], - y = d[1], - z = d[2]; + var x = d.x, + y = d.y, + z = d.z; if (tms) { y = Math.pow(2, z) - y - 1; //TMS reverse for Y-down } @@ -92,66 +92,107 @@ _projection = d3.geoMercator(); _path = d3.geoPath().projection(_projection); - this._xhr = d3.json(url, function(error, json) { - if (error) throw error; - - var k = Math.pow(2, d[2]) * 256; // size of the world in pixels - - _path.projection() - .translate([k / 2 - d[0] *256, k / 2 - d[1] *256]) // [0°,0°] in pixels - .scale(k / 2 / Math.PI); - /* TT: WORK IN PROGRESS FOR ALREADY PROJECTED DATA - function matrix(a, b, c, d, tx, ty) { - return d3.geoTransform({ - point: function(x, y) { - this.stream.point(a * x + b * y + tx, c * x + d * y + ty); + /* Test with MVT */ + if (url.indexOf('.mvt') > -1){ + this._xhr = d3.request(url).responseType('arraybuffer').get(function(error, json) { + var layers = [layername]; + var vtile = new VectorTile( new pbf( new Uint8Array(json.response) ) ); + var extents = 4096; + var data = {}; + + for (var key in vtile.layers) { + data[key] = vtile.layers[layername].toGeoJSON(); } - }); - } - var tx = 0; //k / 2 - d[0] *256; - var ty = 0 ; //k / 2 - d[0] *256; - - - var scale = 1/256; - var path = d3.geoPath() - .projection(matrix(scale, 0, 0, scale, tx, ty)); - /* END OF WORK IN PROGRESS */ - - if (json.objects){ - var features = topojson.feature(json,json.objects[layername]).features; - } else if (json.features){ - var features = json.features; - } else { - throw "Can't work with this vectortile data"; - } - - if (typeof _filter === 'function'){ - features = features.filter(_filter); - } - - var entities = tile.selectAll('path').data(features, function(d){ - return d.id; + if (!data[layername]){return;} + var features = data[layername].features; + var entities = tile.selectAll('path').data(features, function(d){ + return d.id; + }); + var tile_projection = d3.geoTransform({ + point: function(x, y) { + // Sometimes PBF points in a mixed-geometry layer are corrupted + if(!isNaN(y)){ + x = x/extents*256; + y = y/extents*256; + } else { + y = x[0][1]/extents * 256; + x = x[0][0]/extents * 256; + } + this.stream.point(x, y); + } + }); + var tilePath = d3.geoPath() + .projection(tile_projection) + var newentity = entities.enter().append('path') + .attr('id',function(d){ + return 'entity'+ d.properties.id; + }) + .attr('class',function(d){return d.properties.kind;}) + .attr("d", tilePath) + .style('pointer-events','visiblepainted');//make clickable; + newentity.each(setStyle); + entities.exit().remove(); + + // Add events from config + if (_events){ + _events.forEach(function(d){ + newentity.each(function(){ + d3.select(this).on(d.event, d.action); + }); + }); + } }); - - var newentity = entities.enter().append('path') - .attr('id',function(d){ - return 'entity'+ d.properties.id; - }) - .attr('class',function(d){return d.properties.kind;}) - .attr("d", _path) - .style('pointer-events','visiblepainted');//make clickable; - newentity.each(setStyle); - entities.exit().remove(); - - // Add events from config - if (_events){ - _events.forEach(function(d){ - newentity.each(function(){ - d3.select(this).on(d.event, d.action); - }); - }); - } - }); + } + + + /* END of test with mvt */ + else { + + this._xhr = d3.json(url, function(error, json) { + if (error) throw error; + + var k = Math.pow(2, d[2]) * 256; // size of the world in pixels + + _path.projection() + .translate([k / 2 - d[0] *256, k / 2 - d[1] *256]) // [0�,0�] in pixels + .scale(k / 2 / Math.PI); + + if (json.objects){ + var features = topojson.feature(json,json.objects[layername]).features; + } else if (json.features){ + var features = json.features; + } else { + throw "Can't work with this vectortile data"; + } + + if (typeof _filter === 'function'){ + features = features.filter(_filter); + } + + var entities = tile.selectAll('path').data(features, function(d){ + return d.id; + }); + + var newentity = entities.enter().append('path') + .attr('id',function(d){ + return 'entity'+ d.properties.id; + }) + .attr('class',function(d){return d.properties.kind;}) + .attr("d", _path) + .style('pointer-events','visiblepainted');//make clickable; + newentity.each(setStyle); + entities.exit().remove(); + + // Add events from config + if (_events){ + _events.forEach(function(d){ + newentity.each(function(){ + d3.select(this).on(d.event, d.action); + }); + }); + } + }); + } } diff --git a/src/map/d3.mappu.Map.js b/src/map/d3.mappu.Map.js index 2211a8d..50961b6 100644 --- a/src/map/d3.mappu.Map.js +++ b/src/map/d3.mappu.Map.js @@ -264,6 +264,9 @@ d3_mappu_Map = function( id, config ) { else if (d.type == 'vector' || d.type == 'vectortile'){ return document.createElementNS("http://www.w3.org/2000/svg", 'svg'); } + else if (d.type == 'canvas'){ + return document.createElement('canvas'); + } else throw 'No valid type (' + d.type + ' )specified for layer'; }) .attr( 'id', function( d ) { return d.id;} ) diff --git a/test/d3v4.html b/test/d3v4.html index 07626e4..dc9f6b1 100644 --- a/test/d3v4.html +++ b/test/d3v4.html @@ -3,6 +3,10 @@ + + + +