我一直在尝试自学 D3.js,但我似乎无法让语义缩放(缩放位置但不是形状)为我工作。
我在这里阅读了 d3 缩放文档,并尝试在功能上复制svg 语义缩放示例代码
这是我的代码:
var X, Y, circle, circles, h, i, j, svg, transform, w, zoom, _i, _j;
w = 1200;
h = 600;
circles = [];
for (j = _i = 0; _i <= 6; j = ++_i) {
for (i = _j = 0; _j <= 12; i = ++_j) {
circles.push({r: 25, cx: i * 50, cy: j * 50});
}
}
X = d3.scale.linear()
.domain([0, 1])
.range([0, 1]);
Y = d3.scale.linear()
.domain([0, 1])
.range([0, 1]);
zoom = d3.behavior.zoom()
.x(X)
.y(Y)
.on("zoom", function() {
return circle.attr("transform", transform);
});
transform = function(d) {
return "translate(" + (X(d.cx)) + ", " + (Y(d.cy)) + ")";
};
svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h)
.call(zoom)
.append("g");
circle = svg.selectAll("circle")
.data(circles)
.enter().append("circle")
.attr("r", function(d) {
return d.r;
}).attr("cx", function(d) {
return d.cx;
}).attr("cy", function(d) {
return d.cy;
}).attr("transform", transform);
Run Code Online (Sandbox Code Playgroud)
jsfiddle 的实时版本。
这应该很简单。我正在创建在没有应用缩放时应该完全接触的圆圈网格(距离为 50 像素,直径为 50 像素)。当我放大时,我希望圆圈分开,鼠标下方的点保持静止。我希望通过应用鼠标滚轮可以平滑和线性地缩放。但是,圆圈应该保持相同的大小,以便在我放大时它们停止接触;当我缩小时它们应该重叠。
取而代之的是,最初,圆圈的展开范围恰好是它们应有的两倍。当我放大和缩小时,中心点不在鼠标下方(并根据我的平移方式四处移动)。缩放是高度非线性的,当我缩小时渐近地接近 1 的比例(圆圈接触),并在我放大时迅速加速。
这看起来很奇怪,我无法发现我的代码和语义缩放示例之间的显着差异,它按预期工作。我得出的结论是,我实际上并不了解 D3 缩放应该如何工作。有人可以帮我解决吗?
您的代码非常接近正确:Working demo。
使用比例来映射对象的位置
而不是保存对象的确切位置,然后使用比例range和domain设置为[0, 1],而是使用比例为您进行映射:
for (j = _i = 0; _i <= 6; j = ++_i) {
for (i = _j = 0; _j <= 12; i = ++_j) {
circles.push({
r: 25,
cx: i,
cy: j,
color: "#000"
});
}
}
X = d3.scale.linear()
.domain([0, 6])
.range([0, w]);
Y = d3.scale.linear()
.domain([0, 12])
.range([0, h]);
Run Code Online (Sandbox Code Playgroud)
这里的变化是现在 D3知道你的视口的纵横比,以及它应该以什么比例转换比例以保持svg鼠标下的静态点。否则,它会尝试放大和缩小正方形,从而产生不和谐的体验。