Add hover event on intersecting sections of SVG graph - javascript

I have create a fiddle http://jsfiddle.net/bhyt7L5z/
I have 5 ellipse intersecting each other. I want to capture hover event on intersecting areas and show corresponding data in tool-tip.
ASomething like :
$('paths').hover(function(e) {
console.log('show content related to intersection');
});
Can anyone give me pointers on how to do this.
Is there any chart available in JavaScript which gives interactive elliptical venn diagram
Regards

just append .attr('id','ellipse1') for each of you ellipse and now you can use
$('#ellipse1').hover(function(e) {
console.log('show content related to intersection');
});
code from you jsfiddle:
var width = 450,
height = 400
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("svg:ellipse")
.attr("cx", 200)
.attr("cy", 200)
.attr("rx", 50)
.attr("ry",100)
.style("fill", 'rgba(108,255,108,0.4)')
.style("stroke", "#777")
.style("stroke-width", '1px')
.style("transform", 'rotate(30deg)')
.style("transform-origin", "50% 50%")
.attr("id","ellipse1")
.attr("data-toggle","tooltip")
.attr("title","ellipse1")
svg.append("svg:ellipse")
.attr("cx", 200)
.attr("cy", 200)
.attr("rx", 50)
.attr("ry",100)
.style("fill", 'rgba(168,255,168,0.4)')
.style("stroke", "#777")
.style("stroke-width", '1px')
.style("transform", 'rotate(70deg)')
.style("transform-origin", "50% 50%")
.attr("id","ellipse2")
.attr("data-toggle","tooltip")
.attr("title","ellipse2")
svg.append("svg:ellipse")
.attr("cx", 200)
.attr("cy", 200)
.attr("rx", 50)
.attr("ry",100)
.style("fill", 'rgba(148,255,148,0.4)')
.style("stroke", "#777")
.style("stroke-width", '1px')
.style("transform", 'rotate(110deg)')
.style("transform-origin", "50% 50%")
.attr("id","ellipse3")
.attr("data-toggle","tooltip")
.attr("title","ellipse3")
svg.append("svg:ellipse")
.attr("cx", 200)
.attr("cy", 200)
.attr("rx", 50)
.attr("ry",100)
.style("fill", 'rgba(128,255,128,0.4)')
.style("stroke", "#777")
.style("stroke-width", '1px')
.style("transform", 'rotate(140deg)')
.style("transform-origin", "50% 50%")
.attr("id","ellipse4")
.attr("data-toggle","tooltip")
.attr("title","ellipse4")
$('[data-toggle="tooltip"]').tooltip({container: 'body'});
svg {
border:1px dotted #000;
}
<script src="http://d3js.org/d3.v3.js"></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<div id="content"></div>

Related

How to prevent the drag if the user clicks the round in d3.js?

I have group element it has circle and rect elements. User can drag the group element, so both rect and circle element will move. It is working fine. But I need to prevent the drag if the user clicks on the circle element. JS Fiddle
const x = 100;
var y = 100;
var grid = d3.select("#svg-area");
var g = grid.append("g")
.attr("transform", `translate(${x},${y})`)
.call(d3.drag()
.on("drag", function() {
var x1 = d3.event.x - 30;
var y1 = d3.event.y - 10;
d3.select(this).attr("transform", "translate(" +
(x1) + "," + (y1) + ")")
}));
newNode(g);
function newNode(g, text) {
var textWid = 100;
console.log('wid ', textWid);
g.append("rect")
.attr("class", "new-nodes")
.attr("x", '10')
.attr("y", '0')
.attr("rx", '6')
.attr("ry", '6')
.attr("width", textWid)
.attr("height", '35')
.style("fill", "#8c259f")
.style("stroke", "#222")
.style("cursor", "move");
g.append("circle")
.attr("class", "new-nodes")
.attr("cx", '10')
.attr("cy", '17')
.attr("r", '6')
.style("fill", "#dedede")
.style("stroke", "#b2b0b0")
.style("cursor", "pointer")
.on("click", function(d) {
/* d3.event.preventDefault();
d3.event.stopPropagation();
*/
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg id="svg-area" class="chart-area" width="500" height="500" pointer-events="all" style="cursor: crosshair; touch-action: none;">
</svg>
The simplest way - the one closest to your code - is to change on("click" to on("mousedown". A "click" event is registered when the mouse button is released again. A "mousedown" event is clearly registered before that. And the mousedown event is the one that triggers "dragstart".
const x = 100;
var y = 100;
var grid = d3.select("#svg-area");
var g = grid.append("g")
.attr("transform", `translate(${x},${y})`)
.call(d3.drag()
.on("drag", function() {
var x1 = d3.event.x - 30;
var y1 = d3.event.y - 10;
d3.select(this).attr("transform", "translate(" +
(x1) + "," + (y1) + ")")
}));
newNode(g);
function newNode(g, text) {
var textWid = 100;
console.log('wid ', textWid);
g.append("rect")
.attr("class", "new-nodes")
.attr("x", '10')
.attr("y", '0')
.attr("rx", '6')
.attr("ry", '6')
.attr("width", textWid)
.attr("height", '35')
.style("fill", "#8c259f")
.style("stroke", "#222")
.style("cursor", "move");
g.append("circle")
.attr("class", "new-nodes")
.attr("cx", '10')
.attr("cy", '17')
.attr("r", '6')
.style("fill", "#dedede")
.style("stroke", "#b2b0b0")
.style("cursor", "pointer")
.on("mousedown", function(d) {
d3.event.preventDefault();
d3.event.stopPropagation();
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg id="svg-area" class="chart-area" width="500" height="500" pointer-events="all" style="cursor: crosshair; touch-action: none;">
</svg>
Alternatively, you could just move the event to the rectangle and use d3.drag().container. Normally, d3.drag calculates the distance between the event and the parent element. Now, we need the grandparent, because the parent (the g element) is the thing we want to drag around.
I also changed the g element to use a datum object, so you can more easily move it.
var grid = d3.select("#svg-area");
var g = grid.append("g")
.datum({
x: 100,
y: 100
})
.attr("transform", function(d) {
return `translate(${d.x},${d.y})`;
});
newNode(g);
function newNode(g, text) {
var textWid = 100;
console.log('wid ', textWid);
g.append("rect")
.attr("class", "new-nodes")
.attr("x", '10')
.attr("y", '0')
.attr("rx", '6')
.attr("ry", '6')
.attr("width", textWid)
.attr("height", '35')
.style("fill", "#8c259f")
.style("stroke", "#222")
.style("cursor", "move")
.call(d3.drag()
.container(grid.node())
.on("drag", function() {
d3.select(this.parentNode)
.attr("transform", function(d) {
d.x += d3.event.dx;
d.y += d3.event.dy;
return `translate(${d.x},${d.y})`;
});
}));
g.append("circle")
.attr("class", "new-nodes")
.attr("cx", '10')
.attr("cy", '17')
.attr("r", '6')
.style("fill", "#dedede")
.style("stroke", "#b2b0b0")
.style("cursor", "pointer");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg id="svg-area" class="chart-area" width="500" height="500" pointer-events="all" style="cursor: crosshair; touch-action: none;">
</svg>

D3 and java script

Okay i rewrote the code again and this time just passed the parameters for the translate function, but its still not taking the value.
<!DOCTYPE html>
<html lang = "en" class="tas-com">
<head>
<meta charset="utf-8">
<title>Simple Stars</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body>
<h1>Some Stars</h1>
<svg width="200" height="200" style='background: aliceblue'>
</svg>
<script type="text/javascript">
var x;
var y;
function draw(q,r){
var svg1 = d3.select("svg");
svg1.append("polygon")
.attr("points", "0,0.9511, 1.0,0.95111, 1.309,0, 1.618,0.9511, 2.618,0.9511, 1.809,1.5388, 2.118,2.4899, 1.309,1.9021, 0.5,2.4899, 0.809,1.5388")
.attr("fill", "blue")
.attr("transform", "translate(q, r), scale(4)")
.style("fill", "yellow");
}
var svg = d3.select("svg");
svg.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", 200)
.attr("height", 200)
.style("fill", "blue");
for (var i=0;i<150;i+=15){
var o=30
draw(o+i,o+i)
}
</script>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>
Hey I'm trying to mess around with d3 and javascript, and was trying to draw the European flag. But the stars are not getting displayed at all. What might be the error?
I want to use the function for the x,y coordinates value to be taken. The circles drawn are just placeholders for the time being.
thanks
<!DOCTYPE html>
<html lang = "en" class="tas-com">
<head>
<meta charset="utf-8">
<title>Simple Stars</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body>
<h1>Some Stars</h1>
<svg width="200" height="200" style="background: aliceblue"/>
</svg>
<script type="text/javascript">
var x
var y
function draw(q){
x= 100 + 60*Math.cos(q)
y= 100 + 60*Math.sin(q)
return x,y
}
var svg = d3.select("svg");
svg.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", 200)
.attr("height", 200)
.style("fill", "blue");
{draw(10)
svg.append("polygon")
.attr("points", "x,y, x+1.0,y, x+1.309,y-0.9511, x+1.618,y, x+2.618,y, x+1.809,y+0.5877, x+2.118,y+1.5388, x+1.309,y+0.951, x+0.5,y+1.5388, x+0.809,y+0.5877")
.attr("transform", "translate(30, 30), scale(4)")
.style("fill", "green");
};
{draw(25)
svg.append("circle")
.attr("cx", x)
.attr("cy", y)
.attr("r", 5)
.style("fill", "red")
};
{draw(40)
svg.append("circle")
.attr("cx", x)
.attr("cy", y)
.attr("r", 5)
.style("fill", "red")
};
{draw(55)
svg.append("circle")
.attr("cx", x)
.attr("cy", y)
.attr("r", 5)
.style("fill", "red")
};
{draw(70)
svg.append("circle")
.attr("cx", x)
.attr("cy", y)
.attr("r", 5)
.style("fill", "red")
};
{draw(85)
svg.append("circle")
.attr("cx", x)
.attr("cy", y)
.attr("r", 5)
.style("fill", "red")
};
{draw(100)
svg.append("circle")
.attr("cx", x)
.attr("cy", y)
.attr("r", 5)
.style("fill", "red")
};
{draw(115)
svg.append("circle")
.attr("cx", x)
.attr("cy", y)
.attr("r", 5)
.style("fill", "red")
};
{draw(130)
svg.append("circle")
.attr("cx", x)
.attr("cy", y)
.attr("r", 5)
.style("fill", "red")
};
{draw(145)
svg.append("circle")
.attr("cx", x)
.attr("cy", y)
.attr("r", 5)
.style("fill", "red")
};
{draw(160)
svg.append("circle")
.attr("cx", x)
.attr("cy", y)
.attr("r", 5)
.style("fill", "red")
};
{draw(175)
svg.append("circle")
.attr("cx", x)
.attr("cy", y)
.attr("r", 5)
.style("fill", "red")
};
</script>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Your refactor is better but this line
.attr("transform", "translate(q, r), scale(4)")
Should be written as:
.attr("transform", "translate(" + q + "," + r + "), scale(4)")
Here's the whole code cleaned up a bit more:
<!DOCTYPE html>
<html lang="en" class="tas-com">
<head>
<meta charset="utf-8">
<title>Simple Stars</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body>
<h1>Some Stars</h1>
<svg width="200" height="200" style='background: aliceblue'>
</svg>
<script type="text/javascript">
var svg;
function draw(q, r) {
var x = 100 + 60 * Math.cos(q),
y = 100 + 60 * Math.sin(q)
svg.append("circle")
.attr("cx", x)
.attr("cy", y)
.attr("r", 5)
.style("fill", "red");
svg.append("polygon")
.attr("points", "0,0.9511, 1.0,0.95111, 1.309,0, 1.618,0.9511, 2.618,0.9511, 1.809,1.5388, 2.118,2.4899, 1.309,1.9021, 0.5,2.4899, 0.809,1.5388")
.attr("fill", "blue")
.attr("transform", "translate(" + (x - 5) + "," + (y - 5) + "), scale(4)")
.style("fill", "yellow");
}
svg = d3.select("svg");
svg.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", 200)
.attr("height", 200)
.style("fill", "blue");
for (var i = 0; i < 150; i += 15) {
var o = 30
draw(o + i, o + i)
}
</script>
</body>
</html>

Add border to a line element of d3js

I am trying to add a black border to a line element of the d3js library. How can I do that ? I tried it with following Code:
Plunker:https://plnkr.co/edit/brSPxoRczQcULz3IxXQk?p=preview
CSS:
<style>
line.linecap {
border-style:dashed;
border-width:2px;
border-color: black;
}
</style>
JavaScript
<script>
var line = d3.select("body")
.append("svg")
.attr("width", 449)
.attr("height", 249);
line.append("line")
.style("stroke", "rgb(220, 220, 220)")
.attr("stroke-width", 94)
.classed('linecap', true)
.attr("x1", 139)
.attr("y1", 487)
.attr("x2", 139)
.attr("y2", 92);
</script>
SVG elements don't have border. Please check this list: https://www.w3.org/TR/SVG/propidx.html
That being said, the simple alternative is making another line, with the colour you want, a little bit thicker:
var line = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 300);
line.append("line")
.style("stroke", "red")
.attr("stroke-width", 96)
.classed('linecap', true)
.attr("x1", 139)
.attr("y1", 291)
.attr("x2", 139)
.attr("y2", 9);
line.append("line")
.style("stroke", "rgb(220, 220, 220)")
.attr("stroke-width", 94)
.classed('linecap', true)
.attr("x1", 139)
.attr("y1", 290)
.attr("x2", 139)
.attr("y2", 10);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
You can draw a rectangle (SVG rect) instead of a line, then border is available using stroke.
line.append("rect")
.style("stroke-width", "3")
.style("fill", "none")
.style("stroke", "rgb(220, 220, 220)")
.attr("x", 139)
.attr("y", 92)
.attr("width", 94)
.attr("height", 487 - 92 );
Updated plnkr
P.S. the line drawn gets outside of the svg boundaries, I didn't fix this problem (to do so, just adjust the coordinates as wanted).

mouseover doesn't work on d3 rectangle

I am new at d3. I have written the below code for 3 rectangles to appear and make them have some mouse interaction.
svg.append("g").selectAll("rect")
.data([1,2,3])
.enter()
.append("rect")
.attr("x",function(d,i){return 600+i*50;})
.attr("y",30)
.attr("width",40)
.attr("height",40)
.attr("fill","blue")
.on("mouseover",function(d) {
d3.select(this).append("text")
.attr("y", "100")
.attr("x", "500")
.attr("class", "hover")
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.style("fill", "black")
.text(function(d){console.log("mouseover");
return "Text I want";})
})
.on("mouseout", function(d) {
d3.select(this).select("text.hover").remove();
})
.on("click",function(d){console.log(d);
if(d==1)
Pie(array1,array2);
if(d==2)
Pie(array3,array4);
if(d==3)
Pie(array5,array6);
})
.style("opacity",1e-6)
.transition()
.duration(1000)
.style("opacity",0.8);
The console.log("mouseover") appears at the console, but no text is shown at the browser. The click event works with pie charts being constructed. Can anybody spot what is going wrong? Thank you in advance.
In your mouseover:
d3.select(this).append("text")
would append the text to the rect but rect elements can not have children.
Changing it to:
svg.append("text")
works. Full code example:
<!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', 500)
.attr('height', 500);
svg.append("g").selectAll("rect")
.data([1, 2, 3])
.enter()
.append("rect")
.attr("x", function(d, i) {
return 10 + i * 50;
})
.attr("y", 30)
.attr("width", 40)
.attr("height", 40)
.attr("fill", "blue")
.on("mouseover", function(d) {
svg.append("text")
.attr("y", "100")
.attr("x", "200")
.attr("class", "hover")
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.style("fill", "black")
.text(function(d) {
console.log("mouseover");
return "Text I want";
})
})
.on("mouseout", function(d) {
svg.select("text.hover").remove();
})
.on("click", function(d) {
console.log(d);
if (d == 1)
Pie(array1, array2);
if (d == 2)
Pie(array3, array4);
if (d == 3)
Pie(array5, array6);
})
.style("opacity", 1e-6)
.transition()
.duration(1000)
.style("opacity", 0.8);
</script>
</body>
</html>
I think you should use d3-tip module for d3. It provides very nice hover tooltip
http://bl.ocks.org/Caged/6476579
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong>Frequency:</strong> <span style='color:red'>" + d.frequency + "</span>";
})
and on bars or rectangles use
.on('mouseover', tip.show)
.on('mouseout', tip.hide)

How to display a text when mouseover a cilcle

I have tried a code but it dosent work properly. Can you suggest a method to resolve the error. I am new to Visualization and at the beginning stage of d3.js
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js"> </script>
</head>
<body>
<div id="viz"></div>
<script type="text/javascript">
var sampleSVG = d3.select("#viz")
.append("svg")
.attr("width", 100)
.attr("height", 100);
sampleSVG.append("circle")
.style("stroke", "gray")
.style("fill", "white")
.attr("r", 40)
.attr("cx", 50)
.attr("cy", 50)
.on("mouseover", function() {d3.select(this).append("text").attr("fill","blue").text("fill aliceblue");})
</script>
</body>
</html>
Your are trying to append the text element to the circle, which is not possible.
Create a group element and add your circle and text elements to that group.
Here is an example.
var sampleSVG = d3.select("#viz")
.append("svg")
.attr("width", 100)
.attr("height", 100);
var grp = sampleSVG.append("g");
var circle = grp.append("circle")
.style("stroke", "gray")
.style("fill", "white")
.attr("r", 40)
.attr("cx", 50)
.attr("cy", 50);
circle.on("mouseover", function() {
grp.append("text")
.style("fill", "black")
.attr("x", 32)
.attr("y", 52)
.text("Hello");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="viz"></div>
As suggested here: https://stackoverflow.com/a/16780756/1023562
Create a tooltip div and attach it to mouseover, mousemove and mouseout events.
var tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("a simple tooltip");
sampleSVG.append("circle")
.style("stroke", "gray")
.style("fill", "white")
.attr("r", 40)
.attr("cx", 50)
.attr("cy", 50)
.on("mouseover", function(){return tooltip.style("visibility", "visible");})
.on("mousemove", function(){return tooltip.style("top",
(d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px");})
.on("mouseout", function(){return tooltip.style("visibility", "hidden");});
Working fiddle: https://jsfiddle.net/vc95wcvm/
Note that in this Fiddle I have loaded http://d3js.org/d3.v2.js in the script panel (because Fiddle refuses to load it over http, it requires https), so the code that interests you is at the bottom of script panel.

Categories

Resources