【问题标题】:yScale not acting consistently d3.jsyScale 行为不一致 d3.js
【发布时间】:2017-09-10 22:54:11
【问题描述】:

我正在绘制一个带有坐标轴的条形图,yScale 在我的 yAxis 上的行为与在我附加的条形图上的行为不同。

我将 yScale 范围设置为从 (h - yPadding) 开始,以便在底部为 xAxis 标签留出额外空间。

                var yScale = d3.scale.linear()
                            .domain([0, d3.max(val)])
                            .range([h - yPadding, 0]);

-- 范围是倒置的,否则我的 yAxis 标签是颠倒的。

当我使用 yScale 调用 yAxis 时,它遵循 (h - yPadding) 的起点并在底部留出空间。

但我添加到图表的所有“矩形”都从 h 开始,而不是 (h - yPadding),即使我在这些“矩形”上调用 yScale,就像在 yAxis 上一样。

如果我将范围更改为 [h, 0] 而不是 [h - yPadding, 0],则只有 yAxis 会对更改做出反应,并且条形仍然从 h 开始。

为什么条形图忽略了 yScale?

    <script type="text/javascript">
        var xhr = new XMLHttpRequest();

        function makeRequest(){
            xhr.open("GET", "https://api.coinmarketcap.com/v1/ticker/", true);
            xhr.send();
            xhr.onreadystatechange = processRequest;
        }

        function processRequest(){
            console.log("testing, state: ", xhr.readyState)
            if(xhr.readyState == 4 && xhr.status == 200){
                dataset = [];
                for(var i = 0; i < 10; i++){
                    addingId = JSON.parse(xhr.responseText)[i];
                    addingId.id = i;
                    dataset.push(addingId);
                }
                console.log("this is dataset: ", dataset);
                makeChart();
            }
        }

        function makeChart(){
            var w = 1000;
            var h = 600;
            var padding = 40;
            var yPadding = 80;

            var val = [];
            dataset.forEach(function(ele){
                val.push(parseInt(ele.market_cap_usd));
            })
            var max = d3.max(val)

            var xAxisNames = []

            dataset.forEach(function(ele){ xAxisNames.push(ele.name); })
            // console.log(">>>>>>>>", xAxisNames)

            var xScale = d3.scale.ordinal()
                            .domain(d3.range(dataset.length))
                            .rangeRoundBands([padding, w - padding], 0.05)

            var yScale = d3.scale.linear()
                            .domain([0, d3.max(val)])
                            .range([h - yPadding, 0]);

            var yAxis = d3.svg.axis()
                            .scale(yScale)
                            .orient("left")
                            .tickFormat(function(d){
                                if(d > 0){ return d / 1000000000 + " b"; }
                                return "";
                            })

            var xAxis = d3.svg.axis()
                            .scale(xScale)
                            .orient("bottom")
                            .tickFormat(function(d, i){
                                return xAxisNames[i]
                            })

            var svg = d3.select("body")
                        .append("svg")
                        .attr("width", w)
                        .attr("height", h);

            svg.selectAll("rect")
                .data(dataset)
                .enter()
                .append("rect")
                .attr("x", function(d, i){
                    return xScale(i);
                })
                .attr("y", function(d){
                    return yScale(d.market_cap_usd);
                })
                .attr("width", xScale.rangeBand())
                .attr("height", function(d, i){
                    return h - yScale(d.market_cap_usd)
                })

            svg.append("g")
                .attr("class", "y axis")
                .attr("transform", "translate(" + padding + ", 0)")
                .call(yAxis);

            svg.append("g")
                .attr("class", "x axis")
                .attr("transform", "translate(0, " + (h - yPadding) + ")")
                .call(xAxis)
                .selectAll("text")
                .attr("y", 15)
                .attr("font-size", 12)
                .attr("x", xScale.rangeBand() / 2)
                .attr("transform", "rotate(45)")
        }

        makeRequest();

    </script>

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    比例只是将输入域映射到输出范围,仅此而已。您必须相应地设置 SVG 元素的位置和尺寸。让我们看看:

    现在,鉴于您的规模,当您将域中的最小值传递给它时,它将返回:

    h - yPadding
    

    当然,您希望这些条的高度为零像素。为了得到这个零,方程很简单,你必须从那个值中减去:

    (h - yPadding) - yScale(minimumDomainValue)
    

    这将使域中的最小值为零。

    因此,这应该是矩形的高度:

    .attr("height", function(d, i){
        return (h - yPadding) - yScale(d.market_cap_usd)
    })
    

    PS:顺便说一下,在 D3 中,比例决定 SVG 元素尺寸的少数情况之一是轴生成器创建的路径/线。这就是为什么您会在轴上看到不同的行为。

    【讨论】:

    • 好的,我明白你在说什么,谢谢!我认为 (h - yPadding) 会弄乱条的比例,但它只是设置条停止的 x/y 坐标。很好用!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多