我想用d3js重新实现以下Processing sketch。
这个精彩的草图使用复杂的pushMatrix,popMatrix层次结构递归地构建图形。
如何在d3.js中实现这一点,因为我们在追加形状或转换时总会立即处理DOM。但是在这个草图中的逻辑中,附加部分似乎必须阻止相应的popMatrix来。感觉就像我必须实现自己的变换和形状堆栈来临时记住转换和形状,直到popMatrix到来,但似乎不是d3.js.
任何建议都非常感谢
PS: 我不想使用processing.js,因为我想使用svg,而不是canvas。
答案 0 :(得分:2)
有趣的问题!以下是我的看法:http://jsfiddle.net/Y48BL/
这更像是一个概念证明;我并没有做所有不同的颜色等等。然而,它证明了一般方法。一般的想法是使用g
元素而不是处理使用的矩阵。两者都用于坐标系的局部变换;如果是g
元素,则相应地设置transform
。新的g
s(矩阵)在递归函数内创建,然后传递到递归的下一级。这与pushMatrix()
相对应。重新开始,我们会继续使用与g
对应的原始popMatrix()
。
圆形和直线绘图的翻译相当简单 - 我发现D3代码更容易阅读。
答案 1 :(得分:0)
所以我想出了这个帮助“类”来完成这个,也许有点矫枉过正,但我会有更多的用例。
var TransformStack = (function () {
function TransformStack() {
this.stack = [];
}
TransformStack.prototype.getCurrentElement = function () {
return this.stack[this.stack.length - 1];
};
TransformStack.prototype.setCurrentElement = function (element) {
this.stack[this.stack.length - 1] = element;
};
TransformStack.prototype.push = function (transformElement) {
this.stack.push(transformElement);
};
TransformStack.prototype.pushAndTransform = function (transformAttr) {
this.push(this.getCurrentElement().append("g").attr("transform", transformAttr));
};
TransformStack.prototype.transform = function (transformAttr) {
this.setCurrentElement(this.getCurrentElement().append("g").attr("transform", transformAttr));
};
TransformStack.prototype.pop = function () {
return this.stack.pop();
};
return TransformStack;
})();
基本上是一个用于推送/弹出g
元素的堆栈,它取代了Lars已经指出的处理中的矩阵方法。有了这个,主程序看起来像
var svg = d3.select("body").append("svg").attr("width", width).attr("height", height)
.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")scale(" + gScale + ")");
var tstack = new TransformStack();
tstack.push(svg);
doIt(nRecursions);
function doIt(n) {
// Circle
tstack.getCurrentElement()
.append("circle")
.attr("r", theSize)
.style("fill", "#fe6b0c")
.style("stroke", "0")
.style("stroke-width", "2")
.style("opacity", 0.3);
if (n != nRecursions) {
for (var i = 0; i < 4; i++) {
tstack.getCurrentElement().append("line")
.style("stroke", "red")
.style("opacity", 0.16)
.attr("x1", Math.random() * 4 - 2)
.attr("x2", Math.random() * 4 - 2)
.attr("y1", theSize / 2.0 + Math.random() * 4 - 2)
.attr("y2", distance - (theSize * theScale / 2.0) - 8.0 + Math.random() * 4 - 2);
}
}
var rot = 0;
tstack.pushAndTransform("scale(" + theScale + ")");
for (var i = 0; i < n; i++) {
if (n > 0) {
tstack.pushAndTransform("translate(0," + distance + ")");
doIt(n - 1);
tstack.pop();
rot = 360 / n;
tstack.transform('rotate(' + rot + ')');
}
}
tstack.pop();
}
}
只是想分享这个,可能对某些人有用。 Lars已经提出了主要观点。