我正在尝试使用d3的平移/缩放功能在屏幕上绘制框,这样当您单击一个框时,会出现一个新框并将其余框移到右侧,以便新框是在画布的中心。平移将允许我滚动浏览我绘制的所有框。
这是我的jsfiddle:http://jsfiddle.net/uUTBE/1/
这是我的初始化缩放/平移的代码: svg.call(d3.behavior.zoom()。on(“zoom”,redraw));
function redraw() {
d3.select(".canvas").attr("transform",
"translate(" + d3.event.translate + ")"
+ " scale(" + d3.event.scale + ")");
}
这是我绘制框的代码:
function drawBox(x, y) {
var boxGroup = canvas.append("g");
boxGroup.append("rect")
.attr("x", x)
.attr("y", y)
.attr("height", 100)
.attr("width", 100)
.attr("fill", function () {
var i = Math.floor(Math.random() * 4);
if (i === 1) return "red";
else if (i === 2) return "blue";
else if (i === 3) return "yellow";
else return "green";
})
.on("click", function () {
counter++;
d3.select(".canvas")
.transition()
.duration(1000)
.attr('transform', "translate(300,0)");
drawBox(x - counter * 120, y);
});
}
我有这个小提琴的多个问题,但我的两个主要问题是:
1)我如何做到这一点,当我第二次点击一个新的盒子时盒子相应地移动(即当我点击盒子时,旧盒子向右移动并出现一个新盒子,但是当我点击新框,旧框不会向右移动。
2)为什么当我点击新框时,较新的框之间有很大的间距? (仅在尝试在屏幕上放置3个框后才会发生。)
感谢任何提示表示赞赏!
答案 0 :(得分:2)
我认为围绕transform
存在一些混淆。对于单个元素,transform
属性是静态的,而不是累积的 - 因此多次设置.attr('transform', "translate(300,0)")
将在第一次后无效。看起来您的新盒子的放置逻辑也已关闭。
如果您退后一步(假设我理解您要做的事情),这里所需的定位逻辑非常简单:
每次添加新框时,框架所有框都移动120px,因此需要x
- 120 * counter
的翻译。
新框需要偏离新的框架位置,因此需要设置x
-120 * counter
。
缩放需要考虑当前画布偏移量。
(1)可以在你的点击处理程序中完成:
canvas
.transition()
.duration(1000)
.attr('transform', "translate(" + (offset * counter) + ",0)");
(2)非常容易应用于您正在包装框中的g
元素:
var boxGroup = canvas.append("g")
.attr('transform', 'translate(' + (-offset * counter) + ',0)');
(3)可以添加到您的redraw
处理程序中:
function redraw() {
var translation = d3.event.translate,
newx = translation[0] + offset * counter,
newy = translation[1];
canvas.attr("transform",
"translate(" + newx + "," + newy + ")" + " scale(" + d3.event.scale + ")");
}
请在此处查看工作小提琴:http://jsfiddle.net/nrabinowitz/p3m8A/