我正在尝试使用d3.js和es6类构建图表。
我有一组数据data = [{someProp: '', hasWarning: true}, ...]
。
某些数据元素可以具有hasWarning
属性。
如果存在此属性,则在父组中绘制<path class="notification"></path>
元素。
<g id="g-parent" transform="translate(500, 300)" class="group">
<circle r="50" cx="10" cy="10" fill="red"></circle>
<path d="..." transform="translate(30,-40) scale(0.05)"></path>
</g>
当数据更新时,我重画了通知。但是,如果某些.notification
已经存在,我的代码将添加一个新项,而不是更新exisitng。
如何避免添加新元素并更新现有元素?
答案 0 :(得分:0)
在您的renderNotifications
中,您可以在添加任何现有通知之前将其删除。
class ChartRenderer {
constructor(data) {
this.data = data;
this.lineFn = d3.line().curve(d3.curveLinear);
}
renderSvg() {
this.svg = d3.select('body')
.append('svg')
.attr('width', 1000)
.attr('height', 1000)
.attr('id', 1000);
}
renderContainer() {
this.container = this.svg.append('g')
.attr('id', 'testUpdate');
}
renderGroups() {
this.groupSelection = this.container.selectAll('.group')
.data(this.data);
this.groupEnter = this.groupSelection.enter()
.append('g')
.attr('id', (d, i) => `g-${d._id}`)
.attr('transform', (d, i) => `translate(${d.position.x}, ${d.position.y})`)
.attr('class', 'group');
this.groupSelection
.exit()
.classed('remove', true)
.transition()
.delay(200)
.remove();
}
renderCircles() {
this.circles = this.groupEnter
.append('circle')
.attr('r', 50)
.attr('cx', 10)
.attr('cy', 10)
.attr('fill', 'red');
}
renderNotifications() {
this.groupEnter.select('.notification').remove();
this.notifications = this.groupEnter.filter(d => d.hasWarnings)
.append('path')
.attr('class', 'notification')
.attr('d', 'M248.747 204.705l6.588 112c.373 6.343 5.626 11.295 11.979 11.295h41.37a12 12 0 0 0 11.979-11.295l6.588-112c.405-6.893-5.075-12.705-11.979-12.705h-54.547c-6.903 0-12.383 5.812-11.978 12.705zM330 384c0 23.196-18.804 42-42 42s-42-18.804-42-42 18.804-42 42-42 42 18.804 42 42zm-.423-360.015c-18.433-31.951-64.687-32.009-83.154 0L6.477 440.013C-11.945 471.946 11.118 512 48.054 512H527.94c36.865 0 60.035-39.993 41.577-71.987L329.577 23.985zM53.191 455.002L282.803 57.008c2.309-4.002 8.085-4.002 10.394 0l229.612 397.993c2.308 4-.579 8.998-5.197 8.998H58.388c-4.617.001-7.504-4.997-5.197-8.997z')
.attr('transform', 'translate(30,-40) scale(0.05)');
}
}
class Chart {
constructor(data = []) {
// console.log(data);
this.data = data;
this.data.forEach(this.multiplyElementCoordinates);
this.renderer = new ChartRenderer(this.data);
this.draw();
}
draw() {
this.renderer.renderSvg();
this.renderer.renderContainer();
this.renderer.renderGroups();
this.renderer.renderCircles();
this.renderer.renderNotifications();
}
multiplyElementCoordinates(el) {
el.position.x *= 100;
el.position.y *= 100;
}
toggleNotifications() {
this.data.forEach(d => {
d.hasWarnings = true;
});
this.renderer.renderNotifications();
}
}
const data = [{
_id: 'first',
position: {
x: 5,
y: 1
},
hasWarnings: true
},
{
_id: 'second',
position: {
x: 5,
y: 3
}
},
{
_id: 'third',
position: {
x: 3,
y: 5
}
},
{
_id: 'fourth',
type: 'Condition',
position: {
x: 7,
y: 5
}
}
];
const lineChart = new Chart(data);
setTimeout(() => {
lineChart.toggleNotifications();
}, 5000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>