代码之家  ›  专栏  ›  技术社区  ›  ParkerWilliams

如何使用d3绘制一条连续线而不需要单击和拖动鼠标,而只使用mouseover事件?

  •  1
  • ParkerWilliams  · 技术社区  · 6 年前

    https://codepen.io/pwill2/pen/NLdJoL

    索引.html

    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <title>Freehand drawing</title>
        <link rel="stylesheet" href="index.css">
        <script src="http://d3js.org/d3.v3.min.js"></script>
      </head>
      <body>
        <svg id="canvas" width="500px" height="250px"></svg>
        <script src="index.js"></script>
      </body>
    </html>
    

    #canvas {
      background: oldlace;
    }
    .swatch {
      pointer-events: all;
    }
    .swatch.active {
      stroke-width: 2px;
      stroke: black;
    }
    .swatch {
      cursor: pointer;
    }
    .btn {
      pointer-events: all;
    
      font-family: FontAwesome;
      fill: #333;
      font-size: 32px;
      text-anchor: middle;
    
      -webkit-touch-callout: none;
      -webkit-user-select: none;
      -khtml-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
    }
    .btn:hover {
      fill: black;
      cursor: pointer;
    }
    
    .line {
      fill: none;
      stroke-width: 2px;
      stroke-linejoin: round;
      stroke-linecap: round;
    }
    

    索引.js

    (function() {
      var SWATCH_D, active_color, active_line, canvas, drag, drawing_data, lines_layer, palette, redraw, render_line, swatches, trash_btn, ui;
    
      SWATCH_D = 22;
    
      render_line = d3.svg.line().x(function(d) {
        return d[0];
      }).y(function(d) {
        return d[1];
      }).interpolate('basis');
    
      drawing_data = {
        lines: [
          {
            color: "#000000",
            points: []}
        ]
      };
    
      active_line = null;
    
      active_color = "#000000";
    
      canvas = d3.select('#canvas');
    
      lines_layer = canvas.append('g');
    
      drag = d3.behavior.drag();
    
      drag.on('dragstart', function() {
        active_line = {
          points: [],
          color: active_color
        };
        drawing_data.lines.push(active_line);
        return redraw(active_line);
      });
    
      drag.on('drag', function() {
        active_line.points.push(d3.mouse(this));
        return redraw(active_line);
      });
    
      drag.on('dragend', function() {
        if (active_line.points.length === 0) {
          drawing_data.lines.pop();
        }
        active_line = null;
        return console.log(drawing_data);
      });
    
      canvas.call(drag);
    
      redraw = function(specific_line) {
        var lines;
        lines = lines_layer.selectAll('.line').data(drawing_data.lines);
        lines.enter().append('path').attr({
          "class": 'line',
          stroke: function(d) {
            return d.color;
          }
        }).each(function(d) {
          return d.elem = d3.select(this);
        });
        if (specific_line != null) {
          specific_line.elem.attr({
            d: function(d) {
              return render_line(d.points);
            }
          });
        } else {
          lines.attr({
            d: function(d) {
              return render_line(d.points);
            }
          });
        }
        return lines.exit().remove();
      };
    
      redraw();
    
    }).call(this);
    
    1 回复  |  直到 6 年前
        1
  •  3
  •   Andrew Reid    6 年前

    与其用拖拽,为什么不听听 mousemove 事件,并按此方式指向路径绘制函数。

    var points = [];
    var canvas = d3.select("body")
       .append("canvas")
       .attr("height",500)
       .attr("width", 600)
       .on("mousemove", addPoint);
          
    var context = canvas.node().getContext("2d");
          
    function addPoint() {
       points.push(d3.mouse(this));
       draw();
    }
    
    function draw() {
      context.clearRect(0,0,600,600);
      context.beginPath();
      context.moveTo(...points[0]);
      points.forEach(function(d) {
        context.lineTo(...d);
      })
      context.lineWidth = 1;
      context.stroke();
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>

    如果您需要在画布上单击鼠标的每个条目后进行绘制,您也可以在单击时指定mousemove侦听器(mouse out删除下面的mousemove侦听器,这样您就可以绘制多行):

    var points = [];
    
    var canvas = d3.select("body")
       .append("canvas")
       .attr("height",500)
       .attr("width", 600)
       .on("click", function() {
         points.push([])
         d3.select(this).on("mousemove", addPoint);
       })
       .on("mouseout", function() {
         d3.select(this).on("mousemove",null);
       })
       
          
    var context = canvas.node().getContext("2d");
          
    function addPoint() {
       points[points.length-1].push(d3.mouse(this));
       draw();
    }
    
    function draw() {
      context.clearRect(0,0,600,600);
      points.forEach(function(p) {
        context.beginPath();
        context.moveTo(...p[0]);
        p.forEach(function(d) {
          context.lineTo(...d);
        })
        context.lineWidth = 1;
        context.stroke();
      })
    }
    <脚本src=“https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js“></script>

    var points = [];
    var canvas = d3.select("body")
       .append("canvas")
       .attr("height",500)
       .attr("width", 600)
       .on("mousemove", addPoint);
          
    var context = canvas.node().getContext("2d");
    
    var line = d3.line().context(context)
        .x(function(d) { return d[0]; })
        .y(function(d) { return d[1]; })
        .curve(d3.curveBasis);
          
    function addPoint() {
       points.push(d3.mouse(this));
       draw();
    }
    
    function draw() {
      context.clearRect(0,0,600,600)
      context.beginPath();
      line(points);  
      context.lineWidth = 1;
      context.stroke();
    }
    <脚本src=“https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js“></script>

    var points = [];
    var canvas = d3.select("body")
       .append("canvas")
       .attr("height",500)
       .attr("width", 600)
       .on("mousemove", addPoint);
          
    var context = canvas.node().getContext("2d");
    
    var line = d3.line().context(context)
        .x(function(d) { return d[0]; })
        .y(function(d) { return d[1]; })
        .curve(d3.curveBasis);
          
    function addPoint() {
       points.push(d3.mouse(this));
       draw();
    }
    
    function draw() {
      context.clearRect(0,0,600,600)
      context.beginPath();
      line(points.filter(function(p,i) {
        if(i%8 == 0 || i == points.length-1) return p;
      }));  
      context.lineWidth = 1;
      context.stroke();
    }
    <脚本src=“https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js“></script>