首页 > 解决方案 > Centering and scaling canvas object inside another canvas object by width/height in Fabric.js

问题描述

Goal: To center an object (horizontally and vertically) inside another object (rectangle or group) on canvas via Fabric.js or via Javascript which keeps the original object aspect ratio the same, but also not exceed the parent object width/height proportions?

The parent object (rectangle or group) won't be centered on the canvas element.

Here's the code I have so far: https://stackblitz.com/edit/angular-my8hky

My app.component.ts so far:

canvas: fabric.Canvas;

ngOnInit() {
  this.canvas = new fabric.Canvas('canvas');
  var rect = new fabric.Rect({
    left: 100,
    top: 50,
    width: 300,
    height: 200,
    fill: '#eee'
  });
  this.canvas.add(rect);

  fabric.Image.fromURL('https://angular.io/assets/images/logos/angular/logo-nav@2x.png', (img) => {
    let bounds = rect.getBoundingRect();
    let oImg = img.set({
      left: bounds.left,
      top: bounds.top,
      width: rect.width
    }).scale(1);
    this.canvas.add(oImg).renderAll();
  });
}

Not only is the new object not centered vertically, but also not centered horizontally if the rectangle object height is decreased (for example to 50px in height).

I realize I'm only declaring the inner image object width to be the same as the parent rectangle boundary width.

Current solution:

Parent rectangle width: 300 and height: 200:

300px x 200px - Undesired Fabric.js centering solution

Parent rectangle width: 300 and height: 50:

300px x 50px - Undesired Fabric.js centering solution

Desired solution:

Parent rectangle width: 300 and height: 200:

300px x 200px - Desired Fabric.js centering solution

Parent rectangle width: 300 and height: 50:

300px x 50px - Desired Fabric.js centering solution

Can anyone assist?

标签: javascriptangularcanvashtml5-canvasfabricjs

解决方案


想通了.. 这是 StackBlitz: https ://stackblitz.com/edit/angular-pg4fis

诀窍是首先将矩形添加到Fabric组中,如下所示:

var rect = new fabric.Rect({
  left: 100,
  top: 50,
  width: 450,
  height: 200,
  fill: '#e3e3e3',
});

var rectGroup = new fabric.Group([rect], {
  name: 'Rectangle',
});

this.canvas.add(rectGroup);

然后,我能够建立父(组)元素边界并使用可变比例因子通过Math功能设置图像:

fabric.Image.fromURL('https://angular.io/assets/images/logos/angular/logo-nav@2x.png', (img) => {
  let bounds = rectGroup.getBoundingRect();

  const scaleFactor = Math.min(
    Math.min(1, bounds.width / img.width),
    Math.min(1, bounds.height / img.height)
  );
  img.scale(scaleFactor);

  img.set({
    top: bounds.top + Math.max(bounds.height - img.height * scaleFactor, 0)/2,
    left: bounds.left + Math.max(bounds.width - img.width * scaleFactor, 0)/2,
  });

  rectGroup.addWithUpdate(img);
  this.canvas.renderAll();
});

推荐阅读