i've successfully added transitions to my circles in a node graph, but i'm now trying to animate the mouseover of the connective line.
here's what I've tried:
//define the lines:
var edges = svg.selectAll("line")
.data(dataset.edges)
.enter()
.append("line")
.style("stroke", "#ccc")
.style("stroke-width", 1)
.on("mouseover", lineMouseover)
.on("mouseout", lineMouseout);
//the callback functions for mouseover / mouseout
function lineMouseover() {
d3.select(this).select("line")
.transition()
.duration(100)
.style("stroke-width", 3);
}
function lineMouseout() {
d3.select(this).select("line")
.transition()
.duration(100)
.style("stroke-width", 1);
}
Nothing seems to happen at all when i mouse over the lines. so, either i'm capturing the line incorrectly, or the attributes i'm animating are the wrong attributes.
any insight into what I'm doing wrong here?
In your code, the thiscontext in the lineMouseOverand lineMouseOut functions is the line element. You could simply use d3.select(this)to select each line and set its attributes. I wrote a small fiddle http://jsfiddle.net/pnavarrc/4fgv4/2
svg.selectAll('path')
.data(data)
.enter()
.append('path')
.attr('d', function(d) { return line(d.p); })
.attr('stroke-width', function(d) { return d.w; })
.attr('stroke', function(d) { return d.c; })
.on('mouseover', mOver)
.on('mouseout', function(d) {
d3.select(this)
.transition()
.duration(300)
.style('stroke-width', d.w);
});
function mOver(d) {
d3.select(this)
.transition()
.duration(300)
.style('stroke-width', 6);
}
Regards,
Related
I have a line plot with some circle markers.
I'd like to add some mouseover and mouseout effects to the circles.
Here is my code:
let linePlot = svg.selectAll('.line')
.data(data);
// Draws the line
linePlot
.enter()
.append('path')
.merge(linePlot)
.datum(data)
.transition()
.duration(800)
.attr('class', 'line')
.attr('d', d3.line()
.x(function (d) { return xScale(d.YEAR); })
.y(function (d) { return yScale(d[metricType]); })
.curve(d3.curveMonotoneX)
);
linePlot
.exit()
.remove();
// Draws the circles
let circles = svg.selectAll('circle')
.data(data);
circles
.enter()
.append('circle')
.merge(circles)
.data(data)
.transition()
.duration(800)
.attr('fill', '#5e855d')
.attr('stroke', '#49614a')
.attr('cx', function(d) { return xScale(d.YEAR)})
.attr('cy', function(d) { return yScale(d[metricType])})
.attr('r', 6)
;
circles
.on('mouseover', function() {
d3.select(this)
.transition()
.duration(2000)
.attr('fill', 'red')
})
.on('mouseout', function() {
d3.select(this)
.transition()
.duration(2000)
.attr('fill', 'blue')
})
circles
.exit()
.remove();
The mouseout and mouseover effects are not working.
Any assistance would be greatly appreciated.
Thanks!
When you do this...
circles
.enter()
.append('circle')
.merge(circles)
.data(data)
.transition()
.duration(800)
.attr('fill', etc...
...you're basically setting circles as a transition selection, and transitions don't have mouseover as a typename. The only typenames allowed for a transition are:
start
end
interrupt
cancel
The idiomatic solution is breaking that chain:
circles.enter()
.append('circle')
.merge(circles)
.data(data);
circles.transition()
.duration(800)
.attr('fill', etc...
Now circles is a proper D3 selection, so you can do circles.on('mouseover', etc....
Finally, consider revising that data method after merging, it makes little sense to me.
I have the following code:
svg
.selectAll('mySlices')
.data(data_ready)
.enter()
.append('path')
.attr('d', arcGenerator)
.attr('fill', function(d){ return(color(d.data.key)) })
.attr("stroke", "black")
.style("stroke-width", "2px")
.style("opacity", 0.7)
And I'd like to append text elements right after each of my path elements.
This doesn't seem to work:
svg
.selectAll('mySlices')
.data(data_ready)
.enter()
.append('path')
.attr('d', arcGenerator)
.attr('fill', function(d){ return(color(d.data.key)) })
.attr("stroke", "black")
.style("stroke-width", "2px")
.style("opacity", 0.7)
.append('text')
.attr('class', 'label')
.text(function(d){ return d.data.key})
.attr("transform", function(d) { return "translate(" + arcGenerator.centroid(d) + ")"; })
.style("text-anchor", "middle")
.style("font-size", 10)
What's important to me is that each text element immediately follow the respective path element in the document so I can use the + CSS Sibling selector to show text on hover of the path element.
I'm open to alternatives, but can't think of any.
Ultimately I just want to display the text on hover for each pie segment.
Hi you can keep track of the selection storing it as a variable. The difference is that d3 working chaining and applying functions. You also need to add the class name for your selection, in case you want to select them.
const slices = svg
.selectAll('.mySlices')
.data(data_ready)
.enter()
.append('path')
.attr('d', arcGenerator)
.attr('fill', function(d){ return(color(d.data.key)) })
.attr("stroke", "black")
.style("stroke-width", "2px")
.style("opacity", 0.7)
.attr("class", "mySlices");
slices.append('text')
.attr('class', 'label')
.text(function(d){ return d.data.key})
.attr("transform", function(d) { return "translate(" + arcGenerator.centroid(d) + ")"; })
.style("text-anchor", "middle")
.style("font-size", 10);
I am new to d3 javascript library. I am trying to draw line over a circle using d3. I am able to create circle but somehow line does not appear on circle. See sample code attached. Any help is highly appreciated.
diag_circles.data(circle_data)
.enter()
.append("circle")
.attr("cx", function (d) {
console.log("d.x", d.x);
return d.x
})
.attr("cy", function (d) {
return d.y
})
.attr("r", function (d) {
return d.r
})
.append('line')
.attr("x1", function(d){return d.x- d.r})
.attr("y1", function(d){return d.y})
.attr("x2", function (d) { return d.x+ d.r})
.attr("y2", function(d){return d.y})
.attr("stroke-width", 20)
.attr("stroke", "black");
https://jsfiddle.net/c58859xy/
In a nutshell: you cannot append a line element to a circle element.
When creating your SVG, you have to know which elements allow appended children and what children they can have.
Solution: You'll have to append the lines to the SVG:
var lines = svg.selectAll('line')
.data(circle_data)
.enter()
.append("line")
.attr("x1", function(d){return d.x- d.r})
.attr("y1", function(d){return d.y})
.attr("x2", function (d) { return d.x+ d.r})
.attr("y2", function(d){return d.y})
.attr("stroke-width", 20)
.attr("stroke", "black");
Here is the updated fiddle: https://jsfiddle.net/c58859xy/1/
Transition Code,
d3.select('chart').select('svg')
.selectAll("circle")
.data(sampleData)
.enter().append('circle')
.each(function (d,i)
{
d3.select(this)
.transition()
.delay(i*50)
.attr('cx', function(d) {return d.x;})
.attr('cy', function(d) {return d.y;})
.attr('r', 4);
});
How can I stop/cancel the scheduled/delayed transactions?
The accepted answer does not work with the most recent version of d3. If you're using d3 v4, you should call .interrupt() on your selection.
As pointed out in the other answer, all you need is to schedule a new transition. However, the whole thing is much easier than what you're doing in your code -- there's no need for the separate .each() function. To schedule the transitions initially, you can simply do
d3.select('chart').select('svg')
.selectAll("circle")
.data(sampleData)
.enter().append('circle')
.transition()
.delay(function(d, i) { return i*50; })
.attr('cx', function(d) {return d.x;})
.attr('cy', function(d) {return d.y;})
.attr('r', 4);
The function to stop all transitions (scheduled and running) is simply
d3.selectAll("circle").transition();
Complete demo here.
Starting a new transition on the element stops any transition that is already running. You can pause/stop a d3 transition by setting a new transition with duration as 0.
function stopCircleTransitions(){
if(startedApplyingTransitions)
d3.select('chart').select('svg')
.selectAll("circle")
.each(function(d,i){
d3.select(this)
.transition()
.duration(0);
});
}
}
If you would like to stop the transition if and only if it is started applying, you can try the code below.
var startedApplyingTransitions = false;
d3.select('chart').select('svg')
.selectAll("circle")
.data(sampleData)
.enter()
.append('circle')
.each(function (d,i){
d3.select(this)
.transition()
.delay(i*50)
.attr('cx', function(d) {return d.x;})
.attr('cy', function(d) {return d.y;})
.attr('r', 4)
.each("end", function(){ //this code will do the trick
startedApplyingTransitions = true;
});
});
I am working on a toy pie chart using d3.js
My pie chart has 3 slices. I would like to know whether it is possible invoke a function whenever a slice of the pie-chart is clicked.
function animateFirstStep(){
d3.select(this)
.transition()
.attr("d",arc1);
/* .attr("d", arc2)
.style("fill", "black"); */
/* .style("stroke", "black")
.style("stroke-width", 1); */
};
function animateSecondStep(){
d3.select(this)
.transition()
.ease("elastic")
.duration(1500)
.attr("d", arc)
.style("fill", function(d) { return color(d.data.trName); });
/* .style("stroke", "white")
.style("stroke-width", 0); */
};
var g = svg.selectAll(".arc")
.data(pie(data.HubActivity.hubWorkloadList))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.trName); })
.on("mouseover", animateFirstStep)
.on("mouseout", animateSecondStep);
I think this would be of some help ... when you hover the mouse on any arc function will be fired you can change it to click