我正在尝试创建一个自定义传单层,它将允许使用GoJS库。我已经处理了我的大部分主要问题,如:
但是我被困在了在缩放时调整节点大小的问题。我正在计算一个scaleFactor并更改节点的location。到目前为止,这种方法是可行的,但是如果映射被放大到0级别,并且用户缩放回位置是不正确的。Y轴的位置是完全错误的。我还设置了一个小提琴,这样您就可以轻松地使用源代码了。
(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>
发布于 2016-02-29 13:41:08
// 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.latLngToPoint() (用于点)和map.getPixelOrigin() (用于视口)之类的方法--使用绝对坐标会有帮助。现在,所有的定位都是基于map.latLngToContainerPoint(),它隐式地使用getPixelOrigin(),每次用户移动和缩放时都会发生变化,这会使您失去控制。
如果您坚持使用像素坐标来初始化您的图形,那么在初始化您的图形时,将它们投影到LatLng和map.project()中。这样,它们将在移动和缩放时得到适当的重新投影。
如果你想要传单的泛缩放功能,而不是地图功能,考虑使用CRS.Simple使用一个简单的非地理笛卡尔坐标系。
发布于 2016-03-01 11:02:05
非常感谢您的贡献,IvanSanchez。由于GoJS-论坛的一些帮助,我已经解决了我的问题。我使用GoJS数据绑定优化了我的代码。此外,我还更新了使用私有_getMapPanePos方法确定转换的丑陋方法。
小提琴:http://jsfiddle.net/5x0vtk81/
(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.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(),
panePosition,
transform;
if (this._canvas) {
panePosition = this._map._getMapPanePos();
transform = L
.DomUtil
.getTranslateString(panePosition.multiplyBy(-1));
} else {
transform = L
.DomUtil
.getTranslateString(L.point(0, 0));
}
return L.Util.template(
'width: {width}px; ' +
'height: {height}px; ' +
'transform: {transform}',
{
width: size.x,
height: size.y,
transform: transform
}
);
},
_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.diagram.updateAllTargetBindings('latlong')
},
_updateViewport: function (options) {
this._el.setAttribute('style', this._getElementStyle(options));
this._setFixedBounds();
this.diagram.updateAllTargetBindings('latlong');
}
});
L.goJsLayer = function (options) {
return new L.GoJsLayer(options);
};
}
}());
var $ = go.GraphObject.make,
map,
calcDiagramLocation,
nodeTemplate,
linkTemplate,
model,
canvasLayer;
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})
],
dragging: true
});
calcDiagramLocation = function(map, data) {
var point = map.latLngToContainerPoint(data);
return new go.Point(point.x, point.y);
};
// 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', 'latlong', calcDiagramLocation.bind(this, map))
);
// 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, latlong: [51.507884, -0.087765] }, // london bridge
{ key: 2, latlong: [48.853039, 2.349952] }, // Notre-Dame cathedral
],
[
{ 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
}).addTo(map);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>
https://stackoverflow.com/questions/35696993
复制相似问题