我有一個用 d3js v4 和 topojson 制作的世界地圖,它具有縮放/拖動/圓圈。一切似乎都很好,除了我無法將圓圈與縮放比例一起縮放。
當我滾動到地圖時,我的圓圈保持相同的大小,這使得它們與地圖相比變得更大。
縮放時如何將變換應用于圓圈?
var width = 660,
height = 400;
var zoom = d3.zoom()
.scaleExtent([1, 10])
.on("zoom", zoomed);
var projection = d3.geoMercator()
.center([50, 10]) //long and lat starting position
.scale(150) //starting zoom position
.rotate([10,0]); //where world split occurs
var svg = d3.select("svg")
.attr("width", width)
.attr("height", height)
.call(zoom);
var path = d3.geoPath()
.projection(projection);
var g = svg.append("g");
//Zoom functionality
function zoomed() {
const currentTransform = d3.event.transform;
g.attr("transform", currentTransform);
}
d3.select(".zoom-in").on("click", function() {
zoom.scaleBy(svg.transition().duration(750), 1.2);
});
d3.select(".zoom-out").on("click", function() {
zoom.scaleBy(svg.transition().duration(750), 0.8);
});
// load and display the world and locations
d3.json("https://gist.githubusercontent.com/d3noob/5193723/raw/world-110m2.json", function(error, topology) {
var world = g.selectAll("path")
.data(topojson.object(topology, topology.objects.countries).geometries)
.enter()
.append("path")
.attr("d", path)
;
var locations = g.selectAll("circle")
.data(devicesAll)
.enter()
.append("circle")
.attr("cx", function(d) {return projection([d.LastLocation.lon, d.LastLocation.lat])[0];})
.attr("cy", function(d) {return projection([d.LastLocation.lon, d.LastLocation.lat])[1];})
.attr("r", 2)
.style("fill", "black")
.style("opacity", 1)
;
var simulation = d3.forceSimulation()
.force('x', d3.forceX().x(function(d) {return projection([d.LastLocation.lon, d.LastLocation.lat])[0]}))
.force('y', d3.forceY().y(function(d) {return projection([d.LastLocation.lon, d.LastLocation.lat])[1]}))
.force("charge", d3.forceManyBody().strength(0.5)) // Nodes are attracted one each other of value is > 0
.force("collide", d3.forceCollide().strength(.1).radius(2).iterations(2)) // Force that avoids circle overlapping
// Apply these forces to the nodes and update their positions.
// Once the force algorithm is happy with positions ('alpha' value is low enough), simulations will stop.
simulation
.nodes(devicesAll)
.on("tick", function(d){
locations
.attr("cx", function(d){ return d.x; })
.attr("cy", function(d){ return d.y; })
});
uj5u.com熱心網友回復:
如果我正確理解您的問題,您需要將其添加到您的縮放行為中。
//Zoom functionality
function zoomed() {
const currentTransform = d3.event.transform;
g.attr("transform", currentTransform);
}
在這里,您將轉換應用于元素,這很好。但是,您沒有對半徑應用任何邏輯。該邏輯由您決定,它將取決于k轉換事件 ( currentTransform.k)的屬性。我將為您的半徑使用一些虛擬邏輯。您的比例范圍在 1 到 10 之間,您需要一個邏輯,其中半徑隨著縮放比例的增加(更大的 k)而減小。同樣重要的是你的半徑不要低于 1,因為圓的面積會減少得更快(記住面積取決于 r^2,而 r^2 < r for r < 1)所以我的邏輯會是:半徑為 2.1 - (k / 10)。同樣,我過于簡單化了,您可以根據具體情況更改或調整它。
最后,它應該是這樣的:
//Zoom functionality
function zoomed() {
const currentTransform = d3.event.transform;
g.attr("transform", currentTransform);
g.selectAll("circle")
.attr("r", 2.1 - (currentTransform.k / 10))
}
我還沒有測驗過代碼,但請告訴我這是否有效!如果需要,也許您可??以將其添加到 jsfiddle
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/359358.html
標籤:javascript svg d3.js 拓扑文件
上一篇:antd:添加自定義svg圖示
