Lee*_*lor 5 javascript fabricjs
我正在尝试编写一些代码来使对象相互对齐。所以我想得到每个对象的“包含框”。
我知道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();
});Run Code Online (Sandbox Code Playgroud)
<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/>Run Code Online (Sandbox Code Playgroud)
我遇到了同样的问题,并且找到了解决方法。我从活动对象创建了一个临时 SVG 并将其放置在视口之外。然后我使用本机getBBox()函数测量了真实的边界框。
更新
显然,上面的解决方案仅适用于 Firefox (76),所以我想出了一个不同的解决方案。由于我找不到正常工作的本机函数来获取形状的真实边界框,因此我决定扫描像素并从那里检索边界。
小提琴: https://jsfiddle.net/divpusher/2m7c61gw/118/
怎么运行的:
下面的演示
// ---------------------------
// the magic
var tempCanv, ctx, w, h;
function getImageData(dataUrl) {
// we need to use a temp canvas to get imagedata
if (tempCanv == null) {
tempCanv = document.createElement('canvas');
tempCanv.style.border = '1px solid blue';
tempCanv.style.visibility = 'hidden';
ctx = tempCanv.getContext('2d');
document.body.appendChild(tempCanv);
}
return new Promise(function(resolve, reject) {
if (dataUrl == null) return reject();
var image = new Image();
image.addEventListener('load', function() {
w = image.width;
h = image.height;
tempCanv.width = w;
tempCanv.height = h;
ctx.drawImage(image, 0, 0, w, h);
var imageData = ctx.getImageData(0, 0, w, h).data.buffer;
resolve(imageData, false);
});
image.src = dataUrl;
});
}
function scanPixels(imageData) {
var data = new Uint32Array(imageData),
len = data.length,
x, y, y1, y2, x1 = w, x2 = 0;
// y1
for(y = 0; y < h; y++) {
for(x = 0; x < w; x++) {
if (data[y * w + x] & 0xff000000) {
y1 = y;
y = h;
break;
}
}
}
// y2
for(y = h - 1; y > y1; y--) {
for(x = 0; x < w; x++) {
if (data[y * w + x] & 0xff000000) {
y2 = y;
y = 0;
break;
}
}
}
// x1
for(y = y1; y < y2; y++) {
for(x = 0; x < w; x++) {
if (x < x1 && data[y * w + x] & 0xff000000) {
x1 = x;
break;
}
}
}
// x2
for(y = y1; y < y2; y++) {
for(x = w - 1; x > x1; x--) {
if (x > x2 && data[y * w + x] & 0xff000000) {
x2 = x;
break;
}
}
}
return {
x1: x1,
x2: x2,
y1: y1,
y2: y2
}
}
// ---------------------------
// align buttons
function alignLeft(){
var obj = canvas.getActiveObject();
obj.set('left', 0);
obj.setCoords();
canvas.renderAll();
}
function alignLeftbyBoundRect(){
var obj = canvas.getActiveObject();
var bound = obj.getBoundingRect();
obj.set('left', (obj.left - bound.left));
obj.setCoords();
canvas.renderAll();
}
function alignRealLeft(){
var obj = canvas.getActiveObject();
getImageData(obj.toDataURL())
.then(function(data) {
var bound = obj.getBoundingRect();
var realBound = scanPixels(data);
obj.set('left', (obj.left - bound.left - realBound.x1));
obj.setCoords();
canvas.renderAll();
});
}
// ---------------------------
// set up canvas
var canvas = new fabric.Canvas('c');
var path = new fabric.Path('M 0 0 L 150 50 L 120 150 z');
path.set({
left: 170,
top: 30,
fill: 'rgba(0, 128, 0, 0.5)',
stroke: '#000',
strokeWidth: 4,
strokeLineCap: 'square',
angle: 65
});
canvas.add(path);
canvas.setActiveObject(path);
var circle = new fabric.Circle({
left: 370,
top: 30,
radius: 45,
fill: 'blue',
scaleX: 1.5,
angle: 30
});
canvas.add(circle);
canvas.forEachObject(function(obj) {
var setCoords = obj.setCoords.bind(obj);
obj.on({
moving: setCoords,
scaling: setCoords,
rotating: setCoords
});
});
canvas.on('after:render', function() {
canvas.contextContainer.strokeStyle = 'red';
canvas.forEachObject(function(obj) {
getImageData(obj.toDataURL())
.then(function(data) {
var boundRect = obj.getBoundingRect();
var realBound = scanPixels(data);
canvas.contextContainer.strokeRect(
boundRect.left + realBound.x1,
boundRect.top + realBound.y1,
realBound.x2 - realBound.x1,
realBound.y2 - realBound.y1
);
});
});
});Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.3/fabric.min.js"></script>
<p> </p>
<button onclick="alignLeft()">align left (default)</button>
<button onclick="alignLeftbyBoundRect()">align left (by bounding rect)</button>
<button onclick="alignRealLeft()">align REAL left (by pixel)</button>
<p></p>
<canvas id="c" width="600" height="250" style="border: 1px solid rgb(204, 204, 204); touch-action: none; user-select: none;" class="lower-canvas"></canvas>
<p></p>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3291 次 |
| 最近记录: |