当我将一个圆形元素拖出组时,如何取消它?目前我能够将它附加到组但不能在拖动时取消它。如果有任何机构有想法请帮助。我是d3js和javascript的新手
演示:http://jsfiddle.net/q7L9qdyv/
代码:
var svg = d3.select("body").append("svg")
.attr("width", 800)
.attr("height", 803);
//Draw the Circle
var circle = svg.append("circle")
.attr("r", 25)
.attr("cx", 35)
.attr("cy", 145)
.style("stroke-opacity", .9)
.style("stroke", "green")
.style("fill", "white")
.style("stroke-width", "2px")
.classed("baseCircle", true); // created a class to identify
var targetCircle = circle;
var tempCircle = circle;
//unique id for circles
function guid()
{
function _p8(s)
{
var p = (Math.random().toString(16) + "000000000").substr(2, 8);
return s ? "-" + p.substr(0, 4) + "-" + p.substr(4, 4) : p;
}
return _p8() + _p8(true) + _p8(true) + _p8();
}
//function to move circles
function moveCircle()
{
d3.select(this)
.attr('cx', d3.event.x)
.attr('cy', d3.event.y);
}
//Move the group along wth elements/Drag Behaviour for Group
var dragGroup = d3.behavior.drag()
.origin(function () {
var g = this;
return {x: d3.transform(g.getAttribute("transform")).translate[0],
y: d3.transform(g.getAttribute("transform")).translate[1]};
})
.on("drag", function (d, i) {
g = this;
translate = d3.transform(g.getAttribute("transform")).translate;
console.log(translate);
x = d3.event.dx + translate[0],
y = d3.event.dy + translate[1];
d3.select(g).attr("transform", "translate(" + x + "," + y + ")");
d3.event.sourceEvent.stopPropagation();
});
//Group element
var targetG = svg.append("g")
.call(dragGroup)
.style('cursor', 'move')
.attr("transform", "translate(150,150)");
//Append rectangle to group
targetG.append("rect")
.attr("fill", "none")
.style("stroke", "black")
.style("stroke-width", "2px")
.attr("width", 200)
.attr("height", 200)
.style("fill", "white");
//Drag behaviour starts for circles
var drag = d3.behavior.drag()
.on("dragstart", dragstart)
.on("drag", drag)
.on("dragend", dragend);
//Start
function dragstart() {
console.log("circle dragged is::" + d3.select(this).attr("id"));
if (d3.select(this).classed("baseCircle") === true) {
targetCircle = svg.append("circle")
.attr("r", 25) //get radius from targetCircle and also styles?
.attr("cx", targetCircle.attr("cx"))
.attr("cy", targetCircle.attr("cy"))
.style("fill", "white")
.style("stroke", "green")
.style("stroke-width", "2px");
targetCircle.call(drag);
}
else
{
targetCircle = d3.select(this);
tempCircle = this;
}
targetCircle.classed("dragTarget", true).attr("id", "dragTargetId");
}
//Drag
function drag()
{
targetCircle.attr("cx", d3.event.x)
.attr("cy", d3.event.y);
}
//End
function dragend(d) {
//Get event x and y
var tx = targetCircle.attr("cx"),
ty = targetCircle.attr("cy");
var flag = 0;
//Select all elements in svg
try {
var elemArr = svg.selectAll("*").each(function (d, i) {
//If the element is a member of a group, check
if ($(this.parentNode).is("g")) {
//Get coordinates
var box = this.getBBox();
var bx = box.x,
by = box.y,
bw = box.width,
bh = box.height;
//Make shape inherit translate of parent element
var translate = d3.select(this.parentNode).attr("transform");
var translate = translate.substring(translate.indexOf("translate(") + 10, translate.length);
translate = (translate.substring(0, translate.indexOf(")"))).split(",");
bx += parseInt(translate[0]);
by += parseInt(translate[1]);
//Check if within x and y bounds
if (tx >= bx && tx <= (bx + bw) && !flag && ty >= by && ty <= (by + bh))
{
//Flag to prevent further action
flag = 1;
//Append target circle to g element
targetG.append("circle")
.attr("r", 25) //get radius from targetCircle and also styles?
.attr("id", guid())
.classed("circleAddedClass", true)
.attr("cx", d3.mouse(this)[0])
.attr("cy", d3.mouse(this)[1])
.style("fill", "white")
.style("stroke", "black")
.style("stroke-width", "2px")
.call(
d3.behavior.drag()
.on("dragstart", function () {
d3.event.sourceEvent.stopPropagation();
})
.on('drag', moveCircle).origin(function () {
var t = d3.select(this);
return {x: t.attr("cx"), y: t.attr("cy")};
}));
targetCircle.remove();
}
}
});
} catch (e) {
log(e);
}
}
function log(s) {
console.log(s);
return s;
}
circle.call(drag);
答案 0 :(得分:2)
<强> CSS 强>
.baseCircle {
stroke-opacity: 0.9;
stroke: green;
stroke-width: 2px;
fill: white;
}
.dragTarget {
stroke: green;
stroke-width: 2px;
fill: white;
}
.circleAddedClass {
stroke: black;
stroke-width: 2px;
fill: white;
}
<强>脚本强>
我重新整理了你的代码
// unique id for circles
function guid() {
function _p8(s) {
var p = (Math.random().toString(16) + "000000000").substr(2, 8);
return s ? "-" + p.substr(0, 4) + "-" + p.substr(4, 4) : p;
}
return _p8() + _p8(true) + _p8(true) + _p8();
}
function getNode(d3Element) {
return d3Element[0][0];
}
// check if within bounds
function isWithin(x, y, box) {
return (x >= box.x && x <= (box.x + box.width) && y >= box.y && y <= (box.y + box.height))
}
function getTranslate(t) {
var translate = d3.transform(t.getAttribute("transform")).translate;
return {
x: Number(translate[0]),
y: Number(translate[1])
};
}
var svg = d3.select("body")
.append("svg")
.attr("width", 800)
.attr("height", 803);
// movement for a transformed element
var dragG = d3.behavior.drag()
// set the origin to the start position
.origin(function () {
return getTranslate(this);
})
.on("drag", function () {
d3.select(this).attr(
"transform",
"translate(" +
d3.event.x + "," +
d3.event.y + ")");
});
// drop group
var targetG = svg.append("g")
.style('cursor', 'move')
.attr("transform", "translate(150,150)")
.call(dragG)
// append rectangle to group
targetG.append("rect")
.attr("fill", "none")
.style("stroke", "black")
.style("stroke-width", "2px")
.attr("width", 200)
.attr("height", 200)
.style("fill", "white");
// drag functions
var draggedCircle;
var circleDrag = function () {
draggedCircle
.attr("cx", d3.event.x)
.attr("cy", d3.event.y);
}
function circleDragEnd() {
// get event x and y
var dx = Number(draggedCircle.attr("cx"));
var dy = Number(draggedCircle.attr("cy"));
if (draggedCircle.classed("circleAddedClass")) {
var t = getTranslate(getNode(draggedCircle).parentNode);
console.log([dx, dy])
dx += t.x;
dy += t.y;
console.log([dx, dy])
}
svg.selectAll("g").each(function () {
var rect = d3.select(this).select("rect");
if (rect.length === 1) {
var box = getNode(rect).getBBox();
// the actual coordinates of the element must include the parent's transform too
var t = getTranslate(this);
box = {
x: box.x + t.x,
y: box.y + t.y,
width: box.width,
height: box.height
}
if (isWithin(dx, dy, box)) {
if (!draggedCircle.classed("circleAddedClass")) {
draggedCircle = draggedCircle.remove()
.attr("cx", dx - t.x)
.attr("cy", dy - t.y)
.attr("id", guid())
.classed("dragTarget", false)
.classed("circleAddedClass", true);
// append target circle to g element
this.appendChild(getNode(draggedCircle))
}
} else if (draggedCircle.classed("circleAddedClass")) {
if (getNode(draggedCircle).parentNode === this) {
draggedCircle = draggedCircle.remove()
.attr("cx", dx)
.attr("cy", dy)
.classed("dragTarget", true)
.classed("circleAddedClass", false);
getNode(svg).appendChild(getNode(draggedCircle))
}
}
}
});
}
// drag behaviour for circle instances
var dragCircleInstance = d3.behavior.drag()
.on("dragstart", function () {
draggedCircle = d3.select(this)
d3.event.sourceEvent.stopPropagation();
})
.on("drag", circleDrag)
.on("dragend", circleDragEnd);
// drag behaviour for circle template
var dragCircleTemplate = d3.behavior.drag()
.on("dragstart", function () {
draggedCircle = svg.append("circle")
.attr("r", 25) //get radius from targetCircle and also styles?
.attr("cx", d3.select(this).attr("cx"))
.attr("cy", d3.select(this).attr("cy"))
.classed("dragTarget", true)
.call(dragCircleInstance);
})
.on("drag", circleDrag)
.on("dragend", circleDragEnd);
// draw the circle template
var circle = svg.append("circle")
.attr("r", 25)
.attr("cx", 35)
.attr("cy", 145)
.classed("baseCircle", true)
.call(dragCircleTemplate);
答案 1 :(得分:1)
如果我要对此进行编码审核,请提出以下建议:
dragstart
令人困惑并容易出现问题。我只想创建一个静态圆圈,标记您拖动的位置并在拖动结束时克隆。这当然会增加另一个州;最初拖到任何地方。考虑到这一切,这是我的重新编码。
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<script>
var svg = d3.select("body")
.append("svg")
.attr("width", 800)
.attr("height", 803);
//Move the group along wth elements/Drag Behaviour for Group
var dragGroup = d3.behavior.drag()
.origin(function () {
var g = this;
return {
x: d3.transform(g.getAttribute("transform")).translate[0],
y: d3.transform(g.getAttribute("transform")).translate[1]
};
})
.on("drag", function (d, i) {
g = this;
translate = d3.transform(g.getAttribute("transform")).translate;
var x = d3.event.dx + translate[0],
y = d3.event.dy + translate[1];
d3.select(g).attr("transform", "translate(" + x + "," + y + ")");
d3.event.sourceEvent.stopPropagation();
});
// circle drag
function dragging(){
var self = d3.select(this);
self.attr("cx", d3.event.x)
.attr("cy", d3.event.y);
}
// start
function dragstart() {
d3.event.sourceEvent.stopPropagation();
}
//End
function dragend(d) {
var self = d3.select(this);
// is this the first time I'm dragged?
// replace me with a new one
if (self.classed('initialDragCircle')){
// append a new inital draggable
createInitialDragCircle();
self.attr('class','dragCircle');
}
// get necessary coordinates
var tx = self.attr('cx'),
ty = self.attr('cy');
var transG = d3.transform(targG.attr('transform')).translate;
var bx = transG[0];
by = transG[1];
// was it outside of the box?
if (self.classed('dragCircle')){
var coords = d3.mouse(targG.node());
var box = targRect.node().getBBox();
// and now is it in box?
if (coords[0] > 0 && coords[1] > 0 &&
coords[0] < box.width && coords[1] < box.height) {
targG.append("circle")
.attr("r", 25)
.attr("cx", coords[0])
.attr("cy", coords[1])
.style("stroke-opacity", .9)
.style("stroke", "black")
.style("fill", "white")
.style("stroke-width", "2px")
.attr('class','inBoxDragCircle')
.call(drag);
self.remove();
}
}
// was it in the box?
else if (self.classed('inBoxDragCircle'))
{
var coords = d3.mouse(targG.node());
var box = targRect.node().getBBox();
// and now it is out of the box?
if (coords[0] < 0 || coords[1] < 0 ||
coords[0] > box.width || coords[1] > box.height) {
coords = d3.mouse(svg.node());
svg.append("circle")
.attr("r", 25)
.attr("cx", coords[0])
.attr("cy", coords[1])
.style("stroke-opacity", .9)
.style("stroke", "green")
.style("fill", "white")
.style("stroke-width", "2px")
.attr('class','dragCircle')
.call(drag);
self.remove();
}
}
}
var drag = d3.behavior.drag()
.on("dragstart", dragstart)
.on("drag", dragging)
.on("dragend", dragend);
//Group element
var targG = svg.append("g")
.call(dragGroup)
.style('cursor', 'move')
.attr("transform", "translate(150,150)");
var targRect = targG.append("rect")
.attr("fill", "none")
.style("stroke", "black")
.style("stroke-width", "2px")
.attr("width", 200)
.attr("height", 200)
.style("fill", "white");
//Draw the Circle
svg.append("circle")
.attr("r", 25)
.attr("cx", 35)
.attr("cy", 145)
.style("stroke-opacity", .9)
.style("stroke", "green")
.style("fill", "white")
.style("stroke-width", "2px")
.classed("baseCircle", true);
function createInitialDragCircle(){
svg.append("circle")
.attr("r", 25)
.attr("cx", 35)
.attr("cy", 145)
.style("stroke-opacity", .9)
.style("stroke", "green")
.style("fill", "white")
.style("stroke-width", "2px")
.classed("initialDragCircle", true)
.call(drag);
};
createInitialDragCircle();
</script>
</body>
</html>
&#13;
答案 2 :(得分:0)
伪码如下: -
id=xxx
添加到已创建的所有圈子中。 d3.select("_dragged_circle_ID_").append("_another_<g>_container_");