Javascript 当d3中的点发生变化时更新多边形
我目前正在处理d3中的多边形,希望在用户拖动点时更新单个多边形。最初绘制它们很好,但我无法让更新正常工作。下面这把小提琴包含了我让它工作的可怕尝试: 相关代码:Javascript 当d3中的点发生变化时更新多边形,javascript,d3.js,polygon,Javascript,D3.js,Polygon,我目前正在处理d3中的多边形,希望在用户拖动点时更新单个多边形。最初绘制它们很好,但我无法让更新正常工作。下面这把小提琴包含了我让它工作的可怕尝试: 相关代码: const areas = [{ uid: 'ajf9v0', points: [{ x: 52, y: 92 }, { x: 50, y: 151 }, { x: 123,
const areas = [{
uid: 'ajf9v0',
points: [{
x: 52,
y: 92
},
{
x: 50,
y: 151
},
{
x: 123,
y: 149
},
{
x: 125,
y: 91
}
],
foo: 'bar',
// ...
},
{
uid: 'ufnf12',
points: [{
x: 350,
y: 250
},
{
x: 450,
y: 250
},
{
x: 450,
y: 275
},
{
x: 350,
y: 275
}
],
foo: 'baz',
// ...
}
];
const svg = d3.select('#root');
svg.attr('width', 500)
.attr('height', 500);
const areasGroup = svg.append('g')
.attr('class', 'areas');
function drawAreas(areas) {
console.log('Called draw');
const self = this;
const aGroup = areasGroup.selectAll('g.area')
.data(areas, (d) => {
console.log('Areas', d.points.map((d) => [d.x, d.y].join('#')).join('#'));
return d.points.map((d) => [d.x, d.y].join('#')).join('#');
});
areasGroup.exit().remove();
const areaGroups = aGroup.enter()
.append('g')
.attr('class', 'area');
//const areaPolygon = area.append('g')
// .attr('class', 'polygon');
//const areaPoints = area.append('g')
// .attr('class', 'points');
const polygon = areaGroups.selectAll('polygon')
.data((d) => {
console.log('Polygon data points', [d.points]);
return [d.points];
}, (d) => {
console.log('Polygon key', d.map((d) => [d.x, d.y].join('#')).join('#'));
return d.map((d) => [d.x, d.y].join('#')).join('#');
});
polygon.enter()
.append('polygon')
.merge(polygon)
.attr('points', (d) => {
console.log('Polygon points', d);
return d.map((d) => [d.x, d.y].join(',')).join(' ');
})
.attr('stroke', '#007bff')
.attr('stroke-width', 1)
.attr('fill', '#007bff')
.attr('fill-opacity', 0.25)
.on('click', this.handlePolygonSelection)
polygon.exit().remove();
const circles = areaGroups.selectAll('circle')
.data((d) => d.points, (d) => d.x + '#' + d.y);
circles.enter()
.append('circle')
.attr('r', 4)
.attr('cx', (d) => d.x)
.attr('cy', (d) => d.y)
.attr('fill', '#007bff')
.on('click', (d, idx, j) => {
const parentArea = d3.select(j[idx].parentNode).datum().points;
const i = parentArea.findIndex((p) => p.x === d.x && p.y === d.y);
if (i === parentArea.length) {
parentArea.pop();
} else if (i === 0) {
parentArea.shift();
} else {
parentArea.splice(i, 1);
}
this.drawAreas(areas);
})
.call(d3.drag()
.on('start', function(d) {
d3.select(this).classed('active', true)
})
.on('drag', function(d) {
d3.select(this)
.attr('cx', d.x = d3.event.x)
.attr('cy', d.y = d3.event.y);
self.drawAreas(areas);
})
.on('end', function(d) {
d3.select(this).classed('active', false)
}));
circles.exit().remove();
}
this.drawAreas(areas);
感谢所有花时间查看的人,感谢所有帮助。看来我发现了问题: 改变
const polygon = areaGroups.selectAll('polygon')
到
好像已经修好了。我假设这与仅处理enter事件的areaGroups
选择有关
另一种选择是保持现状,改变现状
const areaGroups = aGroup.enter()
.append('g')
.attr('class', 'area');
到
这将产生相同的结果,因为更新事件现在也得到了适当的处理
const areaGroups = aGroup.enter()
.append('g')
.attr('class', 'area');
const areaGroups = aGroup.enter()
.append('g')
.merge(aGroup)
.attr('class', 'area');