Hi i have a donut pie chart and I want to make it grow when the page loads.
It was a normal donut chart that when i clicked on one of the element it would show it's info.
I added the growing part and it is working but my mouseclick part (that was working before the grow part) stopped working.
It says that "undefined is not a function" on the .on("mouseup", function(d, i) line.
So it works with the transition, it works with the mouseup but it's not working with both.
renderarcs.append('path')
.attr('d',arc)
.attr("fill", function(d, i) { return color(i); })
.transition()
.duration(2000)
.attrTween("d", tweenPie)
.on("mouseup", function(d, i){
$("#mostra-nome-banda").html(arrayBandas[i]['name']);
$("#pag-banda-plays").html(arrayBandas[i]['playcount']+" plays");
linkArtista= arrayBandas[i]['url']
d3.selectAll('path').transition()
.duration(100)
.attr("d", arc)
d3.select(this).transition()
.duration(100)
.attr("d", arcOver);
});
You need to add the handler before the transition:
renderarcs.append('path')
.attr('d',arc)
.attr("fill", function(d, i) { return color(i); })
.on("mouseup", function(d, i){
$("#mostra-nome-banda").html(arrayBandas[i]['name']);
$("#pag-banda-plays").html(arrayBandas[i]['playcount']+" plays");
linkArtista= arrayBandas[i]['url']
d3.selectAll('path').transition()
.duration(100)
.attr("d", arc)
d3.select(this).transition()
.duration(100)
.attr("d", arcOver);
})
.transition()
.duration(2000)
.attrTween("d", tweenPie);
Otherwise, you're attaching an event handler to the transition and not the selection. Transitions don't have mouseup events.
Related
i have a line(x-y axis) and some data points on that line. line is moving from right to left based on some fixed interval of 200ms and the data points on the line are also moving along with the line.
But the issue is that, there is some delay in the movement of circles. See the jsfiddle(scroll to the right on fiddle page to see the issue i.e. delay in circle movement)
https://jsfiddle.net/rajatmehta/tm5166e1/13/
chartBody.selectAll(".dot1")
.data(globalData, function(d){ return d.timestamp; })
.enter()
.append("circle")
.attr("class", "dot1")
.attr("r", 3)
.attr("cx", function(d) {
return x(d.timestamp);
})
.attr("cy", function(d) {
return y(d.value);
});
chartBody.selectAll(".dot2")
.data(globalDataNew, function(d){ return d.timestamp; })
.enter()
.append("circle")
.attr("class", "dot2")
.attr("r", 3)
.attr("cx", function(d) {
return x(d.timestamp);
})
.attr("cy", function(d) {
return y(d.value);
});
d3.selectAll(".dot1")
//.data(globalData)
.transition()
.duration(duration)
.ease("linear")
.attr("transform", "translate(" + String(dx) + ")");
d3.selectAll(".dot2")
//.data(globalDataNew)
.transition()
.ease("linear")
.duration(duration)
.attr("transform", "translate(" + String(dxNew) + ")");
how to prevent this delay ?
You can select dot1 and dot2 at same time and apply transition.
Currently you are selecting them and apply transition to each of them separately hence the delay
I have 2 lines in the form of waves plotted in x-y axis based on randomly generated data and i am showing circles on the waves denoting the data points on it.
Based on setInterval of 200 ms, I am updating the original data and the lines(waves) are moving to the left, but the issue is that the only circles which are there in the initial interval are moving and for 2nd interval onward the circles are not showing up on the waves.
see the jsfiddle for the running code : https://jsfiddle.net/rajatmehta/tm5166e1/10/
here is the code :
chartBody.append("path") // Add the valueline path
.datum(globalData)
.attr("id", "path1")
.attr("class", "line")
.attr("d", valueline);
chartBody.selectAll(null)
.data(globalData)
.enter()
.append("circle")
.attr("class", "dot1")
.attr("r", 3)
.attr("cx", function(d) {
console.log(d);
return x(d.timestamp);
})
.attr("cy", function(d) {
return y(d.value);
});
chartBody.selectAll(null)
.data(globalDataNew)
.enter()
.append("circle")
.attr("class", "dot2")
.attr("r", 3)
.attr("cx", function(d) {
return x(d.timestamp);
})
.attr("cy", function(d) {
return y(d.value);
});
chartBody.append("path") // Add the valueline path
.datum(globalDataNew)
.attr("id", "path2")
.attr("class", "line")
.attr("d", valueline2);
any idea how to do that ?
You need to create new circles based on the updated data. Currently, you are only updating the data to selection, but not appending circles, and then moving existing circles to the left.
For example, you could to this:
chartBody.selectAll(".dot1")
.data(globalData, function(d){ return d.timestamp; })
.enter()
.append("circle")
.attr("class", "dot1")
.attr("r", 3)
.attr("cx", function(d) {
return x(d.timestamp);
})
.attr("cy", function(d) {
return y(d.value);
});
chartBody.selectAll(".dot2")
.data(globalDataNew, function(d){ return d.timestamp; })
.enter()
.append("circle")
.attr("class", "dot2")
.attr("r", 3)
.attr("cx", function(d) {
return x(d.timestamp);
})
.attr("cy", function(d) {
return y(d.value);
});
d3.selectAll(".dot1")
//.data(globalData)
.transition()
.duration(duration)
.ease("linear")
.attr("transform", "translate(" + String(dx) + ")");
d3.selectAll(".dot2")
//.data(globalDataNew)
.transition()
.ease("linear")
.duration(duration)
.attr("transform", "translate(" + String(dx) + ")");
See here: https://jsfiddle.net/tm5166e1/11/
This appends the data, using the timestamp as a key so you only create new circles for newly added datums.
(There is an issue when they are first added which is beyond the scope of this question, but it will be worth checking out these examples: https://bl.ocks.org/tomshanley/15a2b09a95ccaf338650e50fd207fcbf and https://bl.ocks.org/mbostock/1642874)
I am trying to add an OnClick event to the nodes of my force layout graph but when I try to click on them, nothing happens. I believe that it is because I am not using an svg element and the .on("click", click) only works with svg elements I think but I am not entirely sure. Here is the code that I am trying to implement:
var node = svg.selectAll(".node")
.data(nodes)
.enter().append("circle")
.attr("r",function(d) {return d.size})
.style("fill",function(d) {return color(d.type);})
.on("click", click)
.call(force.drag);
node.append("title")
.text(function(d){return d.name;});
force.on("tick", function(){
node.attr("cx", function(d){return d.x;})
.attr("cy", function(d) {return d.y;});
link.attr("x1", function(d){return d.source.x;})
.attr("y1", function(d){return d.source.y;})
.attr("x2", function(d){return d.target.x;})
.attr("y2", function(d) {return d.target.y;});
});
function click() {
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", 30)
.style("fill", "lightsteelblue");
}
When I try and click on a node, nothing happens. I am not sure what to do. I think the problem has to do with the:
.enter().append("circle")
I think it needs to be an svg element like ("g") or ("svg") but I couldn't figure that out. Any advice or suggestions would be appreciated. Thanks!
You have an extra .select("circle") in click(). Instead, it should start with just:
function click(){
d3.select(this).transition()...
}
I have some circles that I want to change fill when I hover over them. I give them "pins" class and here's the CSS for them:
.pin {
fill: #9ecae1;
stroke:#3182bd;
}
.pin:hover{
fill:steelblue;
}
Each pin has a value and I want to include some transition so that if there is a change in that value, the circles will momentarily flash some other color, green for instance. They work fine without the update. After the update, the hover no longer works.
Here is my code for the transition:
d[2] is just some key name.
svg.selectAll("circle").data(points, function(d) {return d[2];})
.transition()
.duration(500)
.style("fill", "green")
.attr("r", function(d) {return 5 + 10*Math.ceil(radius(d[3]));})
.each("end", function(d){
d3.select(this).transition()
.style("fill", "#9ecae1");
});
I was able to pinpoint that setting style("fill", xxx) disables the hover but why? And is there a way to get the momentary transition while still maintaining the hover?
I understood the problem, that is in the below code
svg.selectAll("circle").data(points, function(d) {return d[2];})
.transition()
.duration(500)
.style("fill", "green")
.attr("r", function(d) {return 5 + 10*Math.ceil(radius(d[3]));})
.each("end", function(d){
d3.select(this).transition()
.style("fill", "#9ecae1");
});
we are applying the color by using inline style, this inline is more priority than external css, So don't apply the color by using inline style instead use the attribute(fill) to fill the color, the line of code we have to change is remove .style("fill", "green") and replace it with attr("fill", "green")
and .style("fill", "#9ecae1") with .attr("fill", "#9ecae1")
Below is the modified code
svg.selectAll("circle").data(points, function(d) {return d[2];})
.transition()
.duration(500)
.attr("fill", "green")
.attr("r", function(d) {return 5 + 10*Math.ceil(radius(d[3]));})
.each("end", function(d){
d3.select(this).transition()
.attr("fill", "#9ecae1");
});
:)
I have some code that create a bunch of circles, updates those circles, removes some of the circles, and lastly I'd like to find out how to use the enter() correctly to add more circles to my current ones.
This is my code for creating circles when there are none:
var circle = SVGbody
.selectAll("circle")
.data(graphDataY/*, function(d){return d;}*/);
circle.enter()
.append("circle");
circle
.attr("cx",xScale(0))
.attr("cy", yScale(minAxisY))
.attr("r",4)
.style('opacity', 0)
.style("fill", colorCircles())
.transition()
.duration(1000)
.attr("cx", function(d, i){ return xScale(graphDataX[i]);})
//.attr("cy", function (d, i){ return yScale(i); })
.style('opacity', 0.8)
.transition()
.duration(1000)
.attr("cy", function(d){return yScale(parseFloat(d));} );
I use the following code to update my circles and remove the ones that aren't being used (sometimes that's the case):
var circle = SVGbody
.selectAll("circle")
.data(graphDataY);
circle
.style("fill", colorCircles())
.transition().duration(1000)
.attr("cx", function(d, i){ return xScale(graphDataX[i]);})
.attr("cy",function(d){return yScale(parseFloat(d));});
circle.exit()
.style("opacity", 1)
.transition()
.duration(300)
.style("opacity", 0)
.remove();
And when lastly, let's assume the last data i used had a length of 100, that means I currently have 100 circles displayed. If I used a new dataset with 120 of length, I use my update code to move the existing circle ( except for the exit().remove() ), and then I try to use the following to "create" the remaining circles out of the remaining unbound data (which in this case would be 20 circles remaining):
circle.enter().append("circle")
.attr("cx", function(d, i){ return xScale(graphDataX[i]);})
.attr("cy",function(d){return yScale(parseFloat(d));})
.style("opacity", 0)
.transition()
.duration(300)
.style("opacity", 1)