javascript - d3.js 过渡的问题 - 使用 GeoJson 的多边形变形不正确
问题描述
我正在尝试使用 D3 叠加创建传单地图。在叠加层中,我想展示一些能够在它们之间动态切换的形状——从一个平滑转换到另一个(变形)。我设法设置了一些基本的工作代码,它们或多或少可以满足我的需要,但有一个问题。
当我按下按钮改变形状时,最终的形状“展开”而不是平滑过渡,而不是前一个形状。我究竟做错了什么?我在网络上的某些地方看到 .transition() 应该完成这项工作,但在我的情况下不是。我需要使用某种插值吗?或者也许准备数据?我会很感激任何帮助!
这是我的代码,我还包括一个演示链接:(有一个地图和两个按钮来改变形状)
https://jsfiddle.net/xiaoss/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);
}
解决方案
我想通了,问题出在数据上——默认情况下,d3 似乎无法处理这样的形状。当我将两个数字对齐以使其更相似并订购点时,它可以正常工作。我想我需要使用更高级的变形功能,比如flubber https://bestofjs.org/projects/flubber
它适用于这两个数字:
{
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [
[
[
-63.334278,
-8.430061
],
[
-64.029526,
-16.512253
],
[
-44.272875,
-19.923701
],
[
-48.038806,
-7.05227
],
[
-63.334278,
-8.430061
]
]
],
"type": "Polygon"
},
"id": "5142b4060fc932fe302b7ae7258dc916"
}
],
"type": "FeatureCollection"
}
{
"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"
}
推荐阅读
- html - 嵌套 flexbox 布局导致可滚动区域行为不端
- r - 在主标题下添加副标题或在R中的y轴下添加副标题
- java - 为什么从 JetBrains dotMemory 拍摄快照时总内存会变高
- google-ad-manager - 您如何在 Google Ad Manager 中使用不同尺寸的不同广告单元来投放不同的广告?
- matlab - 如何从 Matlab 中的绘图中截取部分数据
- google-apps-script - 谷歌表格脚本功能——使单元格内容全部大写,除非单元格包含超链接
- html - 为什么内容比 div 大?
- javascript - 单击按钮时重绘屏幕
- storage - 如何将外部硬盘驱动器从路由器连接到我的 Iphone (NAS)
- cpu-architecture - 确定 12 位指令微处理器的最大内存大小、最大唯一操作数和无符号常量的最大值