Я пытаюсь создать листовую карту с наложением D3. В оверлее я хотел бы представить некоторые формы с возможностью динамического переключения между ними - плавного перехода от одного к другому (морфинг). Мне удалось настроить некоторый основной рабочий код, который более или менее выполняет то, что мне нужно, но есть одна проблема.
Когда я нажимаю кнопку, чтобы изменить форму, вместо плавного перехода, окончательная форма «разворачивается», безмного уважения к предыдущему. Что я делаю неправильно? Я видел в некоторых местах в Интернете, что .transition () должен делать эту работу, но не в моем случае. Нужно ли использовать какую-то интерполяцию? Или, может быть, подготовить данные? Буду признателен за любую помощь!
Вот мой код, я также включаю ссылку на демонстрацию: (Там есть карта и две кнопки для изменения формы)
https://jsfiddle.net/xianoss/dLk65pyu/
JS:
var figure1 = {
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [
[
[
-72.256697,
1.150426
],
[
-74.579093,
-7.698964
],
[
-67.075969,
-21.93404
],
[
-68.088295,
-34.291664
],
[
-55.285345,
-31.492019
],
[
-44.923888,
-19.0337
],
[
-46.591249,
-5.569695
],
[
-59.394199,
1.983787
],
[
-65.051316,
2.578799
],
[
-72.256697,
1.150426
]
]
],
"type": "Polygon"
},
"id": "c9cd572980c7663fc538a70f2092af60"
}],
"type": "FeatureCollection"
}
var figure2 = {
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [
[
[
-62.921997,
-10.077123
],
[
-62.160825,
-24.409954
],
[
-51.208418,
-18.349548
],
[
-54.379964,
-7.653952
],
[
-62.921997,
-10.077123
]
]
],
"type": "Polygon"
},
"id": "9db95177c15f320f2293f918b58ff94b"
}],
"type": "FeatureCollection"
}
var map = L.map('mapid').setView([-13.294, -60.624], 4);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
maxZoom: 18,
id: 'mapbox.streets',
}).addTo(map);
var svg = d3.select(map.getPanes().overlayPane).append("svg");
var g = svg.append("g").attr("class", "leaflet-zoom-hide");
draw(figure1, figure2)
function draw(collection1, collection2) {
collection = collection1
var transform = d3.geo.transform({
point: projectPoint
})
var geoGenerator = d3.geo.path().projection(transform);
var feature = g.selectAll("path")
.data(collection.features)
.enter().append("path")
.attr("class", "green");
map.on("viewreset", reset);
reset();
$("#btn1").click(function() {
update(collection1, "green")
});
$("#btn2").click(function() {
update(collection2, "red")
});
function update(data, color) {
var t = d3.transition()
.duration(750);
var sel = g.selectAll("path")
.data(data.features)
.attr("class", color)
sel.enter()
.append("path")
sel
.transition().duration(1000)
.attr("d", geoGenerator)
}
function reset() {
var bounds = geoGenerator.bounds(collection),
topLeft = bounds[0],
bottomRight = bounds[1];
svg.attr("width", bottomRight[0] - topLeft[0])
.attr("height", bottomRight[1] - topLeft[1])
.style("left", topLeft[0] + "px")
.style("top", topLeft[1] + "px");
g.attr("transform", "translate(" + -topLeft[0] + "," + -topLeft[1] + ")");
feature.attr("d", geoGenerator);
}
function projectPoint(x, y) {
var point = map.latLngToLayerPoint(new L.LatLng(y, x));
this.stream.point(point.x, point.y);
}
}
HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/styles.css?v=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin="" />
</head>
<body>
<div>
<button type="button" id="btn1">One</button>
<button type=" button" id="btn2">Two</button>
</div>
<div id="mapid"></div>
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="https://d3js.org/queue.v1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.5/leaflet.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
</body>
</html>
CSS:
#mapid {
height: 500px;
}
svg {
position: relative;
}
path {
fill-opacity: .7;
stroke: rgb(90, 89, 89);
stroke-width: 3.5px;
}
.red {
fill: rgb(255, 82, 14);
}
.green {
fill: rgb(16, 236, 64);
}