const width = 256; const height = 128; const data1 = [{ id: 'user-1', page: 'page-A' }, { id: 'user-2', page: 'page-B' }]; const data2 = [{ id: 'user-2', page: 'page-A' }, { id: 'user-1', page: 'page-B' }]; function getX(page) { if (page === 'page-A') { return 50; } else { return width - 50; } } const svg = d3.select('body').append('svg') .attr('width', width) .attr('height', height); function draw(data) { // with key function const circles = svg.selectAll('circle').data(data, d => d.id); // 不要なノードの削除 circles.exit().remove(); // ノードの追加 circles.enter().append('circle') .attr('cx', d => getX(d.page)) .attr('cy', height / 2) .attr('r', 10) .attr('fill', 'blue'); // ノードの移動 circles.transition() .duration(300) .ease("linear") .attr('cx', d => getX(d.page)); } let data = data1; draw(data); setInterval(() => { data = (data === data1) ? data2 : data1; draw(data); }, 2 * 1000);