在D3中改变三角形的高度和方向

时间:2015-05-26 11:12:06

标签: svg d3.js

我有一个带红色和绿色三角形的基本条形图。如果数据为正,则数据与绿色三角形的负比较为红色三角形。绿色三角形应始终指向上方并在条形图底部向下红色,如果数据为中性,则应显示圆形。我无法将箭头/三角形对齐到底部(触摸x轴),也无法根据条件旋转箭头指向上方或下方。这是我的代码

svg.selectAll("line.arrow")
    .data(input.filter(function (d) { return d.AverageValue}))
    .enter().append("line")
    .attr("class", "arrow")
    .attr("x1", function (d) {
        return xScale(d.AppName) + xScale.rangeBand() / 2;
    })
    .attr("x2", function (d) {
        return xScale(d.AppName) + xScale.rangeBand() / 2;
    })
    .attr("y1", function (d) {
        return yScale(20);//bring arrows to bottom
    })
    .attr("y2", function (d) {
        var getValue = d.AverageValue;
        if (getValue >= 0) {
            return yScale(10)-37;
        } else {
            return yScale(23) - 6;
        }
    }) 
    .attr("marker-end", function (d) {
        var getValue = d.ComparedToPreviousMonth;
        if (getValue < 0) {
            return "url(#redArrow)";
        } else if (getValue > 0) {
            return "url(#greenArrow)";
        }
    });

整个代码都是小提琴   http://jsfiddle.net/911vgmp1/

2 个答案:

答案 0 :(得分:3)

查看生成的svg输出,您会注意到用于设置标记的线是几何点而不是线,即x1等于x2y1等于{{ 1}}:

y2

因为此线/点没有任何方向,所以无法确定标记的方向。因此,<line class="arrow" x1="33.5" x2="33.5" y1="296" y2="296" marker-end="url(#redArrow)"></line> 不会正确旋转标记。

orient="auto"的生成器函数中,您正在使用attr("marker-end"),可以正常使用哪个标记。但是,d.ComparedToPreviousMonth的生成器函数使用.attr("y2")来加密d.AverageValue,因此,行的方向和标记的方向。由于y2都是正数,因此行/标记的方向没有变化。

您可以通过将AverageValuey1生成器调整为:

来解决此问题
y2

对于纯粹主义者,.attr("y1", function (d) { return h; }) .attr("y2", function (d) { var getValue = d.ComparedToPreviousMonth; if (getValue < 0) { return h - .001; } else { return h + .001; } }) 生成器甚至可以缩短为:

y2

有了这些,您只需为标记设置不同的.attr("y2", function (d) { return d.ComparedToPreviousMonth < 0 ? h - .001 : h + .001; }) 值,以便在x轴上直观地定位它们:

refX

请参阅更新后的JSFiddle

答案 1 :(得分:0)

此处one way。我&#39;已经

  • 拆分绿色和红色箭头,使它们可以有单独的变换

  • 将标记下移到条形图的底部

  • 使标记溢出可见,以便在翻译数据后仍然显示

                            // add text and arrow
                            svg.selectAll("line.arrow")
                                .data(["red"])
                                .enter()
                              .append("defs").append("marker")
                                .attr("id", function (d) {
    
                                    return d + "Arrow";
    
                                })
                                .attr("viewBox", "0 -5 10 10")
                                .attr("refX", 8)
                                .attr("markerWidth", 12)
                                .attr("markerHeight", 20)
                                .attr("orient", "auto")
                                .attr("overflow", "visible")
                              .append("svg:path")
                                .attr("d", "M0,-5L10,0L0,5")
                                .attr("transform", "rotate(90, 5, 0)  translate(56, 0)")
                                .attr("class", function (d) {
                                    return "marker_" + d;
    
                                });
    
                            svg.selectAll("line.arrow")
                                .data(["green"])
                                .enter()
                              .append("defs").append("marker")
                                .attr("id", function (d) {
    
                                    return d + "Arrow";
    
                                })
                                .attr("viewBox", "0 -5 10 10")
                                .attr("refX", 8)
                                .attr("markerWidth", 12)
                                .attr("markerHeight", 20)
                                .attr("orient", "auto")
                                .attr("overflow", "visible")
                              .append("svg:path")
                                .attr("d", "M0,-5L10,0L0,5")
                                .attr("transform", "rotate(270, 5, 0) translate(-56, 0)")
                                .attr("class", function (d) {
                                    return "marker_" + d;
    
                                });