在fabric.js中绘制两个箭头 [英] Draw two head arrows in fabric.js

查看:42
本文介绍了在fabric.js中绘制两个箭头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是fabric.js的新手,对浏览器canvas api的了解也不多,因此,我感谢别人会提供的所有帮助.

I am new to fabric.js and don't have much experience with the browser canvas api so I appreciate all help someone will provide.

要实现的目标是在3种不同的模式下使用鼠标箭头进行绘制:

The goal to achieve is to draw with mouse arrows in 3 different modes:

  1. 有2个头
  2. 一个头
  3. 完全没有头(只是一条直线)

有一个很好的例子-但只有一个提示".

There is a very good example - but with just one "tip".

另一个更高级的主题可能是:选择一个已经创建的箭头进行更改(例如,单击按钮并将模式从一个带箭头的箭头更改为两个).

Also a more advanced topic might be: after selecting an already created arrow, to change it (e.g. clicking on a button and change the mode from one headed arrow to two).

  _render: function(ctx) {
    this.callSuper('_render', ctx);

    // do not render if width/height are zeros or object is not visible
    if (this.width === 0 || this.height === 0 || !this.visible) return;

    ctx.save();

    var xDiff = this.x2 - this.x1;
    var yDiff = this.y2 - this.y1;
    var angle = Math.atan2(yDiff, xDiff);
    ctx.translate(xDiff / 2, yDiff / 2);
    ctx.rotate(angle);
    ctx.beginPath();
    //move 10px in front of line to start the arrow so it does not have the square line end showing in front (0,0)
    ctx.moveTo(10, 0);
    ctx.lineTo(-20, 15);
    ctx.lineTo(-20, -15);
    ctx.closePath();
    ctx.fillStyle = this.stroke;
    ctx.fill();

    ctx.restore();
  }

可能会更改此特定部分,而不是添加另一个箭头:< --->

This particular part might be changed in place of adding another head of the arrow: <--->

链接到正在工作的JFiddle: Fiddle

Link to working JFiddle with one head: Fiddle

预先感谢您的帮助.祝一切顺利!

Thank you in advance for your help. All the best!

推荐答案

将上下文翻译到直线的两个端点,然后旋转以绘制箭头.

Translate the context to both the end points of line, then rotate to draw the arrow heads.

演示

DEMO

// Extended fabric line class
fabric.LineArrow = fabric.util.createClass(fabric.Line, {

  type: 'lineArrow',

  initialize: function(element, options) {
    options || (options = {});
    this.callSuper('initialize', element, options);
  },

  toObject: function() {
    return fabric.util.object.extend(this.callSuper('toObject'));
  },

  _render: function(ctx) {
    this.ctx = ctx;
    this.callSuper('_render', ctx);
    let p = this.calcLinePoints();
    let xDiff = this.x2 - this.x1;
    let yDiff = this.y2 - this.y1;
    let angle = Math.atan2(yDiff, xDiff);
    this.drawArrow(angle, p.x2, p.y2);
    ctx.save();
    xDiff = -this.x2 + this.x1;
    yDiff = -this.y2 + this.y1;
    angle = Math.atan2(yDiff, xDiff);
    this.drawArrow(angle, p.x1, p.y1);
  },

  drawArrow: function(angle, xPos, yPos) {
    this.ctx.save();
    this.ctx.translate(xPos, yPos);
    this.ctx.rotate(angle);
    this.ctx.beginPath();
    // Move 5px in front of line to start the arrow so it does not have the square line end showing in front (0,0)
    this.ctx.moveTo(10, 0);
    this.ctx.lineTo(-15, 15);
    this.ctx.lineTo(-15, -15);
    this.ctx.closePath();
    this.ctx.fillStyle = this.stroke;
    this.ctx.fill();
    this.ctx.restore();
  }
});



fabric.LineArrow.fromObject = function(object, callback) {
  callback && callback(new fabric.LineArrow([object.x1, object.y1, object.x2, object.y2], object));
};

fabric.LineArrow.async = true;


var Arrow = (function() {
  function Arrow(canvas) {
    this.canvas = canvas;
    this.className = 'Arrow';
    this.isDrawing = false;
    this.bindEvents();
  }

  Arrow.prototype.bindEvents = function() {
    var inst = this;
    inst.canvas.on('mouse:down', function(o) {
      inst.onMouseDown(o);
    });
    inst.canvas.on('mouse:move', function(o) {
      inst.onMouseMove(o);
    });
    inst.canvas.on('mouse:up', function(o) {
      inst.onMouseUp(o);
    });
    inst.canvas.on('object:moving', function(o) {
      inst.disable();
    })
  }

  Arrow.prototype.onMouseUp = function(o) {
    var inst = this;
    this.line.set({
      dirty: true,
      objectCaching: true
    });
    inst.canvas.renderAll();
    inst.disable();
  };

  Arrow.prototype.onMouseMove = function(o) {
    var inst = this;
    if (!inst.isEnable()) {
      return;
    }

    var pointer = inst.canvas.getPointer(o.e);
    var activeObj = inst.canvas.getActiveObject();
    activeObj.set({
      x2: pointer.x,
      y2: pointer.y
    });
    activeObj.setCoords();
    inst.canvas.renderAll();
  };

  Arrow.prototype.onMouseDown = function(o) {
    var inst = this;
    inst.enable();
    var pointer = inst.canvas.getPointer(o.e);

    var points = [pointer.x, pointer.y, pointer.x, pointer.y];
    this.line = new fabric.LineArrow(points, {
      strokeWidth: 5,
      fill: 'red',
      stroke: 'red',
      originX: 'center',
      originY: 'center',
      hasBorders: false,
      hasControls: false,
      objectCaching: false,
      perPixelTargetFind: true
    });

    inst.canvas.add(this.line).setActiveObject(this.line);
  };

  Arrow.prototype.isEnable = function() {
    return this.isDrawing;
  }

  Arrow.prototype.enable = function() {
    this.isDrawing = true;
  }

  Arrow.prototype.disable = function() {
    this.isDrawing = false;
  }

  return Arrow;
}());

var canvas = new fabric.Canvas('canvas', {
  selection: false
});
var arrow = new Arrow(canvas);

<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.17/fabric.min.js"></script>
 Please draw arrow here

<div id="canvasContainer">
  <canvas id="canvas" width="400" height="400" style="border: solid 1px"></canvas>
</div>

这篇关于在fabric.js中绘制两个箭头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆