用d3反射元素时如何正确过渡?

问题描述 投票:0回答:1

我有一个

path
元素,正在使用新数据进行更新。然后它被重新定位并被反射。所有这些都工作正常。无法正常工作的部分是过渡。由于我反映的方式(使用
scale
translate
),它在返回之前移过了正确的位置。

如何在不超过新位置的情况下从初始 x 轴位置过渡到新的 x 轴位置?

jsFiddle

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());
svg d3.js css-transforms
1个回答
0
投票

两个问题:

  1. transform
    与其他类似变换的属性(如
    scale
    )并不能很好地配合。 (至少,很难推理。)在
    transform
    中完成所有事情要容易得多。
  2. 翻译不应根据是否
    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})`
    )
}

三角形从右向左移动时会垂直翻转。

© www.soinside.com 2019 - 2024. All rights reserved.