最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Rotating the whole canvas in fabricjs - Stack Overflow

programmeradmin7浏览0评论

Is there a way to rotate the canvas in fabric.js?

I am not looking to rotate each element, that can be achieved easily, but rather a way to rotate the whole canvas similar to what is achieved with canvas.rotate() on a native canvas element:

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.rotate(20*Math.PI/180);

Accessing the canvas element from fabric.js with getContext() is possible, but if I do that and then rotate it, only one of the two canvases is being rotate and the selection/drawing is severely off and drawing/selecting/etc is not working anymore either.

I am somewhat at a loss here. If this is something that's currently not possible with fabric.js I will create a ticket on github, but somehow it feels like it should be possible ...

[edit]

After the input from Ian I've figured a few things out and am at a point where I can rotate the canvas and get some results. However, objects are very far off from the correct position. However, this might be because, while rotating, I am also zooming and absolute paning the canvas (with canvas.setZoom() and canvas.absolutePan()). I think I'll create a ticket on GitHub and see what the devs think. Somewhat stuck here ... Just for reference here's the code snippet:

setAngle: function(angle) {
    var self = this;

    var canvas = self.getFabricCanvas();
    var group = new fabric.Group();
    var origItems = canvas._objects;
    var size = self.getSize();

    group.set({width: size.width, height: size.height, left: size.width / 2, top: size.height / 2, originX: 'center', originY: 'center', centeredRotation: true})

    for (var i = 0; i < origItems.length; i++) {
        group.add(origItems[i]);
    }

    canvas.add(group);
    group.set({angle: (-1 * self.getOldAngle())});
    canvas.renderAll();
    group.set({angle: angle});
    canvas.renderAll();

    items = group._objects;
    group._restoreObjectsState();
    canvas.remove(group);

    for (var i = 0; i < items.length; i++) {
        canvas.add(items[i]);
        canvas.remove(origItems[i]);
    }

    canvas.renderAll();

    self.setOldAngle(angle);
},

As stated above, this function is called with two other functions:

setPosition: function(left, top) {
    var self = this;

    if (left < 0) {
        left = 0;
    }
    if (top < 0) {
        top = 0;
    }

    var point = new fabric.Point(left, top);
    self.getFabricCanvas().absolutePan(point);
},

setZoom: function(zoom) {
    var self = this;

    self.getFabricCanvas().setZoom(zoom);
},

The functions are called through the following code:

MyClass.setZoom(1);

MyClass.setPosition(left, top);
MyClass.setZoom(zoom);
MyClass.setAngle(angle);

As you can see, I try to set the angle last, but it doesn't make a difference (at least not visually) when I do that. The zoom set to 1 at the beginning is important as otherwise the panning won't work properly.

Maybe someone has an idea ...

Is there a way to rotate the canvas in fabric.js?

I am not looking to rotate each element, that can be achieved easily, but rather a way to rotate the whole canvas similar to what is achieved with canvas.rotate() on a native canvas element:

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.rotate(20*Math.PI/180);

Accessing the canvas element from fabric.js with getContext() is possible, but if I do that and then rotate it, only one of the two canvases is being rotate and the selection/drawing is severely off and drawing/selecting/etc is not working anymore either.

I am somewhat at a loss here. If this is something that's currently not possible with fabric.js I will create a ticket on github, but somehow it feels like it should be possible ...

[edit]

After the input from Ian I've figured a few things out and am at a point where I can rotate the canvas and get some results. However, objects are very far off from the correct position. However, this might be because, while rotating, I am also zooming and absolute paning the canvas (with canvas.setZoom() and canvas.absolutePan()). I think I'll create a ticket on GitHub and see what the devs think. Somewhat stuck here ... Just for reference here's the code snippet:

setAngle: function(angle) {
    var self = this;

    var canvas = self.getFabricCanvas();
    var group = new fabric.Group();
    var origItems = canvas._objects;
    var size = self.getSize();

    group.set({width: size.width, height: size.height, left: size.width / 2, top: size.height / 2, originX: 'center', originY: 'center', centeredRotation: true})

    for (var i = 0; i < origItems.length; i++) {
        group.add(origItems[i]);
    }

    canvas.add(group);
    group.set({angle: (-1 * self.getOldAngle())});
    canvas.renderAll();
    group.set({angle: angle});
    canvas.renderAll();

    items = group._objects;
    group._restoreObjectsState();
    canvas.remove(group);

    for (var i = 0; i < items.length; i++) {
        canvas.add(items[i]);
        canvas.remove(origItems[i]);
    }

    canvas.renderAll();

    self.setOldAngle(angle);
},

As stated above, this function is called with two other functions:

setPosition: function(left, top) {
    var self = this;

    if (left < 0) {
        left = 0;
    }
    if (top < 0) {
        top = 0;
    }

    var point = new fabric.Point(left, top);
    self.getFabricCanvas().absolutePan(point);
},

setZoom: function(zoom) {
    var self = this;

    self.getFabricCanvas().setZoom(zoom);
},

The functions are called through the following code:

MyClass.setZoom(1);

MyClass.setPosition(left, top);
MyClass.setZoom(zoom);
MyClass.setAngle(angle);

As you can see, I try to set the angle last, but it doesn't make a difference (at least not visually) when I do that. The zoom set to 1 at the beginning is important as otherwise the panning won't work properly.

Maybe someone has an idea ...

Share Improve this question edited Aug 1, 2015 at 7:23 Michael Diener asked Jul 30, 2015 at 19:51 Michael DienerMichael Diener 111 silver badge3 bronze badges 3
  • You might need to go through the elements and rotate them one at a time... – Snappawapa Commented Jul 30, 2015 at 20:01
  • Could you not just forget about rotating the canvas, and put everything in a group and rotate that ? If the canvas is coloured, use a rect instead inside the group as well ? – Ian Commented Jul 31, 2015 at 11:13
  • I like the idea of @Ian especially since it gave me a decently good idea as to how I can achieve it. I will report back as to how and if I could solve it! – Michael Diener Commented Aug 1, 2015 at 4:31
Add a ment  | 

1 Answer 1

Reset to default 6

Here is how I did this (code based on this js fiddle).

rotate (degrees) {

  let canvasCenter = new fabric.Point(canvas.getWidth() / 2, canvas.getHeight() / 2) // center of canvas
  let radians = fabric.util.degreesToRadians(degrees)

  canvas.getObjects().forEach((obj) => {
      let objectOrigin = new fabric.Point(obj.left, obj.top)
      let new_loc = fabric.util.rotatePoint(objectOrigin, canvasCenter, radians)
      obj.top = new_loc.y
      obj.left = new_loc.x
      obj.angle += degrees //rotate each object by the same angle
      obj.setCoords()
  });

  canvas.renderAll()


},

After doing this I also had to adjust the canvas background and size so objects wouldn't go off the canvas.

发布评论

评论列表(0)

  1. 暂无评论