javascript - d3js 不要先输入动画

标签 javascript d3.js

我正在尝试为滑动条显示设置动画。基本上,有两个水平相邻的条形,每个条形占据总宽度的一定百分比。随着数字的变化,宽度和 x 位置会发生动画以反射(reflect)新的百分比。

它工作正常,只是我不想在项目首次加载时播放动画,而只在数字更改时播放。现在,它从元素的左侧射入到位。

edit2:这是代码片段中的第一个版本:

const d3SlidingBar = {};
//  data should simply be an array with two numbers
//  future: add support for arbitrary number of numbers
d3SlidingBar.create = function create(el, data, formatText) {
  const svg = d3.select(el).append('svg')
    .attr('class', 'sliding-bar__svg')
    .attr('width', '100%')
    .attr('height', '100%');

  svg.append('g')
    .attr('class', 'sliding-bar__svg__bars')
  //  try 100% here. Should work.
    .attr('width', el.offsetWidth)
    .attr('height', el.offsetHeight);

  if (data) this.update(el, data, formatText);
};

d3SlidingBar.update = function update(el, data, formatText) {
  // Re-compute the scales, and render the data points
  const scales = this.scale(el, data);
  this.drawBars(el, scales, data);
  this.drawNumbers(el, scales, data, formatText);
};

d3SlidingBar.scale = (el, data) =>
  d3.scaleLinear()
  .range([0, el.offsetWidth])
  .domain([0, data.reduce((a, b) => a + b)]);


d3SlidingBar.drawBars = (el, scale, data) => {
  const t = d3.transition()
    .duration(450);

  const barHeight = el.offsetHeight;

  //  keep track of right side of stacks of bar so bars can stack further.
  //  Useful if we have more than two bars.
  let greatestWidth = 0;

  const g = d3.select(el).selectAll('.sliding-bar__svg__bars');

  const bar = g.selectAll('.sliding-bar__svg__bar')
    .data(data);

  bar.enter().append('rect')
    .attr('class', (point, ind) => `sliding-bar__svg__bar sliding-bar__svg__bar--${ind}`)
    .attr('height', barHeight)
    .merge(bar)
    .transition(t)
    .attr('width', point => scale(point))
    .attr('x', (point) => {
      const oldGreatestWidth = greatestWidth;
      greatestWidth += scale(point);
      return oldGreatestWidth;
    });

  bar.exit().remove();
};

//  This function needs an overhaul, but I'm not sure how
d3SlidingBar.drawNumbers = (el, scale, data, formatText = point => point) => {
  const barHeight = el.offsetHeight;

  //  keep track of right side of stacks of bar so bars can stack further.
  //  Bar position is used to position text

  const g = d3.select(el).selectAll('.sliding-bar__svg__bars');

  const number = g.selectAll('.sliding-bar__svg__number')
    .data(data);

  number.enter().append('text')
    .style('font-size', barHeight - 10)
    .attr('y', barHeight - 10)
    .attr('class', (point, ind) => `sliding-bar__svg__number sliding-bar__svg__number--${ind}`)
    .merge(number)
    .attr('y', barHeight - 10)
    .style('font-size', barHeight - 10)
    .text(point => formatText(point))
    .attr('x', function xPosition(point, ind) {
      return (ind % 2) ?
        el.offsetWidth - this.getComputedTextLength() - 8
        : (0 + 8);
    });

  // This is for if we want the number to stay at the left of each bar,
  // const greatestWidth = 0;
  //
  //  ...number.enter...
  //
  // useful for more than 2 bars.
  // .attr('x', (point, ind) => {
  //   const oldGreatestWidth = greatestWidth;
  //   greatestWidth += scale(point);
  //   return oldGreatestWidth + 5;
  // })
  //

  number.exit().remove();
};


let count = 0;
const data = [[50, 50], [75,25]];
const formatText = text => `%${text}`;

const bars = document.getElementById('bars')

d3SlidingBar.create(bars, data[0], formatText)

setInterval(() => {
  count++;
  d3SlidingBar.update(bars, data[count % 2], formatText)
}, 1000)
.sliding-bar__container {
  width: 400px;
  height: 50px;
  border: 2px solid black;
  background-color: black;
  position: absolute;
  display: inline-block;
}

.sliding-bar__svg__bars {
  height: 100%;
  width: 100%;
}

.sliding-bar__svg__bar--0 {
  fill: #33708E;
}

.sliding-bar__svg__bar--1 {
  fill: #CF8D3A;
}

.sliding-bar__svg__number {
  fill: white;
  font-weight: bold;
}
<script src="https://d3js.org/d3.v4.min.js"></script>

<body>
  <div class="sliding-bar__container" id='bars'>
  </div>
</body>

编辑:我尝试将其更改为这样,但现在每次更新时,条形图都会从右侧射出......

d3SlidingBar.drawBars = (el, scale, data) => {
  const t = d3.transition()
    .duration(450);

  const barHeight = el.offsetHeight;

  //  keep track of right side of stacks of bar so bars can stack further.
  //  Useful if we have more than two bars.
  let greatestWidth = 0;
  let greatestWidthEnter = 0;

  const g = d3.select(el).selectAll('.sliding-bar__svg__bars');

  const bar = g.selectAll('.sliding-bar__svg__bar')
    .data(data);

  bar.transition(t)
    .attr('width', point => scale(point))
    .attr('x', (point) => {
      const oldGreatestWidth = greatestWidth;
      greatestWidth += scale(point);
      return oldGreatestWidth;
    });


  bar.enter().append('rect')
    .attr('class', (point, ind) => `sliding-bar__svg__bar sliding-bar__svg__bar--${ind}`)
    .attr('height', barHeight)
    .merge(bar)
    .attr('width', point => scale(point))
    .attr('x', (point) => {
      const oldGreatestWidth = greatestWidthEnter;
      greatestWidthEnter += scale(point);
      return oldGreatestWidth;
    });

  bar.exit().remove();
};

最佳答案

好吧,我明白了。

  bar
    .transition(t)
    .attr('width', point => scale(point))
    .attr('x', (point) => {
        const oldGreatestWidth = greatestWidth;
        greatestWidth += scale(point);
        return oldGreatestWidth;
    });




bar.enter().append('rect')
    .attr('class', (point, ind) => `sliding-bar__svg__bar sliding-bar__svg__bar--${ind}`)
    .attr('height', barHeight)
    .attr('width', point => scale(point))
    .attr('x', (point) => {
      const oldGreatestWidth = greatestWidth;
      greatestWidth += scale(point);
      return oldGreatestWidth;
    });

基本上,这是我的第二次尝试,但删除了 merge(bar) 行。我不确定 merge() 的作用,但它似乎对于我正在做的任何事情都是不必要的。我认为每次使用更新模式时都需要它,但没有它它也能正常工作。

我认为如果 merge(bar) 位于 Enter() block 的末尾而不是中间,它仍然有效。

关于javascript - d3js 不要先输入动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40732889/

相关文章:

javascript - D3.js 在图表之间转换

javascript - Topojson 动画一次飞行

javascript - elasticitY(true) with range 图表不适应新范围

javascript - 如何用d3.js绘制折线图?

javascript - Turbolinks 和 Bootstrap Tab 激活

javascript - Ios Safari 的复制按钮

javascript - 滚动后如何加载ajax?

javascript - 如何在不覆盖整个蓝图的情况下扩展 Sails.js 中蓝图的功能?

javascript - 将多个 colorAxis 对象应用于 dimple.js 中的线图与气泡图时,行为不一致

javascript - 预检响应中的 Access-Control-Allow-Headers 不允许请求 header 字段 Time-Zone