简体   繁体   中英

D3 Area chart with specified base/floor

Is it possible to make an area chart in D3 where I can specify what the floor of the area chart is (as another plot).

Something like this:

在此处输入图片说明

So instead of the floor being always at Y=0, it's actually a plot derived from y=1.03^X

This is my code:

var NSW = "NSW";
var QLD = "QLD";

var width = 600;
var height = 400;
var years = [];

var getStat = function(year, volatility, basis) {
    // volatility = 0.04;
    // basis = 1.11;

    return {
        d: year,
        x: basis,
        vol: volatility,
        value: 45 * Math.pow(basis, year),
        high: 45 * Math.pow(basis+volatility, year),
        low: 45 * Math.pow(basis-volatility, year),
    }
}

for(i = 0; i < 25; i++) {
    years.push(i);
}

var data = years.map(function(year){ return [getStat(year, 0.04, 1.11),getStat(year, 0.02, 1.07)]; });   // generate bogus data
var nsw = data.map(function(d) { return d[0].value;}); // extract new south wales data
var qld = data.map(function(d) { return d[1].value;}); // extract queensland data

var chart = d3.select("#chart").attr("width", width).attr("height", height).append("g");
var x = d3.scale.linear().domain([0, years.length]).range([0, width]);
var y = d3.scale.linear().domain([0, d3.max(data, function(d){ return Math.max(d[0].high, d[1].high); })]).range([height,0]);
var area = d3.svg.area().x(function(d,i) { return x(i); }).y0(height).y1(function(d, i) { return y(d); })

console.log([nsw,qld])

chart
.selectAll("path.area")
.data([nsw,qld])          // !!! here i can pass both arrays in.
.enter()
.append("path")
.attr("fill", "rgba(0,0,0,0.5)")
.attr("class", function(d,i) { return [NSW,QLD][i]; })
.attr("d", area);

And my HTML:

<svg id="chart"></svg>

Here is an example which will help you understand the context.

var area = d3.svg.area()
.x(function(d) { return x(d.xValue); })
.y0(height)
.y1(function(d) { return y(d.xValue^3); });

Now as you do this the base y0 is fixed at full height that is base of your chart right now. But fundamentally y0,y1 are both accessor functions. So basically you pass height to y0 each time for each data value. Now how ever if you change it to something like this:

var area = d3.svg.area()
.x(function(d) { return x(d.xValue); })
.y0(function(d){ return y(d.xValue/2);}) //FUNCTION FOR BASE-Y
.y1(function(d) { return y(d.xValue^3); }); //FUNCTION FOR TOP-Y

Now ideally the base of your area chart will vary accordingly. I hope this helps you achieve what you are trying. Please tellme if the solution doesn't work as expected. I'll create a fiddle then if necessary.

Edit: In response to changes in your question, each area you want to plot must have its own function. Now this would need you to write multiple area functions which is justified for just one or two areas. However if you plan to fill entire chart with multiple colored areas I believe you instead need to use this first d3 stack layout

In concept stack layout rearranges your data such that the returned layout object contains multiple arrays basically(I says arrays as it makes it simple to understand actual structure will be as you write your function I guess for mapping). Now you need a single area function which can be iteratively called for each instance in this returned layout. By each instance I mean different arrays which when passed to area function results in different areas.I hope my explanation helps a bit but I am new to the topic myself so here is an example which will help: Stacked Area Chart

This was the ideal way to do this, if you do not mind a simple workaround then this is what I am doing at the moment: say right now instead of just [nsw,qld] you want to plot areas for [nsw1,qld1],[nsw2,qld2],......so on.

iterationData = [[nsw,qld],[nsw1,qld1],[nsw2,qld2],........];
for(i in iterationData){
    chart
    .data(iterationData[i])
    .append("path")
    .attr("fill", "fixed_color_value/color_scale(category10/category20)")
    .attr("class", function(d,i) { return [NSW,QLD][i]; })
    .attr("d", area);
}

Hope this answers your question thoroughly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM