Dan*_*iel 11 javascript svg d3.js
我必须创建一个由块的层次结构组成的图表(一个包含较小块的大块,其中包含其他块).
数据是这些块的层次结构
{
element: {name: test, geometry: [..], orientation: '180'}
element: {name: test2, geometry: [..], orientation: 'none'}
element: {name: test3, geometry: [..], orientation: 'flipX'}
element: {
name: test4,
geometry: [..],
orientation: '90'
children:
[
element: {name: test5, geometry: [..], orientation: '180'}
element: {name: test6, geometry: [..], orientation: 'none'}
]
}
}
Run Code Online (Sandbox Code Playgroud)
每个块都有一个几何(边数组)和一个方向:
边的坐标相对于父块的原点.
因此,如果旋转主块,子块的坐标系也将旋转.
我需要绘制它,然后根据指标更改每个块的填充颜色.
我现在这样做的方法是递归地解析该层次结构并为每个层次附加svg元素:
<svg>
<g><path>
<g><path></g>
<g><path></g>
<g><path>
<g><path></g>
</g>
</g>
</svg>
Run Code Online (Sandbox Code Playgroud)
当我在已经旋转的组内绘制时,这有助于所有坐标继承.
我不确定这是最好的方法,因为我没有使用.data()append()enter()函数,因为我不知道如何绘制imbricated元素.这些块还有标签和指示其原点的位置,但我不包括这个以简化.
有一个更好的方法吗?
谢谢!
只要您不使用模拟,您就真的不需要打电话.data()
。您可以使用循环函数来解析元素树并将元素附加到特定的 SVG 组。由于您正在 DOM 上应用转换(例如旋转/缩放),我认为最好的解决方案是让 DOM 模仿您的数据树(这对于旋转和翻转是必要的)。翻转是通过负向缩放 DOM 元素来实现的,如下所示:
if (orientation === 'flipX') {
ref.attr('transform', `scale(-1, 1) translate(${-ref.node().getBBox().width}, 0)`);
}
if (orientation === 'flipY') {
ref.attr('transform', `scale(1, -1) translate(0, ${-ref.node().getBBox().height})`);
}
Run Code Online (Sandbox Code Playgroud)
您需要在翻转时测量组的边界框并应用变换,以便通过中点翻转框。
下面的代码允许您解析树并通过特定转换附加 DOM 元素:
const svg = d3.select(svgDOM);
svg.selectAll("*").remove();
const group = svg.append('g');
group.attr('transform', 'translate(200,100)');
const colors = d3.schemeAccent;
let parseDataArr = (parent, arr) => {
const group = parent.append('g');
arr.forEach((elem, index) => {
const {element: {geometry, orientation, children}} = elem;
const ref = group.append('g');
ref
.append('path')
.attr('fill', colors[index])
.attr('opacity', 0.4)
.attr('stroke', '#000')
.attr('stroke-width', 1)
.attr('d', `M ${geometry.join('L')} z`);
if (["none", "flipX", "flipY"].indexOf(orientation) === -1) {
ref.attr('transform', `rotate(${orientation})`);
}
if (children) {
parseDataArr(ref, children);
}
if (orientation === 'flipX') {
ref.attr('transform', `scale(-1, 1) translate(${-ref.node().getBBox().width}, 0)`);
}
if (orientation === 'flipY') {
ref.attr('transform', `scale(1, -1) translate(0, ${-ref.node().getBBox().height})`);
}
});
}
parseDataArr(group, data);
Run Code Online (Sandbox Code Playgroud)
这是我用来测试实现的示例代码:https://observablehq.com/@cstefanache/test-svg-transforms
归档时间: |
|
查看次数: |
289 次 |
最近记录: |