D3 删除 dbclick 上的圆圈
D3 remove circle on dbclick
我正在使用 Bostock 的 Circle Dragging I and Will's D3 Mouse Event,所以我可以单击 svg 并创建一个圆圈,而且它们都是可拖动的。这是有效的,虽然有一个附带问题,如果我在创建圆圈时双击,有时拖动圆圈会导致它们跳来跳去。
但主要问题是我希望能够双击一个圆圈并使其消失,但也希望将其从数据中删除。
绘制圆圈时,我添加了调用函数的 dbclick 事件
function removeElement(d) {
// need to remove this object from data
d3.select(this)
.exit()
.remove();
}
创建新圈子时也会调用此函数。
这个功能不是去除圆圈,正确的做法是什么?
单击做一件事和双击做另一件事之间是否存在冲突?
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
radius = 32;
var data = [{
x: 100,
y: 200
},
{
x: 200,
y: 300
},
{
x: 300,
y: 200
},
{
x: 400,
y: 300
}
];
var xScale = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.x_pos
})]).range([0, width]);
svg.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", radius)
.style("fill", "lightblue")
.attr('id', function(d, i) {
return 'rect_' + i;
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("dblclick", removeElement());
svg.on("click", function() {
var coords = d3.mouse(this);
var newData = {
x: d3.event.x,
y: d3.event.y
};
data.push(newData);
svg.selectAll("circle") // For new circle, go through the update process
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", radius)
.style("fill", "red")
.attr('id', function(d, i) {
return 'circle_' + i;
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("dblclick", removeElement());
})
function dragstarted(d) {
d3.select(this).raise().classed("active", true);
}
function dragged(d) {
d3.select(this)
.attr("cx", d.x = d3.event.x)
.attr("cy", d.y = d3.event.y);
}
function dragended(d) {
d3.select(this)
.classed("active", false);
}
function removeElement(d) {
// need to remove this object from data
d3.select(this)
.exit()
.remove();
}
.active {
stroke: #000;
stroke-width: 2px;
}
<!DOCTYPE html>
<meta charset="utf-8">
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
您的代码将面临的最大问题是区分双击和单击。但是,由于您具体询问了如何删除圆圈,因此该答案将仅处理该问题。
您的删除圆圈的代码有两个问题。
首先,这个...
.on("dblclick", removeElement())
... 将立即调用 removeElement
并 return 它的值(顺便说一下,它是 undefined
)。这不是你想要的。
相反,这样做:
.on("dblclick", removeElement)
与以下相同:
.on("dbclick", function(d){
removeElement(d);
}
这样,removeElement
只会在用户单击圆圈时调用,而不是立即调用。
第二个问题是这样的:
d3.select(this).exit().remove();
由于仍有与该圈子关联的数据,您的"exit"选择为空。
而不是那个,应该是:
d3.select(this).remove();
这是您的代码,其中包含这些更改:
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
radius = 32;
var data = [{
x: 100,
y: 200
},
{
x: 200,
y: 300
},
{
x: 300,
y: 200
},
{
x: 400,
y: 300
}
];
var xScale = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.x_pos
})]).range([0, width]);
svg.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", radius)
.style("fill", "lightblue")
.attr('id', function(d, i) {
return 'rect_' + i;
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("dblclick", removeElement);
function dragstarted(d) {
d3.select(this).raise().classed("active", true);
}
function dragged(d) {
d3.select(this)
.attr("cx", d.x = d3.event.x)
.attr("cy", d.y = d3.event.y);
}
function dragended(d) {
d3.select(this)
.classed("active", false);
}
function removeElement(d) {
// need to remove this object from data
d3.select(this)
.remove();
}
.active {
stroke: #000;
stroke-width: 2px;
}
<!DOCTYPE html>
<meta charset="utf-8">
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
PS:我删除了用于创建圆圈的 SVG 上的点击。由于该问题(区分单击和双击)非常复杂,因此可能值得提出一个新的、单独的问题。
我正在使用 Bostock 的 Circle Dragging I and Will's D3 Mouse Event,所以我可以单击 svg 并创建一个圆圈,而且它们都是可拖动的。这是有效的,虽然有一个附带问题,如果我在创建圆圈时双击,有时拖动圆圈会导致它们跳来跳去。
但主要问题是我希望能够双击一个圆圈并使其消失,但也希望将其从数据中删除。
绘制圆圈时,我添加了调用函数的 dbclick 事件
function removeElement(d) {
// need to remove this object from data
d3.select(this)
.exit()
.remove();
}
创建新圈子时也会调用此函数。
这个功能不是去除圆圈,正确的做法是什么? 单击做一件事和双击做另一件事之间是否存在冲突?
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
radius = 32;
var data = [{
x: 100,
y: 200
},
{
x: 200,
y: 300
},
{
x: 300,
y: 200
},
{
x: 400,
y: 300
}
];
var xScale = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.x_pos
})]).range([0, width]);
svg.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", radius)
.style("fill", "lightblue")
.attr('id', function(d, i) {
return 'rect_' + i;
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("dblclick", removeElement());
svg.on("click", function() {
var coords = d3.mouse(this);
var newData = {
x: d3.event.x,
y: d3.event.y
};
data.push(newData);
svg.selectAll("circle") // For new circle, go through the update process
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", radius)
.style("fill", "red")
.attr('id', function(d, i) {
return 'circle_' + i;
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("dblclick", removeElement());
})
function dragstarted(d) {
d3.select(this).raise().classed("active", true);
}
function dragged(d) {
d3.select(this)
.attr("cx", d.x = d3.event.x)
.attr("cy", d.y = d3.event.y);
}
function dragended(d) {
d3.select(this)
.classed("active", false);
}
function removeElement(d) {
// need to remove this object from data
d3.select(this)
.exit()
.remove();
}
.active {
stroke: #000;
stroke-width: 2px;
}
<!DOCTYPE html>
<meta charset="utf-8">
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
您的代码将面临的最大问题是区分双击和单击。但是,由于您具体询问了如何删除圆圈,因此该答案将仅处理该问题。
您的删除圆圈的代码有两个问题。
首先,这个...
.on("dblclick", removeElement())
... 将立即调用 removeElement
并 return 它的值(顺便说一下,它是 undefined
)。这不是你想要的。
相反,这样做:
.on("dblclick", removeElement)
与以下相同:
.on("dbclick", function(d){
removeElement(d);
}
这样,removeElement
只会在用户单击圆圈时调用,而不是立即调用。
第二个问题是这样的:
d3.select(this).exit().remove();
由于仍有与该圈子关联的数据,您的"exit"选择为空。
而不是那个,应该是:
d3.select(this).remove();
这是您的代码,其中包含这些更改:
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
radius = 32;
var data = [{
x: 100,
y: 200
},
{
x: 200,
y: 300
},
{
x: 300,
y: 200
},
{
x: 400,
y: 300
}
];
var xScale = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.x_pos
})]).range([0, width]);
svg.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", radius)
.style("fill", "lightblue")
.attr('id', function(d, i) {
return 'rect_' + i;
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("dblclick", removeElement);
function dragstarted(d) {
d3.select(this).raise().classed("active", true);
}
function dragged(d) {
d3.select(this)
.attr("cx", d.x = d3.event.x)
.attr("cy", d.y = d3.event.y);
}
function dragended(d) {
d3.select(this)
.classed("active", false);
}
function removeElement(d) {
// need to remove this object from data
d3.select(this)
.remove();
}
.active {
stroke: #000;
stroke-width: 2px;
}
<!DOCTYPE html>
<meta charset="utf-8">
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
PS:我删除了用于创建圆圈的 SVG 上的点击。由于该问题(区分单击和双击)非常复杂,因此可能值得提出一个新的、单独的问题。