d3.js - 如果y.domain不从0开始,则区域图表垂直溢出

时间:2017-12-07 14:25:48

标签: javascript d3.js

如何限制区域图表的内容以保持在由两个轴确定的区域内?

以下是这种情况。如果我将垂直域设置为0到我的数据集的最大值,我就不会遇到问题:

y.domain([0, 1.1*d3.max(data, function(d) { return d.value; })]);

correct

然而,有时我不能从0开始。当我需要从数据集中的最小数字开始时,问题出现了:

y.domain([0.91*d3.min(data, function(d) { return d.value; }), 1.1*d3.max(data, function(d) { return d.value; })]);

incorrect

如你所见,图表的蓝色区域流过底部水平轴,这只是丑陋和凌乱。我可以切换到折线图以避免这个问题,但我更愿意保留一个面积图并解决问题。任何解决方案?

编辑这是我正在使用的完整代码。如果full参数为true,则图表从0开始。如果不是,则从最小数据开始。

function create_area_chart(data, full){
    var svg = d3.select(".chart-holder").append("svg").attr("width","800").attr("height", "400")
        margin = {top: 20, right: 20, bottom: 30, left: 50},
        width = +svg.attr("width") - margin.left - margin.right,
        height = +svg.attr("height") - margin.top - margin.bottom,
        g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var parseTime = d3.timeParse("%Y-%m-%d")
        bisectDate = d3.bisector(function(d) { return d.date; }).left;

    var x = d3.scaleTime()
        .rangeRound([0, width]);

    var y = d3.scaleLinear()
        .rangeRound([height, 0]);

    var area = d3.area()
        .x(function(d) { return x(d.date); })
        .y1(function(d) { return y(d.value); });

    data.forEach(function(d) {
        d.date = parseTime(d.date);
        d.value = +d.value;
    });

    x.domain(d3.extent(data, function(d) { return d.date; }));
    if(full)
        y.domain([0, 1.1*d3.max(data, function(d) { return d.value; })]);
    else
        y.domain([0.91*d3.min(data, function(d) { return d.value; }), 1.1*d3.max(data, function(d) { return d.value; })]);
    area.y0(y(0));

    g.append("path")
        .datum(data)
        .attr("fill", "steelblue")
        .attr("d", area);

    g.append("g")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(x));

    g.append("g")
        .call(d3.axisLeft(y))
        .append("text")
        .attr("fill", "#000")
        .attr("transform", "rotate(-90)")
        .attr("y", 6)
        .attr("dy", "0.71em")
        .attr("text-anchor", "end")
        .text("Price ($)");

    svg.append("rect")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
        .attr("class", "overlay")
        .attr("width", width)
        .attr("height", height);
}

2 个答案:

答案 0 :(得分:1)

您需要通过更改floor

为区域图表设置y0
if(full){
    y.domain([0, 1.1*d3.max(data, function(d) { return d.value; })]);
    area.y0(y(0));
} else {
    y.domain([0.91*d3.min(data, function(d) { return d.value; }), 1.1*d3.max(data, function(d) { return d.value; })]);
    area.y0(y(0.91*d3.min(data, function(d) { return d.value; })));
}

请参阅文档:https://github.com/d3/d3/blob/master/API.md#areas

修改

重现问题

考虑改编OP代码的这个区域chart

我在示例中运行代码并得到以下图:

enter image description here

一切都如预期。 y domainy0的设置如下:

y.domain([0, d3.max(data, function(d) { return d.close; })]);
area.y0(y(0));

现在,如果我将y domain更改为:

y.domain([
    0.91*d3.min(data, function(d) { return d.close; }),
    d3.max(data, function(d) { return d.close; })
]);

我得到以下情节:

enter image description here

我们收到了溢出信息,但如果我现在更改y0()以匹配新的y domain

area.y0(y(0.91*d3.min(data, function(d) { return d.close; })));

其中的情节:

enter image description here

溢出现在已得到纠正。

答案 1 :(得分:0)

我认为问题可能来自你的尺度范围。

也许尝试用

var y = d3.scaleLinear()
        .rangeRound([height-margin.bottom, margin.top]);

编辑:虽然你的代码可能不是什么问题,因为你已经定义了height减去两个边距。对不起,祝你好运!