我有一个
path
元素,正在使用新数据进行更新。然后它被重新定位并被反射。所有这些都工作正常。无法正常工作的部分是过渡。由于我反映的方式(使用 scale
和 translate
),它在返回之前移过了正确的位置。
如何在不超过新位置的情况下从初始 x 轴位置过渡到新的 x 轴位置?
HTML:
<button id="reflect">reflect</button>
<div id="container"></div>
JS:
import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
const width = 500;
const height = 200;
const x = d3.scaleLinear()
.domain([0, 100])
.range([0, width]);
const y = d3.scaleLinear()
.domain([0, 50])
.range([height, 0]);
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height);
svg.append("g")
.attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(x));
svg.append("g")
.call(d3.axisLeft(y));
const data = [{
x: 60,
y: 20
}];
const reflectedData = [{
x: 30,
y: 20
}];
svg.selectAll('arrow')
.data(data)
.join('path')
.attr('class', 'arrow')
.attr('d', 'M0,0 L80,0 L80, 50z')
d3.select('#reflect')
.on('click', () => {
svg.selectAll('.arrow')
.data(reflectedData)
updateArrow(2000)
})
updateArrow(0);
function updateArrow(duration) {
const midpoint = x.domain()[1] / 2
svg.selectAll('.arrow')
.transition()
.duration(duration)
.style('scale', d => d.x < midpoint ? '-1 1' : '1 1')
.style('transform', d => {
const translateX = d.x < midpoint ? -x(d.x) : x(d.x);
return `translate(${translateX}px, ${y(d.y)}px)`;
})
}
container.append(svg.node());
两个问题:
transform
与其他类似变换的属性(如 scale
)并不能很好地配合。 (至少,很难推理。)在transform
中完成所有事情要容易得多。d.x < midpoint
而改变;只有秤应该。function updateArrow(duration) {
const midpoint = x.domain()[1] / 2
svg.selectAll('.arrow')
.transition()
.duration(duration)
.style('transform', d =>
`translate(${x(d.x)}px, ${y(d.y)}px) scaleX(${d.x < midpoint ? -1 : 1})`
)
}
三角形从右向左移动时会垂直翻转。