D3.js folded areas with a color change above a certain value

At work, someone who is no longer available has made an application with a D3.js schedule, it is not finished yet, and I have to finish it. However, I was not, and I still am not familiar with the D3.js library, I could fix some things. But one thing that I just can’t fix, I have a graph with a colored area that works and looks good, which should show a red graph instead of a yellow one if the value is exceeded. In this case, the value is -30, therefore, above the red line (see Figures).

The image on the left shows what I have now, and what I need:

Current graphThe solution

I found out that several areas can be stacked using d3.layout.stack() . But I only find code examples using hard-coded JSON or multiple graphs on top of each other.
The code below is what I have now: (I cut that doesn't matter)

 var area = d3.svg.area() .interpolate("basis") .x(function (d) {return x(d.date); }) .y0(function (d) {return y(0); }) .y1(function (d) {return y(d.energy); }); var svg = d3.select("#datacontainer2").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom); svg.append("defs").append("clipPath") .attr("id", "clip") .append("rect") .attr("width", width) .attr("height", height); var context = svg.append("g").attr("transform","translate("+margin2.left+","+margin2.top + ")"); d3.csv("file:///data.txt", function (error, data) { data.forEach(function (d) { d.date = parseDate(d.date); d.energy = d.energy; }); x.domain(d3.extent(data.map(function (d) { return d.date; }))); y.domain([25, -50] /*d3.extent(data.map(function(d) { return d.energy; }))*/ ); x2.domain(x.domain()); y2.domain(y.domain()); focus.append("path") .datum(data) .attr("clip-path", "url(#clip)") .attr("d", area); // red line focus.append("svg:line") .attr("x1", 0) .attr("x2", height * data.length) .attr("y1", (function (d) { return y(-30); } )) .attr("y2", (function (d) { return y(-30); })) .attr("stroke", "#ff0000") .attr("stroke-width", "3"); }); 

In addition, all values ​​below zero should be green, but this can be easily extended if there is code for the above question.

+4
source share
2 answers

This is what you can look for: http://jsfiddle.net/h45CD/ .

 Create a area gradient and color according to that. // Set the threshold svg.append("linearGradient") .attr("id", "area-gradient") // change from line to area .attr("gradientUnits", "userSpaceOnUse") .attr("x1", 0).attr("y1", y(0)) .attr("x2", 0).attr("y2", y(1000)) .selectAll("stop") .data([ {offset: "0%", color: "red"}, {offset: "30%", color: "red"}, {offset: "45%", color: "black"}, {offset: "55%", color: "black"}, {offset: "60%", color: "lawngreen"}, {offset: "100%", color: "lawngreen"} ]) .enter().append("stop") .attr("offset", function(d) { return d.offset; }) .attr("stop-color", function(d) { return d.color; }); 

You can learn more about this in d3noob .

+3
source

This is an old question, but if it helps anyone who stumbles upon this question, I have a similar problem. I hate how gradients look visually, so I was looking for an alternative answer. Another, and, in my opinion, a cleaner approach can be used using this example from Mike himself.

http://bl.ocks.org/mbostock/4062844

+1
source

Source: https://habr.com/ru/post/1499747/


All Articles