【问题标题】:Draw line with arrow cap用箭头帽画线
【发布时间】:2018-04-17 16:24:31
【问题描述】:

我正在尝试在线的末端画一条带箭头的线。但我无法完成它。谁能帮帮我。

我尝试用线条添加三角形,但不幸的是它在动态绘制时不起作用。这是我尝试过的。

    var myPath;

function onMouseDown(event) {
    myPath = new Path();
    myPath.strokeColor = 'black';
}

function onMouseDrag(event) {
    myPath.add(event.point);
}

function onMouseUp(event) {
    var myCircle = new Path.RegularPolygon(event.point, 3, 10);
    myCircle.strokeColor = 'black';
    myCircle.fillColor = 'white';
}

【问题讨论】:

    标签: javascript paperjs


    【解决方案1】:

    你用这段代码用箭头画线,

    paper.Shape.ArrowLine = function (sx, sy, ex, ey, isDouble) {
    function calcArrow(px0, py0, px, py) {
        var points = [];
        var l = Math.sqrt(Math.pow((px - px0), 2) + Math.pow((py - py0), 2));
        points[0] = (px - ((px - px0) * Math.cos(0.5) - (py - py0) * Math.sin(0.5)) * 10 / l);
        points[1] = (py - ((py - py0) * Math.cos(0.5) + (px - px0) * Math.sin(0.5)) * 10 / l);
        points[2] = (px - ((px - px0) * Math.cos(0.5) + (py - py0) * Math.sin(0.5)) * 10 / l);
        points[3] = (py - ((py - py0) * Math.cos(0.5) - (px - px0) * Math.sin(0.5)) * 10 / l);
        return points;
    }
    
    var endPoints = calcArrow(sx, sy, ex, ey);
    var startPoints = calcArrow(ex, ey, sx, sy);
    
    var e0 = endPoints[0],
        e1 = endPoints[1],
        e2 = endPoints[2],
        e3 = endPoints[3],
        s0 = startPoints[0],
        s1 = startPoints[1],
        s2 = startPoints[2],
        s3 = startPoints[3];
    var line = new paper.Path({
        segments: [
            new paper.Point(sx, sy),
            new paper.Point(ex, ey)
        ],
        strokeWidth: 1
    });
    var arrow1 = new paper.Path({
        segments: [
            new paper.Point(e0, e1),
            new paper.Point(ex, ey),
            new paper.Point(e2, e3)
        ]
    });
    
    var compoundPath = new paper.CompoundPath([line, arrow1]);
    if (isDouble === true) {
        var arrow2 = new paper.Path({
            segments: [
                new paper.Point(s0, s1),
                new paper.Point(sx, sy),
                new paper.Point(s2, s3)
            ]
        });
    
        compoundPath.addChild(arrow2);
    }
    
    return compoundPath;};
    

    使用

    tool.onMouseDrag = function (event) { this.item = new paper.Shape.ArrowLine(event.downPoint.x, event.downPoint.y, event.point.x, event.point.y);
                this.item.removeOnDrag();}
    

    【讨论】:

    • 不错的一个.. 即使箭头的点超过了线条的边界如果 strokewidth > 1
    【解决方案2】:

    paperjs refrence 中有一个示例代码,它在矢量末尾绘制一个箭头。
    看看:http://paperjs.org/tutorials/geometry/vector-geometry/(一直向下滚动到页面末尾)

    【讨论】:

      【解决方案3】:

      一种简单的方法是创建一个由矢量本身(线)和箭头组成的组。 lineStartlineEnd 是箭头线的起点和终点。

      // parameters
      headLength = 10;
      headAngle = 150;
      
      lineStart = new Point(200, 200);
      lineEnd = new Point (250, 250);
      
      tailLine = new Path.Line(lineStart, lineEnd);
      tailVector = lineEnd - lineStart;
      headLine = tailVector.normalize(headLength);
      
      arrow = new Group([
          new Path([lineStart, lineEnd]),
          new Path([
              lineEnd + headLine.rotate(headAngle),
              lineEnd,
              lineEnd + headLine.rotate(-headAngle)
          ])
      ]);
      
      arrow.strokeColor = 'black';
      

      而且,如前所述,如果您想每次都重新创建它,那么您可以将之前的代码变成一个函数,例如:

      // parameters
      var headLength = 10;
      var headAngle = 150;
      var arrowColor = 'black';
      
      // the arrow
      var arrow = null;
      
      function drawArrow(start, end) {
      
          var tailLine = new Path.Line(start, end);
          var tailVector = end - start;
          var headLine = tailVector.normalize(headLength);
      
          arrow = new Group([
              new Path([start, end]),
              new Path([
                  end + headLine.rotate(headAngle),
                  end,
                  end + headLine.rotate(-headAngle)
              ])
          ]);
      
          arrow.strokeColor = arrowColor;
      }
      
      tool.onMouseDrag = function(e) {
          if (arrow) {
              arrow.remove();
          }
          drawArrow(e.downPoint, e.point);
      }
      

      这里是之前代码sketch.paperjs.org的草图

      【讨论】:

      • 我尝试了您提供的代码,但由于某种原因它在这里失败了 - jsfiddle.net/1j6nLa7c/5
      • 你需要做end.add(headLine.rotate(headAngle),因为它没有被纸解析以使操作员工作(就像你对end.subtract(start)所做的那样。
      • 如果对您有帮助,我们将不胜感激。
      • 另外,paperjs 中有没有办法让我点击一个项目;例如在这种情况下该项目是矩形,单击矩形并将其删除。如果我有一个点,那么我可以使用代码将其删除,但我想选择并删除它(更用户友好)。
      【解决方案4】:

      这是一个例子,我扩展paper.Group

      在我的示例中,我避免重绘每个 mousedrag 上的箭头。我在mousedown 上创建一次,然后将线和箭头部分转换到每个mousedrag 上的适当位置/旋转。

      注意:我相当肯定以下代码可以改进很多。

      通过鼠标事件绘图

      'use strict'
      
      /* Arrow Class extends Group */
      
      const Arrow = paper.Group.extend({
        initialize: function (args) {
          paper.Group.call(this, args)
          this._class = 'Arrow'
          this._serializeFields = Object.assign(this._serializeFields, {
            from: null,
            to: null,
            headSize: null
          })
      
          this.from = args.from
          this.to = args.to || args.from
          this.headSize = args.headSize
      
          // @NOTE
          // `paper.project.importJSON()` passes the deserialized children
          // (the arrow parts) to the `Group` superclass so there's no need to
          // create them again.
          if (this.children.length)
            return
      
          this.addChildren([
            new paper.Path({
              ...args,
              segments: [
                this.from,
                this.from
              ]
            }),
            new paper.Path({
              ...args,
              segments: [
                this.from,
                this.from
              ]
            }),
            new paper.Path({
              ...args,
              segments: [
                this.from,
                this.from
              ]
            })
          ])
      
          this.update(this.to)
        },
      
        update: function (point) {
          const angle = this.from.subtract(point).angle - 90
      
          this.children[0].lastSegment.point = point
      
          this.children[1].firstSegment.point = point
          this.children[1].lastSegment.point = point.add(
            this.headSize,
            this.headSize
          )
      
          this.children[2].firstSegment.point = point
          this.children[2].lastSegment.point = point.add(
            -this.headSize,
            this.headSize
          )
      
          this.children[1].rotate(angle, point)
          this.children[2].rotate(angle, point)
      
          return this
        }
      })
      
      paper.Base.exports.Arrow = Arrow
      
      /* Usage */
      
      paper.setup(document.querySelector('canvas'))
      
      const tool = new paper.Tool()
      
      let arrow
      
      tool.onMouseDown = e => {
        arrow = new Arrow({
          from: e.point,
          headSize: 10,
          strokeWidth: 1,
          strokeColor: '#555',
          strokeCap: 'round'
        })
      }
      
      tool.onMouseDrag = e => {
        arrow.update(e.point)
      }
      canvas {
        display: block;
        width: 100%;
        height: 100%;
        margin: 0;
        background: #fafafa;
      }
      <script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.11.5/paper-core.min.js"></script>
      <canvas resize="true"></canvas>

      ...或者只是画到一个静态位置

      如果您只想绘制箭头(不使用鼠标事件),只需执行以下操作:

      const arrow = new Arrow({
        from: new paper.Point(100, 100),
        to: new paper.Point(200, 200),
        headSize: 10,
        strokeWidth: 1,
        strokeColor: '#555',
        strokeCap: 'round'
      })
      

      【讨论】:

        猜你喜欢
        • 2014-12-13
        • 1970-01-01
        • 1970-01-01
        • 2016-01-22
        • 2015-09-28
        • 2016-08-03
        • 1970-01-01
        • 2011-05-05
        • 2020-05-21
        相关资源
        最近更新 更多