Reputation: 440
I have drawn two circles with the below code, i have to draw a line between these two circles but the tricky point when i start to draw a line from the first circle there should be availability of second circle then only it should draw otherwise it shouldn't draw line and vice versa. if i click outside of circle then also it shouldn't draw line
in my below code or fiddle check it i can a draw a line my condition is not working
var line;
var svg = d3.select("body").append("svg")
.attr("width", 600)
.attr("height", 400).on("mousedown", mousedown).on("mouseup", mouseup);
function mousedown() {
var m = d3.mouse(this);
line = vis.append("line")
.attr("x1", m[0])
.attr("y1", m[1])
.attr("x2", m[0])
.attr("y2", m[1]);
svg.on("mousemove", mousemove);
}
function mousemove() {
var m = d3.mouse(this);
line.attr("x2", m[0])
.attr("y2", m[1]);
}
function mouseup() {
svg.on("mousemove", null);
}
var inputs = [
{ "x" : 200, "y" : 150, r : 50},
{ "x" : 300, "y" : 250, r : 50},
]
svg.selectAll("circle").data(inputs).enter().append("circle")
.attr("r", function(d, i){ return d.r })
.attr("cx", function(d, i){ return d.x })
.attr("cy", function(d, i){ return d.y })
.attr("stroke", "red")
.attr("fill", "white")
Here is my fiddle : https://jsfiddle.net/34j6pkn9/1/
Upvotes: 1
Views: 2182
Reputation: 41
There will be a line after every circle (except the first one). Each line will connect the centers of every two consecutive circles.
You've the first circle which you are appending in your svg now, but how will you find the previous circle? You can, simply, find previousElementSibling of the first circle. But, there is catch here, notice there is line after every circle. So, be sure to check the name of the previousElementSibling if it's "line", find previousElementSibling once more.
// At this point, you've just appended the circle in
// 'svg' based on where the mouse is etc.
// Now, find the previous circle.
const parentNode = document.querySelector("svg");
// 'thisCircle' is the one you're appending in svg now.
const thisCircle = parentNode.lastElementChild;
// Previous sibling of this circle.
const previousSibling = thisCircle.previousElementSibling;
// If this is the first circle drawn, then do nothing- return
if (!previousSibling) {
return;
}
// Check if previous sibling is indeed 'circle' and not 'line'
const nodeNameOfPreviousSiblig = previousSibling.nodeName;
let previousCircle = previousSibling;
// If the previous node is 'line' go one more step upwards- it must be a circle. Since pattern => 1 circle, 1 line.
if (nodeNameOfPreviousSiblig == 'line') {
previousCircle = previousSibling.previousElementSibling;
}
// center of the previous circle.
const xCoordOPrevCircleCenter = previousCircle.getAttribute("cx");
const yCoordOPrevCircleCenter = previousCircle.getAttribute("cy");
Now, finally, append the line connecting these two consecutive circles centers:
svg.append('line')
.attr('x1', xCoordOThisCircleCenter)
.attr('y1', yCoordOThisCircleCenter)
.attr('x2', xCoordOPrevCircleCenter)
.attr('y2', yCoordOPrevCircleCenter)
Upvotes: 1
Reputation: 948
maybe this will help you but its far from a good solution, but it work
Note :
circle drawing its bit ridiculus for me, it draw rect, imagine you draw rect first then you draw a circle inside of it that its why, it have bug on each angle of it that look like circle but difinetly its a reactangle,i think it can be solve by some calculation,but sorry i didnt know any of that
var line;
var mx =0
var my =0
var inputs = [
{ "x" : 200, "y" : 150, r : 50},
{ "x" : 300, "y" : 250, r : 50},
]
var vis = d3.select("body").append("svg")
.attr("width", 600)
.attr("height", 400)
.on("mouseup", mouseup);
function mousedown() {
var m = d3.mouse(this);
line = vis.append("line")
.attr("x1", m[0])
.attr("y1", m[1])
.attr("x2", m[0])
.attr("y2", m[1]);
mx = m[0]
my = m[1]
vis.on("mousemove", mousemove);
}
function mousemove() {
var m = d3.mouse(this);
line.attr("x2", m[0])
.attr("y2", m[1]);
}
function mouseup() {
var m = d3.mouse(this);
//console.log(mx-m[0],my-m[1])
inputs.forEach(function(d,i){
if(m[0]<(d.x+d.r)&& m[0]>(d.x-d.r)&&m[1] <(d.y+d.r)&& m[1]>(d.y-d.r)){
if(mx<(d.x+d.r)&& mx>(d.x-d.r)&&my <(d.y+d.r)&& my>(d.y-d.r)){
}else{
vis.on("mousemove", null);
}
}
})
}
vis.selectAll("circle").data(inputs).enter().append("circle")
.attr("r", function(d, i){ return d.r })
.attr("cx", function(d, i){ return d.x })
.attr("cy", function(d, i){ return d.y })
.attr("stroke", "red")
.attr("fill", "white")
.on("mousedown", mousedown).on("mouseup", mouseup);
svg {
border: 1px solid red;
}
line {
stroke: steelblue;
stroke-width: 2px;
stroke-linecap: round;
}
<html>
<head>
<meta charset="utf-8">
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script>
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head><body>
</body>
Upvotes: 1