1
私はアニメーション化しようとしているスライドバーの表示を持っています。基本的に、横に横に2つのバーがあり、それぞれが全幅のパーセンテージを占めています。数値が変わると、幅とxの位置がアニメーション化され、新しいパーセンテージが反映されます。d3js最初にアニメートしないでください
項目が最初に読み込まれるときにアニメーションを必要としないことを除いて、数字が変更された場合のみ、うまくいきます。今は、アイテムの左側から所定の場所に撃たれます。
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();
};
コードをStackExchangeスニペットに変更して実行することができますか?何が起こっているのかを視覚化するのは難しいです。 – Ian
OK、完了!最初の読み込み時に左からアニメーションがどのようにあるかに注目してください。私はむしろ、最初の読み込み時にアニメーションが存在しないと思います。 –