【问题标题】:Changing direction of D3 animation / transition?改变 D3 动画/过渡的方向?
【发布时间】:2019-12-05 10:24:28
【问题描述】:

我最近构建了一个小型热图,其单个单元格在页面加载后一个接一个地淡入显示:

https://codepen.io/ChrisBean/pen/KKwpmjb

通过将单元格的初始不透明度值设置为0来触发淡入动画

squares.transition()
    .duration(1000)
    .delay((_d, i) => i * 200)
    .style('opacity', 1);

截至目前,单元格从底部逐列淡入到顶部。我希望它们逐行从左到右淡入。这是我的目标,在 thinkpad 上用钢笔绘图快速可视化:

任何人都可以推动我在过渡触发器中改变方向的正确方向吗?

【问题讨论】:

    标签: javascript html css d3.js


    【解决方案1】:

    在 D3 中没有 “过渡方向” 这样的东西。这里的整个问题是您正在使用元素的索引来设置延迟。话虽如此,只需更改 data 数组中对象的顺序,以便索引匹配您想要的方向。

    例如:

    data.sort(function(a,b){
        return myVars.indexOf(b.variable) - myVars.indexOf(a.variable) || 
            myGroups.indexOf(a.group) - myGroups.indexOf(b.group)
    });
    

    以下是更改后的代码:

    // set the dimensions and margins of the graph
    const margin = {
      top: 0,
      right: 0,
      bottom: 0,
      left: 0,
    };
    const width = 400 - margin.left - margin.right;
    const height = 400 - margin.top - margin.bottom;
    
    // append the svg object to the body of the page
    // eslint-disable-next-line no-undef
    const svg = d3.select('#my_dataviz')
      .append('svg')
      .attr('viewBox', '0 0 900 320')
      .append('g')
      .attr('transform',
        `translate(${margin.left},${margin.top})`);
    
    // Labels of row and columns
    const myGroups = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'];
    const myVars = ['v1', 'v2', 'v3', 'v4', 'v5', 'v6', 'v7', 'v8', 'v9', 'v10'];
    
    // Build X scales and axis:
    const x = d3.scaleBand()
      .range([0, width])
      .domain(myGroups)
      .padding(0.00);
    svg.append('g')
      .attr('transform', `translate(0,${height})`)
      .call(d3.axisBottom(x));
    
    // Build X scales and axis:
    const y = d3.scaleBand()
      .range([height, 0])
      .domain(myVars)
      .padding(0.00);
    svg.append('g')
      .call(d3.axisLeft(y));
    
    // Build color scale
    const myColor = d3.scaleLinear()
      .range(['white', '#363636'])
      .domain([1, 100]);
    
    // Read the data
    d3.csv('https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/heatmap_data.csv', (data) => {
      data.sort(function(a, b) {
        return myVars.indexOf(b.variable) - myVars.indexOf(a.variable) || myGroups.indexOf(a.group) - myGroups.indexOf(b.group)
      });
      // create a tooltip
      const tooltip = d3.select('#my_dataviz')
        .append('div')
        .style('opacity', 0)
        .attr('class', 'tooltip')
        .style('background-color', 'white')
        .style('border', 'solid')
        .style('border-width', '2px')
        .style('border-radius', '5px')
        .style('padding', '5px');
    
      // Three function that change the tooltip when user hover / move / leave a cell
      const mouseover = function() {
        tooltip.style('opacity', 1);
      };
      const mousemove = function(d) {
        tooltip
          .html(`Client Branch:${d.value} <br>
                 Project:   <br>`)
          .style('left', `${d3.mouse(this)[0] + 70}px`)
          .style('top', `${d3.mouse(this)[1]}px`);
      };
      const mouseleave = function() {
        tooltip.style('opacity', 0);
      };
    
      // add the squares
      const squares = svg.selectAll()
        .data(data, (d) => `${d.group}:${d.variable}`)
        .enter()
        .append('rect')
        .attr('x', (d) => x(d.group))
        .attr('y', (d) => y(d.variable))
        .attr('width', x.bandwidth())
        .attr('height', y.bandwidth())
        .style('fill', (d) => myColor(d.value))
        .style('opacity', 0)
        .on('mouseover', mouseover)
        .on('mousemove', mousemove)
        .on('mouseleave', mouseleave);
    
      squares.transition()
        .duration(1000)
        .delay((_d, i) => i * 200)
        .style('opacity', 1);
    });
    <!DOCTYPE html>
    <meta charset="utf-8">
    
    <!-- Load d3.js -->
    <script src="https://d3js.org/d3.v4.js"></script>
    
    
    <!-- Create a div where the graph will take place -->
    <div id="my_dataviz"></div>

    【讨论】:

    • “D3 中没有“过渡方向”这样的东西。“感谢您清楚地指出这一点,这解释了为什么我根据方向寻找解决方案是徒劳的,而我应该寻找对象的顺序。我认为您的意见对我的帮助远不止这个例子!