繁体   English   中英

如何使用d3绘制连续线而无需单击并拖动鼠标,而只是使用鼠标悬停事件?

[英]How can I draw a continuous line using d3 without needing to click&drag the mouse, but rather just use the mouseover event?

我试图使用d3绘制一条连续的线而不点击鼠标。 目前我有这个d3代码,当我点击并移动时可以工作,但是当我只是进入应绘制线条的区域时,它不起作用。 我在这里提供了CodePen链接: https ://codepen.io/pwill2/pen/NLdJoL

的index.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>

index.css

#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;
}

index.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);

为什么不在画布上监听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监听器(鼠标移除下面的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(); }) } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script> 

如果你想平滑曲线因为手抖动你可以使用d3.line和d3曲线绘制线条:

 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(); } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script> 

虽然你也可以过滤掉数组中的点以获得更平滑的东西(因为鼠标移动添加的点将根据鼠标速度非常接近地添加,使得平滑更难),或者使用不同的d3曲线:

 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(); } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM