@cg_fd wrote:
I'm trying to create a custom Leaflet layer that shall enable the usage of the GoJS library. I've manged most of my main problems such as:
- Reposition the diagram based on the layer translation
- Draw elements outside the diagrams viewport
- Reposition diagram nodes when the map is beeing draged
But I'm stuck with the problem of resizing the the nodes while zooming. I'm calculating a
scaleFactor
and change thelocation
of the nodes. The approach works so far, but as far as the map is zoomed out to level0
and the user zooms back into the location is calculated incorrect. The location of the y-axis is completly wrong. I've also set up a fiddle so you can easily play arroud with the source.(function () { if (typeof(L) !== 'undefined' && typeof(go) !== 'undefined') { L.GoJsLayer = L.Class.extend({ includes: [L.Mixin.Events], options: { "animationManager.isEnabled": false, allowZoom: false, allowHorizontalScroll: false, hasHorizontalScrollbar: false, allowVerticalScroll: false, hasVerticalScrollbar: false, padding: 0 }, initialize: function (options) { L.setOptions(this, options); }, onAdd: function (map) { this._map = map; if (!this.diagram) { this._initDiagram(); } this._map .on('viewreset', this._reset, this) .on('moveend', this._updateViewport, this); }, onRemove: function (map) { this._map .getPanes() .overlayPane .removeChild(this._el); this._map .off('moveend', this._updateViewport, this); }, addTo: function (map) { map.addLayer(this); return this; }, _initDiagram: function () { this._initElement(); this._viewport = this._map.getBounds(); this.diagram = new go.Diagram( this._el.getAttribute('id') ); this._setFixedBounds(); this.diagram.setProperties(this.options); this._setCanvas(); }, _initElement: function () { var size = this._map.getSize(); this._el = L .DomUtil .create('div', 'leaflet-layer'); this._el.setAttribute( 'id', 'leaflet-gojs-diagram-' + L.Util.stamp(this) ); this._el .setAttribute('style', this._getElementStyle()); L.DomUtil.addClass(this._el, 'leaflet-zoom-hide'); this._map .getPanes() .overlayPane .appendChild(this._el); }, _getElementStyle: function (options) { var size = this._map.getSize(), paneTranslation, vpOffset, translation; if (this._canvas) { // This is a dirty solution due to the pressure of time. // This needs to be refractored! paneTranslation = L.DomUtil .getStyle(this._map.getPanes() .mapPane, 'transform') .match(/\-?\d+px/g) .map(function (value) { return parseInt(value); }); vpOffset = L.point(paneTranslation[0], paneTranslation[1]); translation = L .DomUtil .getTranslateString(vpOffset.multiplyBy(-1)); return '' .concat('width: ' + size.x + 'px;') .concat('height: ' + size.y + 'px;') .concat('transform: ' + translation); } else { translation = L.DomUtil.getTranslateString(L.point(0, 0)); return '' .concat('width: ' + size.x + 'px;') .concat('height: ' + size.y + 'px;') .concat('transform: ' + translation); } }, _setFixedBounds: function () { var width = parseInt(L.DomUtil.getStyle(this._el, 'width')), height = parseInt(L.DomUtil.getStyle(this._el, 'height')); this.diagram.setProperties({ fixedBounds: new go.Rect(0, 0, width, height) }); }, _setCanvas: function () { var canvasElements = this._el.getElementsByTagName('canvas'); if (canvasElements.length) { this._canvas = canvasElements.item(0); return true; } return false; }, _reset: function () { this._resizeNodes(); }, _resizeNodes: function () { var scale = this._map.options.crs.scale, currentScale = scale(this._map.getZoom()), previousScale = scale(this._calcPreviousScale()), scaleFactor = currentScale / previousScale; this.diagram.startTransaction('reposition'); this.diagram.nodes.each(this._resizeNode.bind(this, scaleFactor)); this.diagram.commitTransaction('reposition'); }, _calcPreviousScale: function () { var vp = this._viewport, vpNw = vp.getNorthWest(), vpSw = vp.getSouthWest(), mb = this._map.getBounds(), mbNw = mb.getNorthWest(), mbSw = mb.getSouthWest(), currentScale = this._map.getZoom(), previousScale; if (mbNw.distanceTo(mbSw) > vpNw.distanceTo(vpSw)) { previousScale = currentScale + 1; } else { previousScale = currentScale - 1; } return previousScale; }, _resizeNode: function (scaleFactor, node) { node.location = new go.Point( node.location.x * scaleFactor, node.location.y * scaleFactor ); }, _updateViewport: function (options) { this._el.setAttribute('style', this._getElementStyle(options)); this._setFixedBounds(); this._repositionNodes(); this._viewport = this._map.getBounds(); }, _repositionNodes: function () { this.diagram.startTransaction('reposition'); this.diagram.nodes.each(this._repositionNode.bind(this)); this.diagram.commitTransaction('reposition'); }, _repositionNode: function (node) { var vp = this._viewport, vpNw = vp.getNorthWest(), vpOffset = this._map.latLngToContainerPoint(vpNw), vpOffsetInverse = vpOffset.multiplyBy(-1), newX = node.location.x - vpOffsetInverse.x, newY = node.location.y - vpOffsetInverse.y; node.location = new go.Point(newX, newY); } }); L.goJsLayer = function (options) { return new L.GoJsLayer(options); }; } }()); var $ = go.GraphObject.make, nodeTemplate, linkTemplate, model, canvasLayer, map; // the node template describes how each Node should be constructed nodeTemplate = $(go.Node, 'Auto', $(go.Shape, 'Rectangle', { fill: '#FFF', width: 10, height: 10 } ), new go.Binding('location', 'loc', go.Point.parse) ); // the linkTemplates describes how each link should be constructed linkTemplate = $(go.Link, $(go.Shape)); // the Model holds only the essential information describing the diagram model = new go.GraphLinksModel( [ { key: 1, loc: '320 100' }, { key: 2, loc: '320 300' } ], [ { from: 1, to: 2 } ] ); // Caution: The model property has to be set after the template properties canvasLayer = L.goJsLayer({ nodeTemplate: nodeTemplate, linkTemplate: linkTemplate, model: model }); map = L.map('map', { zoom: 4, center: [51.505, -0.09], layers: [ L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {noWrap: true}), canvasLayer ], //dragging: false });
html, body, .map { padding: 0px; margin: 0px; height: 100%; } div canvas { outline: none; }
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" /> <script type="text/javascript" src="http://gojs.net/latest/release/go-debug.js"></script> <script type="text/javascript" src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script> <div id="map" class="map"></div>
Posts: 3
Participants: 2