【问题标题】:Drawing different colored "strokes" between center and different nodes in a D3.js tree在 D3.js 树的中心和不同节点之间绘制不同颜色的“笔触”
【发布时间】:2014-02-08 18:29:09
【问题描述】:

这是我的代码。我正在尝试在中心和不同节点之间连接/绘制路径。现在我想为不同的路径制作不同颜色的stroke。我已经创建了一个颜色数组,对于哪条路径,笔触颜色是什么。但是我不能让stroke 变成不同的颜色。

var lineFunction = d3.svg.line()
                     .x(function(d) { return d.x;})
                     .y(function(d) { return d.y;})
                     .interpolate("linear");
var lineGraph = vis.append("g")
                  .append("path")
                  .attr("d", lineFunction(CenterList))
                  .attr("stroke", function(d, i) { return ColorArr[i]; } )
                  .attr("stroke-width", 5)
                  .attr("fill", "none")
                  .attr("id", "viz");

ColorArr=black, black, red, red, black, black, black, red, black, red;

【问题讨论】:

  • line 函数创建的“线条”实际上只是一个单一的 SVG <path> 元素,它只能有一个单一的笔画颜色。如果您希望线条的每个部分具有不同的颜色,则需要将它们分别设为单独的 SVG <line> 元素。
  • 好的@AmeliaBR 非常感谢您澄清了这个概念,我也猜到了。你能概括一下我应该对代码所做的更改吗?
  • @Dibyendu Dutta,现在你明白写出非常清晰的问题是多么重要了:Amelia 和我以非常不同的方式解释它......

标签: javascript svg d3.js colors


【解决方案1】:

看看下面三个 jsFiddles。正如@AmeliaBR 所说,该解决方案的关键思想是。仔细研究这三个图中的链接实现(相当简单)。我提取了代码中最重要的部分。

Red only

.link_dashed {
    fill: none;
    stroke: #ff0000;
    stroke-width: 1.5px;
    stroke-dasharray: 0,20,20,30,10,10,10;
}

Black only

.link_dashed {
    fill: none;
    stroke: #000000;
    stroke-width: 1.5px;
    stroke-dasharray: 20,20,30,10,10,10,0;
}

Red and Black

.link_dashed {
    fill: none;
    stroke: #ff0000;
    stroke-width: 1.5px;
    stroke-dasharray: 0,20,20,30,10,10,10;
}
.link_dashed2 {
    fill: none;
    stroke: #000000;
    stroke-width: 1.5px;
    stroke-dasharray: 20,20,30,10,10,10,0;
}

【讨论】:

  • 嗯,这当然看起来很酷,但如果我正确理解了这个问题——每个点之间的线应该是基于数据的颜色——那么这将无法实现无需大量计算即可计算出路径中每条线段的长度。
  • 好吧,这留给读者作为练习。 :) @AmeliaBR
  • @AmeliaBR,我们是互补的......而且,这个问题相当笼统。
  • 张贴者说“我已经创建了一个颜色数组,哪个路径的描边颜色是什么”所以我假设它是一个常数。但即使不是这样,调整解决方案也不难。 :)
【解决方案2】:

要对不同的线段进行不同的样式设置,它们必须是单独的线元素,而不是一条路径的所有部分。

但是,将折线图绘制为一系列线元素会使代码复杂化。对于每个点,您不仅需要知道该点的数据,还需要知道上一个或下一个点(行的开始或结束)的数据。

我已经编写了一个(更复杂的)以这种方式制作折线图的示例for a previous SO question,因此我能够快速适应您。

这是小提琴:http://fiddle.jshell.net/4xZwb/3/

对于那个例子,我使用了“每个”调用来对所有计算进行分组:

var lines = svg.append("g").attr("class", "plot").selectAll("line");
        //define a d3 selection consisting of <line> elements
        //that are grouped within g.plot

    lines = lines.data(data);  
        //tell the selection to make room for every point in the data array

    lines.enter().append("line");
        //add one <line> element for every data point

    lines.each(function(d,i){
        //for each line in the selection, this function will be called
        //with d equal to the data point and i equal to the index
        //and "this" equal to the <line> element

        var value = d;
        //y-value for current point 
        //(we're just using the raw number from the array,
        //normally it would be something like d.y or d[1] )

        //find next point
        var next = i+1; //x-position (just using index #)
        var nextValue = data[i+1]; //y-position

        if (isNaN(nextValue)){
            // there is no next value,
            // so repeat this point as the end of line
            //(line will have zero length, but the marker will show up)
            next = i;
            nextValue = value;
        }

        d3.select(this) //select this particular <line> element
                        //so that we can use d3 methods

            //set coordinates:
            .attr( 
                {x1: xScale(i),
                 y1: yScale(value),
                 x2: xScale(next),
                 y2: yScale(nextValue)}
                )

            //Set styles for this individual line segment
            //e.g., based on whether value is increasing
            //or decreasing, we can set stroke colour red or black
            .style("stroke", ( (value > nextValue) ?
                              "red" :
                              "black" )
                  );
    });//end of "each" call

但是,您也可以单独设置它们,就像在这个版本中一样:

lines = lines.data(data);

lines.enter().append("line");

lines.attr("x1", function(d,i){return xScale(i);})
.attr("x2", function(d,i){
    return xScale( (i+1 == data.length)?i:i+1);
})
.attr("y1", function(d,i){return yScale(d);})
.attr("y2", function(d,i){
    return yScale( (i+1 == data.length)?
                  d:data[i+1]);
})
.style("stroke", function(d,i){
    return ( (d > data[i+1]) ?
             "red" : "black" )
    });

http://fiddle.jshell.net/4xZwb/4/

【讨论】:

  • 只是为了大惊小怪,最后把 y 轴调到正确的方向:fiddle.jshell.net/4xZwb/5 Doh。
  • 很好的答案,@AmeliaBR。想知道如果需要 B 样条插值(又名曲线),您将如何处理这个问题?由于绘制单独的线段,它变得更加复杂,对吧?或者有没有简单的方法来做到这一点?例如在这里查看我稍微修改过的小提琴,只有 5 个值:fiddle.jshell.net/4xZwb/36
  • @ryanm 如果您需要曲线,则需要使用&lt;path&gt; 而不是&lt;line&gt;。可能最容易使用 d3.svg.line 来计算平滑曲线(尽管您可以自己做)。您需要传递 i-1、i、i+1 和 i+2 数据点,以便它可以正确平滑事物,但是您需要将每个路径元素剪辑到 i 到 i+1 间隔,或者通过使用剪辑路径矩形,或者进入并编辑 d3.svg.line 返回的路径数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-16
  • 2012-11-11
  • 1970-01-01
  • 1970-01-01
  • 2013-10-21
相关资源
最近更新 更多