I have been trying to create a dynamic line chart in d3.js, using the tutorial here. I have almost got it working, but there is a slight problem. When I choose a date interval using the viewport and redraw the chart, it draws the line outside of the axis too. See the left of the graphic below.
Normally, I draw the line as below:
var valueline = d3.svg.line()
.x(function (d) {
return xScale(d.timestamp);
})
.y(function (d) {
return yScale(d.value);
});
plotChart.append("path")
.attr("class", "line")
.attr("id", "lineGraphId")
.attr("d", valueline(data));
And my redraw chart function is as below:
function redrawChart() {
plotChart.select("#lineGraphId").remove();
plotChart.append("path")
.attr("class", "line")
.attr("id", "lineGraphId")
.attr("d", valueline(data));
plotChart.select('.x.axis').call(xAxis);
}
I could not find a solution for drawing outside of the axis. I could not host my code in jsfiddle because I needed to load a csv data, but you can see all source code here.
Apparently, I needed to add this line of code to redrawChart function:
.attr('clip-path', 'url(#plotAreaClip)')
Related
My implementation for Brush & Zoom functionality in my d3 line chart is not working as expected,
I followed this link - https://bl.ocks.org/EfratVil/92f894ac0ba265192411e73f633a3e2f,
Problems what I am facing is -
chart is not showing all the values, I have 4 data but it only shows 3 data
onClick of dot I am showing the rect which is not moving with the brush functionality
minor thing but chart always goes out of the box
My code sandbox - https://codesandbox.io/s/proud-firefly-xy1py
Can someone point out what I am doing wrong? thanks.
Please suggest me what I am doing wrong, thanks.
Your first point is going behind your clip area. For example, if you right click on the first visible circle and inspect element you will see all 4 circle elements are present in the dom. The first circle element is behind the axis.
This means you have to move your plot to the right. Unfortunately, the way you have coded the chart you have not appended a g element for the main chart and then appended the circles and path to that g element. As a result this has to be done in multiple places.
First we adjust your clip path as:
svg
.append("defs")
.append("SVG:clipPath")
.attr("id", "clip")
.append("SVG:rect")
.attr("width", containerWidth)
.attr("height", height)
.attr("x", 40)
.attr("y", 0);
next we adjust your circles
scatter
.selectAll(".foo")
.data(data)
.enter()
.append("circle")
.attr("class", "foo")
.attr("transform", "translate(40,0)")
and then your line
scatter
.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line)
.attr("transform", "translate(40,0)");
You will have to account for this 40 px translate for your other elements as well. Although I am having a hard time destructuring your svg. I think this should give you the idea though. Check the axis matches the time points as well.
Check the code sand box
Update
To make the rectangles move with the brush, you will have to add code to your brushed const function to recalculate the x, y, width and height using the updated scales.
Update2
After going through the codesandbox presented in the comments I was able to add the code to update the rectangles to the brushed const as below to make the rects also move with the brushing:
// update rectangles
scatter
.selectAll(".rect-elements")
.attr("x", d => {
console.log(d);
return xScale(d.startTime) - 12.5;
})
.attr("y", 0)
.attr("width", 24)
.attr("height", height + 5);
Full working Code Sandbox.
I'm trying to achieve similar line effect to the one visible on those charts: https://www.informationisbeautifulawards.com/showcase/2873-a-night-under-the-stars
To build my visualization I use React + d3.
This is the code for my line:
var avgWeekday = d3.selectAll('.radial').append("path")
.datum(this.props.avgWeekday)
.attr("fill", "none")
.attr("stroke", "#2A41E5")
.attr("stroke-width", function(d) { return d.value; })
.attr("d", line);
The line is rendered properly but the stroke width is not assigned, what am I doing wrong here?
The data from this.props.avgWeekday looks like this:
However when I actually try to print it inside stroke-width function I get undefined.
I started from a sample Map app at: http://bl.ocks.org/d3noob/raw/5193723/
I want to place a custom pie chart, as shown in the fig below. I created one by adding the code snippet just after the creation of circles is done.
Pie-chart Snippet:
var r=10;
var p = Math.PI*2;
var arc = d3.svg.arc()
.innerRadius(r-3)
.outerRadius(r)
.startAngle(0)
.endAngle(p* d.value1);
var arc2 = d3.svg.arc()
.innerRadius(r-7)
.outerRadius(r-4)
.startAngle(0)
.endAngle(p* d.value2);
g.append("path")
.attr("d", arc)
.attr("fill", "red")
.attr("transform", "translate(400,500)");
g.append("path")
.attr("d", arc2)
.attr("fill", "orange")
.attr("transform", "translate(400,500)");
It comes out nicely as shown in the pic below near Thailand:
Problem
When I zoom or move the map, the pie-chart disappears but the circles remain intact. Can someone help me understand it?
One can notice a very crude way the arcs are plotted. The pie-chart is expected to be plotted for each of the city. I am looking for a cleaner way just like the way circles are drawn.
The code that runs when zoom takes place
g.selectAll("path")
.attr("d", path.projection(projection));
is selecting all paths and modifying their "d" attribute. Since it's "generically" just looking for pathss, then it's also grabbing the donut paths you created and modifying them (probably setting them to empty strings or NaNs).
You can fix this either by taking the donuts out of the same g of the geo paths, so that they don't get selected. OR, you can make your "path" selector more specific, by adding some class (e.g. "geo") to all the geo paths and using that class whenever you select them (e.g. g.selectAll("path.geo")).
I'm having trouble getting the area portions of a difference chart to properly execute transitions.
As I am still learning, the chart is based on Mike Bostock's Difference Chart example and the transitions were guided by d3noob's transitions post.
Relevant bits:
svgchin.select("#clip-above-chin path")
.duration(750)
.attr("d", area.y0(0));
svgchin.select("#clip-below-chin path")
.duration(750)
.attr("d", area.y0(height));
svgchin.select(".area.above")
.duration(750)
.attr("d", area.y0(function(d) { return y(d["Post"]); }));
svgchin.select(".area.below")
.duration(750)
.attr("d", area);
Full jsFiddle here: http://jsfiddle.net/uxb3yq9g/6/
As you can see, the lines and axes update as intended. The areas, however, are not yet on board.
Any ideas?
You haven't actually updated the data bound to the elements. Just do
var svgchin = d3.select("#chinook").datum(data).transition();
and everything works fine. Complete demo here.
I'm using a D3 brush to update the arcs of a donut chart, but the update is occurring only after I release the brush. I know that D3 is capable of brush-based continuous updating as Mike has done in this example; what part of that code have I missed in my adaptation?
Here's the function that I currently use to do the updating:
function brushended() {
path.select('.donutPath')
.data(pie([brush.extent()[1],100 - brush.extent()[1]]))
.enter().append("path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc);
}
The event you need to listen to is .on("brush",..., like:
var brush = d3.svg.brush()
.x(x)
.extent([0,40])
.on("brush", brushended);
You should change the name of the function to better reflect the situation, but this alone will make it work.
FIDDLE with the listener changes, but also with changes to the way the update selection was being handled.