我正在尝试d3 v4中的拖放功能。我正在努力获取目标元素。考虑在拖放时拖动小圆圈的示例,我想确定圆圈是在哪条路径上放置的。
非常感谢您的帮助
d3.selection.prototype.moveToFront = function() {
return this.each(function(){
this.parentNode.appendChild(this);
});
};
// Feel free to change or delete any of the code you see in this editor!
const svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 960)
const svgp = svg.append("g")
.attr("transform", "translate(400,300)")
// set constants
var PI = Math.PI;
var arcMin = 0; // inner radius of the first arc
var arcWidth = 25; // width
var arcPad = 0; // padding between arcs
var pieces = 4;
var arcPieces = [{start:0,end:90},{start:90,end:180},{start:180,end:270},{start:270,end:360}];
var drawArc = d3.arc()
.innerRadius(function(d, i) {
return d.ir;
})
.outerRadius(function(d, i) {
return d.or;
})
.startAngle(function(d, i) {
//console.log(d);
return d.start * Math.PI/180;
})
.endAngle(function(d, i) {
return (d.end * Math.PI/180);
});
var q = ["q1","q2","q3","q4"];
var p = [1,2,3,4,5,6,7,8,9,10];
var step = 360/q.length;
var objData = []
var drawData = q.forEach((q,i)=>{
p.forEach((p,j)=>{
objData.push({
q:q,
p:p,
start:(i*step),
end:((i+1)*step),
ir : j*25,
or : (j+1) *25
})
})
});
//console.log(objData);
// bind the data
var arcs = svgp.selectAll("path.arc-path").data(objData);
arcs.enter().append("svg:path")
.attr("class", "arc-path") // assigns a class for easier selecting
.attr("id",(d)=>d.q+"-"+d.p)
// sets position--easier than setting x's and y's
.attr("fill", function(d,i){
// fill is an rgb value with the green value determined by the data
// smaller numbers result in a higher green value (1 - d/60)
// you should also look into using d3 scales to create gradients
//var grn = Math.floor((1 - d/60)*255);
//console.log((d.q.replace("q",'')*10));
return "rgb(0, 0,"+ (d.q.replace("q",'')*20) +")";
})
.attr("d", drawArc) // draw the arc
.on('click',function(d){
//console.log(d);
})
.on('mouseover',function(){
//d3.select(this).attr("fill","#ffffff");
})
.on('dragover',function(){
alert("on arc")
})
var circleC = svg.append("circle").attr("cx",25).attr("cy",25).attr("r",10)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
function dragstarted(d,e){
//console.log("s",d,e);
d3.select(this).raise().classed("active", true);
}
function dragged(d,e){
//console.log(d3.event,event,this);
circleC.attr("cx",d3.event.x)
circleC.attr("cy",d3.event.y)
}
function dragended(d,e){
//I want to get on which path is is dropped
//console.log("e",d,e)
}
<script src="https://d3js.org/d3.v4.min.js"></script>
答案 0 :(得分:2)
最直接,最直接的解决方案可能是使用elementFromPoint。
例如,获取id
中的<path>
:
d3.select(document.elementFromPoint(d3.event.sourceEvent.clientX, d3.event.sourceEvent.clientY))
.attr("id");
要使其正常工作,我们必须先lower
个圆圈,这样它才不会位于路径的顶部。
这是您更新的代码:
d3.selection.prototype.moveToFront = function() {
return this.each(function() {
this.parentNode.appendChild(this);
});
};
// Feel free to change or delete any of the code you see in this editor!
const svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 960)
const svgp = svg.append("g")
.attr("transform", "translate(400,300)")
// set constants
var PI = Math.PI;
var arcMin = 0; // inner radius of the first arc
var arcWidth = 25; // width
var arcPad = 0; // padding between arcs
var pieces = 4;
var arcPieces = [{
start: 0,
end: 90
}, {
start: 90,
end: 180
}, {
start: 180,
end: 270
}, {
start: 270,
end: 360
}];
var drawArc = d3.arc()
.innerRadius(function(d, i) {
return d.ir;
})
.outerRadius(function(d, i) {
return d.or;
})
.startAngle(function(d, i) {
//console.log(d);
return d.start * Math.PI / 180;
})
.endAngle(function(d, i) {
return (d.end * Math.PI / 180);
});
var q = ["q1", "q2", "q3", "q4"];
var p = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var step = 360 / q.length;
var objData = []
var drawData = q.forEach((q, i) => {
p.forEach((p, j) => {
objData.push({
q: q,
p: p,
start: (i * step),
end: ((i + 1) * step),
ir: j * 25,
or: (j + 1) * 25
})
})
});
//console.log(objData);
// bind the data
var arcs = svgp.selectAll("path.arc-path").data(objData);
arcs.enter().append("svg:path")
.attr("class", "arc-path") // assigns a class for easier selecting
.attr("id", (d) => d.q + "-" + d.p)
// sets position--easier than setting x's and y's
.attr("fill", function(d, i) {
// fill is an rgb value with the green value determined by the data
// smaller numbers result in a higher green value (1 - d/60)
// you should also look into using d3 scales to create gradients
//var grn = Math.floor((1 - d/60)*255);
//console.log((d.q.replace("q",'')*10));
return "rgb(0, 0," + (d.q.replace("q", '') * 20) + ")";
})
.attr("d", drawArc) // draw the arc
.on('click', function(d) {
//console.log(d);
})
.on('mouseover', function() {
//d3.select(this).attr("fill","#ffffff");
})
.on('dragover', function() {
alert("on arc")
})
var circleC = svg.append("circle").attr("cx", 25).attr("cy", 25).attr("r", 10)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
function dragstarted(d, e) {
//console.log("s",d,e);
d3.select(this).raise().classed("active", true);
}
function dragged(d, e) {
//console.log(d3.event,event,this);
circleC.attr("cx", d3.event.x)
circleC.attr("cy", d3.event.y)
}
function dragended(d, e) {
//I want to get on which path is is dropped
d3.select(this).lower();
console.log(d3.select(document.elementFromPoint(d3.event.sourceEvent.clientX, d3.event.sourceEvent.clientY)).attr("id"));
d3.select(this).raise();
}
<script src="https://d3js.org/d3.v4.min.js"></script>
由于SVG本身没有id
,因此,如果将圆圈放到路径之外,则会得到null
。