仅允许使用按钮进行缩放,允许使用鼠标拖动进行平移
Allow zoom with buttons only, allow pan with mouse drag
[已更新为现在使用拖动 - 但拖动功能并非 100% 正确,因此仍需要帮助]
我正在尝试使用 d3 以特定方式缩放和平移 svg。我希望用户必须使用 zoom in/zoom out 按钮进行缩放,然后能够通过鼠标拖动进行平移。我还希望将平移限制在边界内。这与纽约时报在他们的 covid 地图上设置的方式相同——https://www.nytimes.com/interactive/2021/us/covid-cases.html(滚动到热点地图)
我在边界内进行了缩放,并且通过注释掉 .call(zoom)
禁用了自由缩放。我只是用按钮缩放并使用 .call(zoom.transform, initialTransform)
。
我正在调用拖动来控制平移,但它跳了一点,不是我想要的流畅交互。它似乎也可能影响缩放。
非常感谢任何指点或帮助。
var width = 960,
height = 500;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.style("background-color", randomColor),
g = svg.append("g");
var zoom = d3.zoom()
.scaleExtent([1, 10])
.on("zoom", zoomed);
let zoomLevel,
tx,
ty
var drag = d3.drag()
.on("drag", dragged);
var initialTransform = d3.zoomIdentity
.translate(0, 0)
.scale(1)
d3.select('#zoom-in').on('click', function () {
zoom.scaleBy(svg.transition().duration(50), 1.3);
});
d3.select('#zoom-out').on('click', function () {
zoom.scaleBy(svg.transition().duration(50), 1 / 1.3);
});
function dragged(event, d) {
var e = event
var dx = e.subject.x,
dy = e.subject.y,
x = e.x,
y = e.y,
translate = [width / 2 - zoomLevel * x, height / 2 - zoomLevel * y];
var transform = d3.zoomIdentity
.translate(translate[0], translate[1])
.scale(zoomLevel);
svg.transition()
.duration(50)
.call(zoom.transform, transform);
}
function zoomed(event) {
zoomLevel = event.transform.k
var e = event
tx = Math.min(0, Math.max(e.transform.x, width - width * e.transform.k)),
ty = Math.min(0, Math.max(e.transform.y, height - height * e.transform.k));
g.attr("transform", [
"translate(" + [tx, ty] + ")",
"scale(" + e.transform.k + ")"
].join(" "));
}
svg
//.call(zoom) // uncomment to disable free zooming. but then can't pan ?
.call(zoom.transform, initialTransform)
.call(drag) // use this to pan
// random circles to fill svg
var circle = g.selectAll("circle")
.data(d3.range(300).map(function (i) {
return {
x: Math.random() * width,
y: Math.random() * height,
r: .01 + Math.random() * 50,
color: randomColor()
};
}).sort(function (a, b) {
return d3.descending(a.r, b.r);
}))
.enter()
.append("circle")
.attr("fill", function (d) { return d.color; })
.attr("cx", function (d) { return d.x; })
.attr("cy", function (d) { return d.y; })
.attr("r", function (d) { return d.r; });
function randomColor() {
return "hsl(" + ~~(60 + Math.random() * 180) + ",80%,60%)";
}
<script src="http://d3js.org/d3.v6.min.js"></script>
<div id="zoom-buttons">
<button id="zoom-in">+</button>
<button id="zoom-out">-</button>
</div>
只需禁用滚轮缩放(并放下拖动):
svg.call(zoom)
.on("wheel.zoom", null);
这里是你的代码有那个变化:
var width = 960,
height = 500;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.style("background-color", randomColor),
g = svg.append("g");
var zoom = d3.zoom()
.scaleExtent([1, 10])
.on("zoom", zoomed);
d3.select('#zoom-in').on('click', function() {
zoom.scaleBy(svg.transition().duration(50), 1.3);
});
d3.select('#zoom-out').on('click', function() {
zoom.scaleBy(svg.transition().duration(50), 1 / 1.3);
});
function zoomed(event) {
zoomLevel = event.transform.k
var e = event
tx = Math.min(0, Math.max(e.transform.x, width - width * e.transform.k)),
ty = Math.min(0, Math.max(e.transform.y, height - height * e.transform.k));
g.attr("transform", [
"translate(" + [tx, ty] + ")",
"scale(" + e.transform.k + ")"
].join(" "));
}
svg.call(zoom)
.on("wheel.zoom", null);
// random circles to fill svg
var circle = g.selectAll("circle")
.data(d3.range(300).map(function(i) {
return {
x: Math.random() * width,
y: Math.random() * height,
r: .01 + Math.random() * 50,
color: randomColor()
};
}).sort(function(a, b) {
return d3.descending(a.r, b.r);
}))
.enter()
.append("circle")
.attr("fill", function(d) {
return d.color;
})
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", function(d) {
return d.r;
});
function randomColor() {
return "hsl(" + ~~(60 + Math.random() * 180) + ",80%,60%)";
}
<script src="http://d3js.org/d3.v6.min.js"></script>
<div id="zoom-buttons">
<button id="zoom-in">+</button>
<button id="zoom-out">-</button>
</div>
[已更新为现在使用拖动 - 但拖动功能并非 100% 正确,因此仍需要帮助]
我正在尝试使用 d3 以特定方式缩放和平移 svg。我希望用户必须使用 zoom in/zoom out 按钮进行缩放,然后能够通过鼠标拖动进行平移。我还希望将平移限制在边界内。这与纽约时报在他们的 covid 地图上设置的方式相同——https://www.nytimes.com/interactive/2021/us/covid-cases.html(滚动到热点地图)
我在边界内进行了缩放,并且通过注释掉 .call(zoom)
禁用了自由缩放。我只是用按钮缩放并使用 .call(zoom.transform, initialTransform)
。
我正在调用拖动来控制平移,但它跳了一点,不是我想要的流畅交互。它似乎也可能影响缩放。
非常感谢任何指点或帮助。
var width = 960,
height = 500;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.style("background-color", randomColor),
g = svg.append("g");
var zoom = d3.zoom()
.scaleExtent([1, 10])
.on("zoom", zoomed);
let zoomLevel,
tx,
ty
var drag = d3.drag()
.on("drag", dragged);
var initialTransform = d3.zoomIdentity
.translate(0, 0)
.scale(1)
d3.select('#zoom-in').on('click', function () {
zoom.scaleBy(svg.transition().duration(50), 1.3);
});
d3.select('#zoom-out').on('click', function () {
zoom.scaleBy(svg.transition().duration(50), 1 / 1.3);
});
function dragged(event, d) {
var e = event
var dx = e.subject.x,
dy = e.subject.y,
x = e.x,
y = e.y,
translate = [width / 2 - zoomLevel * x, height / 2 - zoomLevel * y];
var transform = d3.zoomIdentity
.translate(translate[0], translate[1])
.scale(zoomLevel);
svg.transition()
.duration(50)
.call(zoom.transform, transform);
}
function zoomed(event) {
zoomLevel = event.transform.k
var e = event
tx = Math.min(0, Math.max(e.transform.x, width - width * e.transform.k)),
ty = Math.min(0, Math.max(e.transform.y, height - height * e.transform.k));
g.attr("transform", [
"translate(" + [tx, ty] + ")",
"scale(" + e.transform.k + ")"
].join(" "));
}
svg
//.call(zoom) // uncomment to disable free zooming. but then can't pan ?
.call(zoom.transform, initialTransform)
.call(drag) // use this to pan
// random circles to fill svg
var circle = g.selectAll("circle")
.data(d3.range(300).map(function (i) {
return {
x: Math.random() * width,
y: Math.random() * height,
r: .01 + Math.random() * 50,
color: randomColor()
};
}).sort(function (a, b) {
return d3.descending(a.r, b.r);
}))
.enter()
.append("circle")
.attr("fill", function (d) { return d.color; })
.attr("cx", function (d) { return d.x; })
.attr("cy", function (d) { return d.y; })
.attr("r", function (d) { return d.r; });
function randomColor() {
return "hsl(" + ~~(60 + Math.random() * 180) + ",80%,60%)";
}
<script src="http://d3js.org/d3.v6.min.js"></script>
<div id="zoom-buttons">
<button id="zoom-in">+</button>
<button id="zoom-out">-</button>
</div>
只需禁用滚轮缩放(并放下拖动):
svg.call(zoom)
.on("wheel.zoom", null);
这里是你的代码有那个变化:
var width = 960,
height = 500;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.style("background-color", randomColor),
g = svg.append("g");
var zoom = d3.zoom()
.scaleExtent([1, 10])
.on("zoom", zoomed);
d3.select('#zoom-in').on('click', function() {
zoom.scaleBy(svg.transition().duration(50), 1.3);
});
d3.select('#zoom-out').on('click', function() {
zoom.scaleBy(svg.transition().duration(50), 1 / 1.3);
});
function zoomed(event) {
zoomLevel = event.transform.k
var e = event
tx = Math.min(0, Math.max(e.transform.x, width - width * e.transform.k)),
ty = Math.min(0, Math.max(e.transform.y, height - height * e.transform.k));
g.attr("transform", [
"translate(" + [tx, ty] + ")",
"scale(" + e.transform.k + ")"
].join(" "));
}
svg.call(zoom)
.on("wheel.zoom", null);
// random circles to fill svg
var circle = g.selectAll("circle")
.data(d3.range(300).map(function(i) {
return {
x: Math.random() * width,
y: Math.random() * height,
r: .01 + Math.random() * 50,
color: randomColor()
};
}).sort(function(a, b) {
return d3.descending(a.r, b.r);
}))
.enter()
.append("circle")
.attr("fill", function(d) {
return d.color;
})
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", function(d) {
return d.r;
});
function randomColor() {
return "hsl(" + ~~(60 + Math.random() * 180) + ",80%,60%)";
}
<script src="http://d3js.org/d3.v6.min.js"></script>
<div id="zoom-buttons">
<button id="zoom-in">+</button>
<button id="zoom-out">-</button>
</div>