File size: 2,570 Bytes
b456468
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import { fabric } from 'fabric';
import Component from '@/interface/component';
import { componentNames } from '@/consts';

/**
 * Image Rotation component
 * @class Rotation
 * @extends {Component}
 * @param {Graphics} graphics - Graphics instance
 * @ignore
 */
class Rotation extends Component {
  constructor(graphics) {
    super(componentNames.ROTATION, graphics);
  }

  /**
   * Get current angle
   * @returns {Number}
   */
  getCurrentAngle() {
    return this.getCanvasImage().angle;
  }

  /**
   * Set angle of the image
   *
   *  Do not call "this.setImageProperties" for setting angle directly.
   *  Before setting angle, The originX,Y of image should be set to center.
   *      See "http://fabricjs.com/docs/fabric.Object.html#setAngle"
   *
   * @param {number} angle - Angle value
   * @returns {Promise}
   */
  setAngle(angle) {
    const oldAngle = this.getCurrentAngle() % 360; // The angle is lower than 2*PI(===360 degrees)

    angle %= 360;

    const canvasImage = this.getCanvasImage();
    const oldImageCenter = canvasImage.getCenterPoint();
    canvasImage.set({ angle }).setCoords();
    this.adjustCanvasDimension();
    const newImageCenter = canvasImage.getCenterPoint();
    this._rotateForEachObject(oldImageCenter, newImageCenter, angle - oldAngle);

    return Promise.resolve(angle);
  }

  /**
   * Rotate for each object
   * @param {fabric.Point} oldImageCenter - Image center point before rotation
   * @param {fabric.Point} newImageCenter - Image center point after rotation
   * @param {number} angleDiff - Image angle difference after rotation
   * @private
   */
  _rotateForEachObject(oldImageCenter, newImageCenter, angleDiff) {
    const canvas = this.getCanvas();
    const centerDiff = {
      x: oldImageCenter.x - newImageCenter.x,
      y: oldImageCenter.y - newImageCenter.y,
    };

    canvas.forEachObject((obj) => {
      const objCenter = obj.getCenterPoint();
      const radian = fabric.util.degreesToRadians(angleDiff);
      const newObjCenter = fabric.util.rotatePoint(objCenter, oldImageCenter, radian);

      obj.set({
        left: newObjCenter.x - centerDiff.x,
        top: newObjCenter.y - centerDiff.y,
        angle: (obj.angle + angleDiff) % 360,
      });
      obj.setCoords();
    });
    canvas.renderAll();
  }

  /**
   * Rotate the image
   * @param {number} additionalAngle - Additional angle
   * @returns {Promise}
   */
  rotate(additionalAngle) {
    const current = this.getCurrentAngle();

    return this.setAngle(current + additionalAngle);
  }
}

export default Rotation;