好的,如果我有以下旋转形状然后被选中,您将看到它们的边界框:
我正在尝试编写一些代码来使对象相互对齐。所以我想得到每个对象的“包含框”。
我知道 getBoundingRect
但是,对于上述形状,这给了我以下信息:
因此,这些盒子对我来说用处不大。是否有一种标准方法来获取我称之为所有形状的“包含框”?例如,我希望能够将以下箱子退还给我:
因此,对于任何给定的形状,我希望能够获得红色边界矩形(没有旋转)。
显然,我可以在 fabricJS 中为每种可能的形状编写一个例程,但我不想重新发明轮子!有什么想法吗?
编辑这是一个显示当前边界框(红色)的交互式片段:
$(function ()
{
canvas = new fabric.Canvas('c');
canvas.add(new fabric.Triangle({
left: 50,
top: 50,
fill: '#FF0000',
width: 50,
height: 50,
angle : 30
}));
canvas.add(new fabric.Circle({
left: 250,
top: 50,
fill: '#00ff00',
radius: 50,
angle : 30
}));
canvas.add(new fabric.Polygon([
{x: 185, y: 0},
{x: 250, y: 100},
{x: 385, y: 170},
{x: 0, y: 245} ], {
left: 450,
top: 50,
fill: '#0000ff',
angle : 30
}));
canvas.on("after:render", function(opt)
{
canvas.contextContainer.strokeStyle = '#FF0000';
canvas.forEachObject(function(obj)
{
var bound = obj.getBoundingRect();
canvas.contextContainer.strokeRect(
bound.left + 0.5,
bound.top + 0.5,
bound.width,
bound.height
);
});
});
canvas.renderAll();
});
<script src="//cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.6/fabric.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="c" width="800" height="600"></canvas><br/>
最佳答案
所以getBoundingBox是fabricjs的Object类的一个方法。 没有什么能阻止您为您能想到的每种形状重写此方法。
我将从圆形和三 Angular 形开始,让您想象多边形。当形状是路径或将圆缩放为椭圆时,它变得越来越难。
圆形是最难的。 我对所有象限的 30、60、90 度圆进行了采样。仍然不完美。您可能需要增加采样或找到更好的公式(也许每 15 度采样一次就可以解决问题)。
三 Angular 形比较容易,因为它有 3 个兴趣点。
多边形是由三 Angular 形派生出来的,这里没有什么难的。
fabric.Circle.prototype.getBoundingRect = function() {
var matrix = this.calcTransformMatrix();
var points = [{x:-this.width/2, y:0}, {x:this.width/2, y:0}, {x:0, y: -this.height/2}, {x: 0, y: this.height/2}, {x: 0, y: -this.height/2}, {x: 0.433 * this.width, y: this.height/4}, {x: -0.433 * this.width, y: this.height/4}, {y: 0.433 * this.height, x: this.width/4}, {y: -0.433 * this.height, x: this.width/4}, {y: -0.433 * this.height, x: -this.width/4}, {y: 0.433 * this.height, x: -this.width/4}, {x: 0.433 * this.width, y: -this.height/4}, {x: -0.433 * this.width, y: -this.height/4}];
points = points.map(function(p) {
return fabric.util.transformPoint(p, matrix);
});
return fabric.util.makeBoundingBoxFromPoints(points);
}
fabric.Triangle.prototype.getBoundingRect = function() {
var matrix = this.calcTransformMatrix();
var points = [{x:-this.width/2, y:this.height/2}, {x:this.width/2, y:this.height/2}, {x:0, y: -this.height/2}, {x: 0, y: 0}];
points = points.map(function(p) {
return fabric.util.transformPoint(p, matrix);
});
return fabric.util.makeBoundingBoxFromPoints(points);
}
fabric.Polygon.prototype.getBoundingRect = function() {
var matrix = this.calcTransformMatrix();
var points = this.points;
var offsetX = this.pathOffset.x;
var offsetY = this.pathOffset.y;
points = points.map(function(p) {
return fabric.util.transformPoint({x: p.x - offsetX , y: p.y -
offsetY}, matrix);
});
return fabric.util.makeBoundingBoxFromPoints(points);
}
$(function ()
{
fabric.util.makeBoundingBoxFromPoints = function(points) {
var minX = fabric.util.array.min(points, 'x'),
maxX = fabric.util.array.max(points, 'x'),
width = Math.abs(minX - maxX),
minY = fabric.util.array.min(points, 'y'),
maxY = fabric.util.array.max(points, 'y'),
height = Math.abs(minY - maxY);
return {
left: minX,
top: minY,
width: width,
height: height
};
};
fabric.Circle.prototype.getBoundingRect = function() {
var matrix = this.calcTransformMatrix();
var points = [{x:-this.width/2, y:0}, {x:this.width/2, y:0}, {x:0, y: -this.height/2}, {x: 0, y: this.height/2}, {x: 0, y: -this.height/2}, {x: 0.433 * this.width, y: this.height/4}, {x: -0.433 * this.width, y: this.height/4}, {y: 0.433 * this.height, x: this.width/4}, {y: -0.433 * this.height, x: this.width/4}, {y: -0.433 * this.height, x: -this.width/4}, {y: 0.433 * this.height, x: -this.width/4}, {x: 0.433 * this.width, y: -this.height/4}, {x: -0.433 * this.width, y: -this.height/4}];
points = points.map(function(p) {
return fabric.util.transformPoint(p, matrix);
});
return fabric.util.makeBoundingBoxFromPoints(points);
}
fabric.Triangle.prototype.getBoundingRect = function() {
var matrix = this.calcTransformMatrix();
var points = [{x:-this.width/2, y:this.height/2}, {x:this.width/2, y:this.height/2}, {x:0, y: -this.height/2}, {x: 0, y: 0}];
points = points.map(function(p) {
return fabric.util.transformPoint(p, matrix);
});
return fabric.util.makeBoundingBoxFromPoints(points);
}
fabric.Polygon.prototype.getBoundingRect = function() {
var matrix = this.calcTransformMatrix();
var points = this.points;
var offsetX = this.pathOffset.x;
var offsetY = this.pathOffset.y;
points = points.map(function(p) {
return fabric.util.transformPoint({x: p.x - offsetX , y: p.y -
offsetY}, matrix);
});
return fabric.util.makeBoundingBoxFromPoints(points);
}
canvas = new fabric.Canvas('c');
canvas.add(new fabric.Triangle({
left: 50,
top: 50,
fill: '#FF0000',
width: 50,
height: 50,
angle : 30
}));
canvas.add(new fabric.Circle({
left: 250,
top: 50,
fill: '#00ff00',
radius: 50,
angle : 30
}));
canvas.add(new fabric.Polygon([
{x: 185, y: 0},
{x: 250, y: 100},
{x: 385, y: 170},
{x: 0, y: 245} ], {
left: 450,
top: 50,
fill: '#0000ff',
angle : 30
}));
canvas.on("after:render", function(opt)
{
canvas.contextContainer.strokeStyle = '#FF0000';
canvas.forEachObject(function(obj)
{
var bound = obj.getBoundingRect();
if(bound)
{
canvas.contextContainer.strokeRect(
bound.left + 0.5,
bound.top + 0.5,
bound.width,
bound.height
);
}
});
});
canvas.renderAll();
});
<script src="//cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.6/fabric.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="c" width="800" height="600"></canvas><br/>
关于javascript - 获取容器的标准方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42800125/