最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Make a single line be solid and a section of it dashed - Stack Overflow

programmeradmin0浏览0评论

I would like to know if there is an alternative to applying the "stroke-dasharray" to a path. What I'm trying to do is add a dashed line to a certain range in the path. The thing is that the line is not straight. And I want to avoid creating two lines using the same data within different range. Does anyone have an idea?

I would like to know if there is an alternative to applying the "stroke-dasharray" to a path. What I'm trying to do is add a dashed line to a certain range in the path. The thing is that the line is not straight. And I want to avoid creating two lines using the same data within different range. Does anyone have an idea?

Share Improve this question edited Jan 25, 2016 at 19:02 xkcd149 8411 gold badge11 silver badges17 bronze badges asked Jan 25, 2016 at 18:50 skip87skip87 5291 gold badge7 silver badges27 bronze badges 5
  • 2 You can do this with stroke-dasharray -- one long stroke for the first uninterrupted part, then strokes and dashes, then another long stroke for the second uninterrupted part. – Lars Kotthoff Commented Jan 25, 2016 at 19:08
  • With stroke array i have to give the number of pixel for solid than the number of pixel for the dashed. Yet my line is not straight so it won't work ? – skip87 Commented Jan 25, 2016 at 19:11
  • 3 The strokes are relative to the length of the line, so it doesn't matter whether it's curved or straight. – Lars Kotthoff Commented Jan 25, 2016 at 19:14
  • ok i"ll let you know if it's working thanks – skip87 Commented Jan 25, 2016 at 19:16
  • Similar question: stackoverflow./questions/24725587/… – Mark Commented Jan 25, 2016 at 20:27
Add a ment  | 

2 Answers 2

Reset to default 8

I linked this question which provides a pretty good overview of how stroke-dasharray works, but the interesting part of this question bees, how can I dash over a specific section of the line? With that in mind, say we have a line from 0 to 10 and we want to dash it from 2.5 to 7:

<!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: steelblue;
    stroke-width: 1.5px;
  }
</style>

<body>
  <script src="//d3js/d3.v4.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.scaleLinear()
      .range([0, width])
      .domain([0, 10]);

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

    var xAxis = d3.axisBottom()
      .scale(x);

    var yAxis = d3.axisLeft()
      .scale(y);

    var line = d3.line()
      .x(function(d) {
        return x(d.x);
      })
      .y(function(d) {
        return y(d.y);
      })
      .curve(d3.curveBasis);

    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 + ")");

    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("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/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;
    })
    
    // draw the dashes
    var sd =  dashBetweenL[0],
        dp = dashBetweenL[0],
        count = 0;
    while (dp < dashBetweenL[1]){
      dp += 2;
      sd += ", 2";
      count++;
    }
    // per answer below needs odd number of dash array
    if (count % 2 == 0)
      sd += ", 2";   
    sd += ", " + (totalLen - dashBetweenL[1]);
    p.attr("stroke-dasharray", sd);    
  </script>
</body>

</html>

@Mark has a partially working solution for me. I had to perform one additional check after adding the dashes. If the number of dashes added was even, the line after the dash would not render.

Modifying the section as follows fixed it for me:

let 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);

Truthfully, I'm having a hard time seeing why it was necessary but appears to be working perfectly.

发布评论

评论列表(0)

  1. 暂无评论