2017-02-16 174 views
0

我解决了我最初的目标,让最后一点由虚线连接,而曲线的其余部分与实线连接(请参阅图像)。如何在d3.js v4的关节点平滑两条曲线?

但是,通过这样做,我失去了曲线的平滑。 你会如何解决这个问题? enter image description here

此外,如何让样式代替类似于HTML5的类? (该圈有一个红色笔划作为样式属性,但赢得了该类的蓝色)。

// curve 
    self.svg.append("path") 
    .datum(function() {return data.slice(0,data.length-1);}) 
     .attr("stroke", colors(i)) 
     .attr("class", "line ") 
     .attr("d", d3.line() 
      .curve(d3.curveCatmullRom) 
      .x(function(d) { return self.xSales(d.period) + self.xSales.bandwidth()/2;}) 
      .y(function(d) { return self.ySales(v(d)); }) 
     ); 

    self.svg.append("path") 
    .datum(function() {return data.slice(data.length-2, data.length);}) 
     .attr("stroke", colors(i)) 
     .attr("class", "line currentPeriod") 
     .attr("d", d3.line() 
      .curve(d3.curveCatmullRom) 
      .x(function(d) { return self.xSales(d.period) + self.xSales.bandwidth()/2;}) 
      .y(function(d) { return self.ySales(v(d)); }) 
     ); 
+1

要回答你的第二个问题,使用'.style(“行程,......',而不是'.attr'然后它会CSS和行为就像CSS一样,对于第一个问题,您需要生成一个单独的路径并使用'dash-offset'和一个渐变着色。 – Mark

回答

1

至于我的评论:

关于第一个问题,你需要生成一个单一的路径和使用破折号,偏移和梯度着色。

我提供了一个很好的答案here关于如何冲破一段单一路径但它不提供颜色。所以我下面更新为:

<!DOCTYPE html> 
 
<meta charset="utf-8"> 
 
<style> 
 
    body { 
 
    font: 10px sans-serif; 
 
    } 
 
    
 
    .axis path, 
 
    .axis line { 
 
    fill: none; 
 
    stroke: #000; 
 
    shape-rendering: crispEdges; 
 
    } 
 
    
 
    .x.axis path { 
 
    display: none; 
 
    } 
 
    
 
    .line { 
 
    fill: none; 
 
    stroke-width: 1.5px; 
 
    } 
 
</style> 
 

 
<body> 
 
    <script src="//d3js.org/d3.v3.min.js"></script> 
 
    <script> 
 
    var margin = { 
 
     top: 20, 
 
     right: 20, 
 
     bottom: 30, 
 
     left: 50 
 
     }, 
 
     width = 960 - margin.left - margin.right, 
 
     height = 500 - margin.top - margin.bottom; 
 

 
    var data = d3.range(11).map(function(d, i) { 
 
     return { 
 
     x: i, 
 
     y: Math.random() * 100 
 
     }; 
 
    }); 
 

 
    var x = d3.scale.linear() 
 
     .range([0, width]) 
 
     .domain([0, 10]); 
 

 
    var y = d3.scale.linear() 
 
     .range([height, 0]) 
 
     .domain([0, 100]); 
 

 
    var xAxis = d3.svg.axis() 
 
     .scale(x) 
 
     .orient("bottom"); 
 

 
    var yAxis = d3.svg.axis() 
 
     .scale(y) 
 
     .orient("left"); 
 

 
    var line = d3.svg.line() 
 
     .x(function(d) { 
 
     return x(d.x); 
 
     }) 
 
     .y(function(d) { 
 
     return y(d.y); 
 
     }) 
 
     .interpolate("basis"); 
 

 
    var svg = d3.select("body").append("svg") 
 
     .attr("width", width + margin.left + margin.right) 
 
     .attr("height", height + margin.top + margin.bottom) 
 
     .append("g") 
 
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 
     
 
    var lG = svg.append("defs") 
 
     .append("linearGradient") 
 
     .attr("id", "lineColor") 
 
     .attr("x1", "0%") 
 
     .attr("x2", "100%") 
 
     .attr("y1", "0%") 
 
     .attr("y2", "0%"); 
 
    
 
    lG.append("stop") 
 
     .attr("offset", "0") 
 
     .attr("stop-color", "steelblue"); 
 
     
 
    svg.append("g") 
 
     .attr("class", "x axis") 
 
     .attr("transform", "translate(0," + height + ")") 
 
     .call(xAxis); 
 

 
    svg.append("g") 
 
     .attr("class", "y axis") 
 
     .call(yAxis) 
 

 
    var p = svg.append("path") 
 
     .datum(data) 
 
     .attr("class", "line") 
 
     .attr("stroke", "url(#lineColor)") 
 
     .attr("d", line); 
 

 
    // draw dashed from 2.7 to 7 in the X domain 
 
    var dashBetweenX = [2.5, 7] 
 
    path = p.node(), 
 
     totalLen = path.getTotalLength(); 
 

 
    // find the corresponding line lengths 
 
    var dashBetweenL = dashBetweenX.map(function(d, i) { 
 

 
     var beginning = 0, 
 
     end = totalLen, 
 
     target = null, 
 
     d = x(d); 
 

 
     // find the line lengths the correspond to our X values 
 
     // stolen from @duopixel from http://bl.ocks.org/duopixel/3824661 
 
     while (true) { 
 
     target = Math.floor((beginning + end)/2); 
 
     pos = path.getPointAtLength(target); 
 
     if ((target === end || target === beginning) && pos.x !== d) { 
 
      break; 
 
     } 
 
     if (pos.x > d) end = target; 
 
     else if (pos.x < d) beginning = target; 
 
     else break; //position found 
 
     } 
 

 
     return target; 
 
    }) 
 

 
    var sd = dashBetweenL[0], 
 
     dp = dashBetweenL[0], 
 
     count = 0; 
 
    while (dp < dashBetweenL[1]) { 
 
     count++; 
 
     dp += 4; 
 
     sd += ", 4"; 
 
    } 
 

 
    if (count % 2 == 0) { 
 
     sd += ", 4, " + (totalLen - dashBetweenL[1]); 
 
    } else { 
 
     sd += ", " + (totalLen - dashBetweenL[1]); 
 
    } 
 
    p.attr("stroke-dasharray", sd); 
 
    
 
    lG.append("stop") 
 
     .attr("offset", dashBetweenX[0]/x.domain()[1]) 
 
     .attr("stop-color", "steelblue"); 
 
    
 
    lG.append("stop") 
 
     .attr("offset", dashBetweenX[0]/x.domain()[1] + 0.001) 
 
     .attr("stop-color", "red"); 
 
     
 
    lG.append("stop") 
 
     .attr("offset", dashBetweenX[1]/x.domain()[1]) 
 
     .attr("stop-color", "red"); 
 
     
 
    lG.append("stop") 
 
     .attr("offset", dashBetweenX[1]/x.domain()[1] + 0.001) 
 
     .attr("stop-color", "steelblue"); 
 
     
 
    lG.append("stop") 
 
     .attr("offset", '1') 
 
     .attr("stop-color", "steelblue"); 
 
    
 
    </script> 
 
</body> 
 

 
</html>