336 lines
9.8 KiB
Vue
336 lines
9.8 KiB
Vue
/*
|
|
* @Author: hisense.wuhongjian
|
|
* @Date: 2022-03-22 14:40:05
|
|
* @LastEditors: hisense.wuhongjian
|
|
* @LastEditTime: 2022-03-22 14:40:05
|
|
* @Description: 告诉大家这是什么
|
|
*/
|
|
(function(factory, window) {
|
|
if (typeof define === 'function' && define.amd) {
|
|
define(['leaflet'], factory);
|
|
} else if (typeof exports === 'object') {
|
|
module.exports = factory(require('leaflet'));
|
|
}
|
|
if (typeof window !== 'undefined' && window.L) {
|
|
window.L.tooltipLayout = factory(L);
|
|
}
|
|
})(function(L) {
|
|
var TooltipLayout = {};
|
|
|
|
// global variables
|
|
let map;
|
|
let markerList = []; // all markers here
|
|
let polylineList = []; // all polylines here
|
|
|
|
// events
|
|
let _onPolylineCreated = null; // will be called after polyline has been created
|
|
|
|
function initialize(leafletMap, onPolylineCreated) {
|
|
map = leafletMap;
|
|
polylineList = [];
|
|
|
|
//default style
|
|
if (onPolylineCreated) {
|
|
_onPolylineCreated = onPolylineCreated;
|
|
} else {
|
|
_onPolylineCreated = ply => {
|
|
ply.setStyle({
|
|
color: '#90A4AE'
|
|
});
|
|
};
|
|
}
|
|
|
|
setRandomPos(map);
|
|
layoutByForce();
|
|
setEdgePosition();
|
|
drawLine(map);
|
|
|
|
// event registrations
|
|
map.on('zoomstart', function() {
|
|
removeAllPolyline(map);
|
|
});
|
|
|
|
map.on('zoomend', function() {
|
|
setRandomPos(map);
|
|
layoutByForce();
|
|
setEdgePosition();
|
|
drawLine(map);
|
|
});
|
|
|
|
map.on('dragend', function() {
|
|
removeAllPolyline(map);
|
|
setRandomPos(map);
|
|
layoutByForce();
|
|
setEdgePosition();
|
|
drawLine(map);
|
|
});
|
|
|
|
map.on('resize', function() {
|
|
removeAllPolyline(map);
|
|
setRandomPos(map);
|
|
layoutByForce();
|
|
setEdgePosition();
|
|
drawLine(map);
|
|
});
|
|
}
|
|
|
|
function resetMarker(marker) {
|
|
var name = marker.getTooltip().getContent();
|
|
var options = marker.getTooltip().options;
|
|
marker.unbindTooltip();
|
|
|
|
marker.bindTooltip(name, {
|
|
pane: options.pane,
|
|
offset: options.offset,
|
|
classname: 'heading',
|
|
permanent: true,
|
|
interactive: true,
|
|
direction: 'left',
|
|
sticky: 'none',
|
|
opacity: options.opacity
|
|
});
|
|
markerList.push(marker);
|
|
}
|
|
|
|
function getMarkers() {
|
|
return markerList;
|
|
}
|
|
|
|
function getLine(marker) {
|
|
return marker.__ply;
|
|
}
|
|
|
|
function removeAllPolyline(map) {
|
|
var i;
|
|
for (i = 0; i < polylineList.length; i++) {
|
|
map.removeLayer(polylineList[i]);
|
|
}
|
|
polylineList = [];
|
|
}
|
|
|
|
/**
|
|
* Draw lines between markers and tooltips
|
|
* @param map leaflet map
|
|
*/
|
|
function drawLine(map) {
|
|
removeAllPolyline(map);
|
|
for (var i = 0; i < markerList.length; i++) {
|
|
var marker = markerList[i];
|
|
var markerDom = marker._icon;
|
|
var markerPosition = getPosition(markerDom);
|
|
var label = marker.getTooltip();
|
|
|
|
var labelDom = label._container;
|
|
var labelPosition = getPosition(labelDom);
|
|
|
|
var x1 = labelPosition.x;
|
|
var y1 = labelPosition.y;
|
|
|
|
var x = markerPosition.x;
|
|
var y = markerPosition.y;
|
|
|
|
x1 -= 5;
|
|
y1 += 2;
|
|
if (x1 - x !== 0 || y1 - y !== 0) {
|
|
if (x1 + labelDom.offsetWidth < markerPosition.x) {
|
|
x1 += labelDom.offsetWidth;
|
|
}
|
|
if (y1 + labelDom.offsetHeight < markerPosition.y) {
|
|
y1 += labelDom.offsetHeight;
|
|
}
|
|
var lineDest = L.point(x1, y1);
|
|
var destLatLng = map.layerPointToLatLng(lineDest);
|
|
|
|
setTimeout(
|
|
((marker, destLatLng) => () => {
|
|
let ply = L.polyline([marker.getLatLng(), destLatLng]);
|
|
_onPolylineCreated && _onPolylineCreated(ply);
|
|
marker.__ply = ply;
|
|
polylineList.push(ply);
|
|
ply.addTo(map);
|
|
})(marker, destLatLng),
|
|
0
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function setRandomPos() {
|
|
for (var i = 0; i < markerList.length; i++) {
|
|
var marker = markerList[i];
|
|
var label = marker.getTooltip();
|
|
var labelDom = label._container;
|
|
var markerDom = marker._icon;
|
|
var markerPosition = getPosition(markerDom);
|
|
// var angle = Math.floor(Math.random() * 19 + 1) * 2 * Math.PI / 20;
|
|
var angle = ((2 * Math.PI) / 6) * i;
|
|
var x = markerPosition.x;
|
|
var y = markerPosition.y;
|
|
var dest = L.point(
|
|
Math.ceil(x + 50 * Math.sin(angle)),
|
|
Math.ceil(y + 50 * Math.cos(angle))
|
|
);
|
|
L.DomUtil.setPosition(labelDom, dest);
|
|
}
|
|
}
|
|
|
|
function scaleTo(a, b) {
|
|
return L.point(a.x * b.x, a.y * b.y);
|
|
}
|
|
|
|
function normalize(a) {
|
|
var l = a.distanceTo(L.point(0, 0));
|
|
if (l === 0) {
|
|
return a;
|
|
}
|
|
return L.point(a.x / l, a.y / l);
|
|
}
|
|
|
|
function fa(x, k) {
|
|
return (x * x) / k;
|
|
}
|
|
|
|
function fr(x, k) {
|
|
return (k * k) / x;
|
|
}
|
|
|
|
/**
|
|
* get position form el.style.transform
|
|
*/
|
|
function getPosition(el) {
|
|
var translateString = el.style.transform
|
|
.split('(')[1]
|
|
.split(')')[0]
|
|
.split(',');
|
|
return L.point(parseInt(translateString[0]), parseInt(translateString[1]));
|
|
}
|
|
|
|
/**
|
|
* t is the temperature in the system
|
|
*/
|
|
function computePositionStep(t) {
|
|
var area = (window.innerWidth * window.innerHeight) / 10;
|
|
var k = Math.sqrt(area / markerList.length);
|
|
var dpos = L.point(0, 0);
|
|
var v_pos;
|
|
var v;
|
|
var i;
|
|
|
|
for (i = 0; i < markerList.length; i++) {
|
|
v = markerList[i];
|
|
// get position of label v
|
|
v.disp = L.point(0, 0);
|
|
v_pos = getPosition(v.getTooltip()._container);
|
|
|
|
// compute gravitational force
|
|
for (var j = 0; j < markerList.length; j++) {
|
|
var u = markerList[j];
|
|
if (i !== j) {
|
|
var u_pos = getPosition(u.getTooltip()._container);
|
|
dpos = v_pos.subtract(u_pos);
|
|
if (dpos !== 0) {
|
|
v.disp = v.disp.add(
|
|
normalize(dpos).multiplyBy(fr(dpos.distanceTo(L.point(0, 0)), k))
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// compute force between marker and tooltip
|
|
for (i = 0; i < markerList.length; i++) {
|
|
v = markerList[i];
|
|
v_pos = getPosition(v.getTooltip()._container);
|
|
dpos = v_pos.subtract(getPosition(v._icon));
|
|
v.disp = v.disp.subtract(
|
|
normalize(dpos).multiplyBy(fa(dpos.distanceTo(L.point(0, 0)), k))
|
|
);
|
|
}
|
|
|
|
// calculate layout
|
|
for (i = 0; i < markerList.length; i++) {
|
|
var disp = markerList[i].disp;
|
|
var p = getPosition(markerList[i].getTooltip()._container);
|
|
var d = scaleTo(
|
|
normalize(disp),
|
|
L.point(Math.min(Math.abs(disp.x), t), Math.min(Math.abs(disp.y), t))
|
|
);
|
|
p = p.add(d);
|
|
p = L.point(Math.ceil(p.x), Math.ceil(p.y));
|
|
L.DomUtil.setTransform(markerList[i].getTooltip()._container, p);
|
|
}
|
|
}
|
|
|
|
function layoutByForce() {
|
|
var start = Math.ceil(window.innerWidth / 10);
|
|
var times = 50;
|
|
var t;
|
|
for (var i = 0; i < times; i += 1) {
|
|
t = start * (1 - i / (times - 1));
|
|
computePositionStep(t);
|
|
}
|
|
|
|
for (i = 0; i < markerList.length; i++) {
|
|
var disp = markerList[i].disp;
|
|
var p = getPosition(markerList[i].getTooltip()._container);
|
|
var width = markerList[i].getTooltip()._container.offsetWidth;
|
|
var height = markerList[i].getTooltip()._container.offsetHeight;
|
|
p = L.point(Math.ceil(p.x - width / 2), Math.ceil(p.y - height / 2));
|
|
L.DomUtil.setTransform(markerList[i].getTooltip()._container, p);
|
|
}
|
|
}
|
|
|
|
function setEdgePosition() {
|
|
var bounds = map.getBounds();
|
|
var northWest = map.latLngToLayerPoint(bounds.getNorthWest());
|
|
var southEast = map.latLngToLayerPoint(bounds.getSouthEast());
|
|
|
|
for (let i = 0; i < markerList.length; i++) {
|
|
var tooltip = getPosition(markerList[i].getTooltip()._container);
|
|
var marker = getPosition(markerList[i]._icon);
|
|
var width = markerList[i].getTooltip()._container.offsetWidth;
|
|
var height = markerList[i].getTooltip()._container.offsetHeight;
|
|
|
|
var isEdge = false;
|
|
if (marker.x > northWest.x && tooltip.x < northWest.x) {
|
|
tooltip.x = northWest.x;
|
|
isEdge = true;
|
|
} else if (marker.x < southEast.x && tooltip.x > southEast.x - width) {
|
|
tooltip.x = southEast.x - width;
|
|
isEdge = true;
|
|
}
|
|
|
|
if (marker.y > northWest.y && tooltip.y < northWest.y) {
|
|
tooltip.y = northWest.y;
|
|
isEdge = true;
|
|
} else if (marker.y < southEast.y && tooltip.y > southEast.y - height) {
|
|
tooltip.y = southEast.y - height;
|
|
isEdge = true;
|
|
}
|
|
|
|
if (!isEdge) {
|
|
if (marker.x < northWest.x && tooltip.x > northWest.x - width) {
|
|
tooltip.x = northWest.x - width;
|
|
} else if (marker.x > southEast.x && tooltip.x < southEast.x) {
|
|
tooltip.x = southEast.x;
|
|
}
|
|
|
|
if (marker.y < northWest.y && tooltip.y > northWest.y - height) {
|
|
tooltip.y = northWest.y - height;
|
|
} else if (marker.y > southEast.y && tooltip.y < southEast.y) {
|
|
tooltip.y = southEast.y;
|
|
}
|
|
}
|
|
|
|
L.DomUtil.setTransform(markerList[i].getTooltip()._container, tooltip);
|
|
}
|
|
}
|
|
|
|
TooltipLayout['initialize'] = initialize;
|
|
TooltipLayout['resetMarker'] = resetMarker;
|
|
TooltipLayout['getMarkers'] = getMarkers;
|
|
TooltipLayout['getLine'] = getLine;
|
|
TooltipLayout['removeAllPolyline'] = removeAllPolyline;
|
|
|
|
return TooltipLayout;
|
|
}, window); |