在另一个 canvas 中添加 canvas:obj.setCoords 不是函数(fabric js)
Adding canvas inside another canvas: obj.setCoords is not a function( fabric js)
开始使用 fabric.js 并尝试在另一个 canvas 中添加一个 canvas,以便顶部 canvas 保持不变,我将向内部 canvas。
这是将 canvas 添加到另一个 canvas 的片段。
canvas = new fabric.Canvas('artcanvas');
innerCanvas = new fabric.Canvas("innerCanvas");
canvas.add(innerCanvas);
我的 html 看起来像这样
<canvas id="artcanvas" width="500" height="500"></canvas>
<canvas id="innerCanvas" width="200" height="200" ></canvas>
一旦成功添加这些,我要做的是,将坐标添加到内部 canvas,以便最终用户看起来像一个在另一个上。
然而,运行 试过的代码出现以下错误
Uncaught TypeError: obj.setCoords is not a function
at klass._onObjectAdded (fabric.js:6894)
at klass.add (fabric.js:231)
at main.js:60
at fabric.js:19435
at HTMLImageElement.fabric.util.loadImage.img.onload (fabric.js:754)
_onObjectAdded @ fabric.js:6894
add @ fabric.js:231
(anonymous) @ main.js:60
(anonymous) @ fabric.js:19435
fabric.util.loadImage.img.onload @ fabric.js:754
查看错误消息,刚转到错误行,这是我在 chrome 控制台中找到的内容
谁能指出我代码中的错误?
据我所知,您不能将 canvas 添加到另一个 canvas - 当它尝试在您添加的对象上调用 setCoords() 时出现该错误,但在这种情况下,它是另一个 canvas 并且 fabric.Canvas 不包含该方法(请参阅 docs). I think a better approach would be to have two canvases and position them relatively using CSS - see this simple fiddle
HTML
<div class="parent">
<div class="artcanvas">
<canvas id="artcanvas" width="500" height="500"></canvas>
</div>
<div class="innerCanvas">
<canvas id="innerCanvas" width="200" height="200" ></canvas>
</div>
</div>
CSS
.parent {
position: relative;
background: black;
}
.artcanvas {
position: absolute;
left: 0;
top: 0;
}
.innerCanvas {
position: absolute;
left: 150px;
top: 150px;
}
JS
$(document).ready(function() {
canvas = new fabric.Canvas('artcanvas');
innerCanvas = new fabric.Canvas("innerCanvas");
var rect = new fabric.Rect({
fill: 'grey',
width: 500,
height: 500
});
canvas.add(rect);
var rect2 = new fabric.Rect({
fill: 'green',
width: 200,
height: 200
});
innerCanvas.add(rect2);
})
要处理对象序列化,您可以这样做:
var innerObjs = innerCanvas.toObject();
console.dir(innerObjs);
var outerObjs = canvas.toObject();
innerObjs.objects.forEach(function (obj) {
obj.left += leftOffset; // offset of inner canvas
obj.top += topOffset;
outerObjs.objects.push(obj);
});
var json = JSON.stringify(outerObjs);
然后这将为您提供 canvases
上所有对象的 JSON
经过 no.of 讨论和互联网解决方案后,我暂时将 Fabric Rectangle 用作裁剪器并设置其边界,以便用户能够 drop/play 使用该特定裁剪器。
红色点缀(下图)是我的裁剪器,现在我可以绑定删除,下面是使用裁剪器添加图像的代码。
function addImageToCanvas(imgSrc) {
fabric.Object.prototype.transparentCorners = false;
fabric.Image.fromURL(imgSrc, function(myImg) {
var img1 = myImg.set({
left: 20,
top: 20,
width: 460,
height: 460
});
img1.selectable = false;
canvas.add(img1);
var clipRectangle = new fabric.Rect({
originX: 'left',
originY: 'top',
left: 150,
top: 150,
width: 200,
height: 200,
fill: 'transparent',
/* use transparent for no fill */
strokeDashArray: [10, 10],
stroke: 'red',
selectable: false
});
clipRectangle.set({
clipFor: 'layer'
});
canvas.add(clipRectangle);
});
}
现在,在将任何 image/layer 附加到 canvas 时,我将 image/layer/文本绑定到我创建的剪裁器。
function addLayerToCanvas(laImg) {
var height = $(laImg).height();
var width = $(laImg).width();
var clickedImage = new Image();
clickedImage.onload = function(img) {
var pug = new fabric.Image(clickedImage, {
width: width,
height: height,
left: 150,
top: 150,
clipName: 'layer',
clipTo: function(ctx) {
return _.bind(clipByName, pug)(ctx)
}
});
canvas.add(pug);
};
clickedImage.src = $(laImg).attr("src");
}
看起来像,在限制边界之后,
这是我用一些静态图像 url 创建的 fiddle。
https://jsfiddle.net/sureshatta/yxuoav39/
所以我现在继续使用这个解决方案,我真的觉得它很老套而且很脏。寻找其他一些干净的解决方案。
我不明白你为什么要这样做,但是把一个 canvas 放在另一个 canvas 里面,你有一个简单的方法:
canvas = new fabric.Canvas('artcanvas');
innerCanvas = new fabric.Canvas("innerCanvas");
imageContainer = new fabric.Image(innerCanvas.lowerCanvasEl);
canvas.add(imageContainer);
然后根据您想要执行的操作,您可能需要进行额外的调整,但这应该是开箱即用的。
不要创建 canvas
fabric 中的大多数对象(根据我有限的经验)在某个时候会转换为 canvas。创建一个额外的结构 canvas 来管理一组对象是毫无意义的,因为您只是在添加开销并模仿内置在组对象中的结构。
Fabric 对象基本上是 DOM canvases 包装器。
下面的例子展示了 fabric 如何使用 canvas 来存储组的内容。该演示创建一个组并将其添加到结构 canvas,然后获取组 canvas 并将其添加到 DOM。点击群组的 canvas 将添加一个圆圈。请注意它是如何成长以适应新圈子的。
const radius = 50;
const fill = "#0F0";
var pos = 60;
const canvas = new fabric.Canvas('fCanvas');
// create a fabric group and add two circles
const group = new fabric.Group([
new fabric.Circle({radius, top : 5, fill, left : 20 }),
new fabric.Circle({radius, top : 5, fill, left : 120 })
], { left: 0, top: 0 });
// add group to the fabric canvas;
canvas.add(group);
// get the groups canvas and add it to the DOM
document.body.appendChild(group._cacheContext.canvas);
// add event listener to add circles to the group
group._cacheContext.canvas.addEventListener("click",(e)=>{
group.addWithUpdate(
new fabric.Circle({radius, top : pos, fill : "blue", left : 60 })
);
canvas.renderAll();
pos += 60;
});
canvas {
border : 2px solid black;
}
div {
margin : 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.13/fabric.min.js"></script>
<div>Fabric's canvas "canvas = new fabric.Canvas('fCanvas');"</div>
<canvas id="fCanvas" width="256" height="140"></canvas>
<div>Fabric group canvas below. Click on it to add a circle.</div>
使用组而不是结构的新实例canvas。
如您所见,已为您生成 canvas。添加另一个 fabric canvas(注意 fabric canvas 与 DOM canvas 不同)只会增加 fabric 要做的更多工作,而 fabric 已经有很多工作要做。
您最好使用一个组,并让该组保存您希望隐藏的其他织物对象的内容。这也将其内容包含在一个组中。
只是一张图片
而且不是,DOM canvas 是一个图像,可以像任何其他图像一样被 fabric 使用。有时直接渲染到 canvas 而不是通过 fabric 会更好,这样可以避免 fabric 需要操作的渲染开销。
要将 DOM canvas 添加到织物中,只需将其添加为图像即可。边框和文本不是 fabric 对象,除了渲染它们的代码外,它们不占用内存,如果您使用 fabric canvas 和对象,则不会产生额外的 CPU 开销。
const canvas = new fabric.Canvas('fCanvas');
// create a standard DOM canvas
const myImage = document.createElement("canvas");
// size it add borders and text
myImage.width = myImage.height = 256;
const ctx = myImage.getContext("2d");
ctx.fillRect(0,0,256,256);
ctx.fillStyle = "white";
ctx.fillRect(4,4,248,248);
ctx.fillStyle = "black";
ctx.font = "32px arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText("The DOM canvas!",128,128);
// use the canvas to create a fabric image and add it to fabrics canvas.
canvas.add( new fabric.Image(myImage, {
left: (400 - 256) / 2,
top: (400 - 256) / 2,
}));
canvas {
border : 2px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.13/fabric.min.js"></script>
<canvas id="fCanvas" width="400" height="400"></canvas>
innerCanvas.setCoords();
是一个函数,但是你设置坐标后才需要它。或者更准确地说,设置这四个元素:
innerCanvas.scaleX = 1;
innerCanvas.scaleY = 1;
innerCanvas.left = 150;
innerCanvas.top = 150;
innerCanvas.setCoords();
canvas.renderAll();
开始使用 fabric.js 并尝试在另一个 canvas 中添加一个 canvas,以便顶部 canvas 保持不变,我将向内部 canvas。
这是将 canvas 添加到另一个 canvas 的片段。
canvas = new fabric.Canvas('artcanvas');
innerCanvas = new fabric.Canvas("innerCanvas");
canvas.add(innerCanvas);
我的 html 看起来像这样
<canvas id="artcanvas" width="500" height="500"></canvas>
<canvas id="innerCanvas" width="200" height="200" ></canvas>
一旦成功添加这些,我要做的是,将坐标添加到内部 canvas,以便最终用户看起来像一个在另一个上。
然而,运行 试过的代码出现以下错误
Uncaught TypeError: obj.setCoords is not a function
at klass._onObjectAdded (fabric.js:6894)
at klass.add (fabric.js:231)
at main.js:60
at fabric.js:19435
at HTMLImageElement.fabric.util.loadImage.img.onload (fabric.js:754)
_onObjectAdded @ fabric.js:6894
add @ fabric.js:231
(anonymous) @ main.js:60
(anonymous) @ fabric.js:19435
fabric.util.loadImage.img.onload @ fabric.js:754
查看错误消息,刚转到错误行,这是我在 chrome 控制台中找到的内容
谁能指出我代码中的错误?
据我所知,您不能将 canvas 添加到另一个 canvas - 当它尝试在您添加的对象上调用 setCoords() 时出现该错误,但在这种情况下,它是另一个 canvas 并且 fabric.Canvas 不包含该方法(请参阅 docs). I think a better approach would be to have two canvases and position them relatively using CSS - see this simple fiddle
HTML
<div class="parent">
<div class="artcanvas">
<canvas id="artcanvas" width="500" height="500"></canvas>
</div>
<div class="innerCanvas">
<canvas id="innerCanvas" width="200" height="200" ></canvas>
</div>
</div>
CSS
.parent {
position: relative;
background: black;
}
.artcanvas {
position: absolute;
left: 0;
top: 0;
}
.innerCanvas {
position: absolute;
left: 150px;
top: 150px;
}
JS
$(document).ready(function() {
canvas = new fabric.Canvas('artcanvas');
innerCanvas = new fabric.Canvas("innerCanvas");
var rect = new fabric.Rect({
fill: 'grey',
width: 500,
height: 500
});
canvas.add(rect);
var rect2 = new fabric.Rect({
fill: 'green',
width: 200,
height: 200
});
innerCanvas.add(rect2);
})
要处理对象序列化,您可以这样做:
var innerObjs = innerCanvas.toObject();
console.dir(innerObjs);
var outerObjs = canvas.toObject();
innerObjs.objects.forEach(function (obj) {
obj.left += leftOffset; // offset of inner canvas
obj.top += topOffset;
outerObjs.objects.push(obj);
});
var json = JSON.stringify(outerObjs);
然后这将为您提供 canvases
上所有对象的 JSON经过 no.of 讨论和互联网解决方案后,我暂时将 Fabric Rectangle 用作裁剪器并设置其边界,以便用户能够 drop/play 使用该特定裁剪器。
红色点缀(下图)是我的裁剪器,现在我可以绑定删除,下面是使用裁剪器添加图像的代码。
function addImageToCanvas(imgSrc) {
fabric.Object.prototype.transparentCorners = false;
fabric.Image.fromURL(imgSrc, function(myImg) {
var img1 = myImg.set({
left: 20,
top: 20,
width: 460,
height: 460
});
img1.selectable = false;
canvas.add(img1);
var clipRectangle = new fabric.Rect({
originX: 'left',
originY: 'top',
left: 150,
top: 150,
width: 200,
height: 200,
fill: 'transparent',
/* use transparent for no fill */
strokeDashArray: [10, 10],
stroke: 'red',
selectable: false
});
clipRectangle.set({
clipFor: 'layer'
});
canvas.add(clipRectangle);
});
}
现在,在将任何 image/layer 附加到 canvas 时,我将 image/layer/文本绑定到我创建的剪裁器。
function addLayerToCanvas(laImg) {
var height = $(laImg).height();
var width = $(laImg).width();
var clickedImage = new Image();
clickedImage.onload = function(img) {
var pug = new fabric.Image(clickedImage, {
width: width,
height: height,
left: 150,
top: 150,
clipName: 'layer',
clipTo: function(ctx) {
return _.bind(clipByName, pug)(ctx)
}
});
canvas.add(pug);
};
clickedImage.src = $(laImg).attr("src");
}
看起来像,在限制边界之后,
这是我用一些静态图像 url 创建的 fiddle。
https://jsfiddle.net/sureshatta/yxuoav39/
所以我现在继续使用这个解决方案,我真的觉得它很老套而且很脏。寻找其他一些干净的解决方案。
我不明白你为什么要这样做,但是把一个 canvas 放在另一个 canvas 里面,你有一个简单的方法:
canvas = new fabric.Canvas('artcanvas');
innerCanvas = new fabric.Canvas("innerCanvas");
imageContainer = new fabric.Image(innerCanvas.lowerCanvasEl);
canvas.add(imageContainer);
然后根据您想要执行的操作,您可能需要进行额外的调整,但这应该是开箱即用的。
不要创建 canvas
fabric 中的大多数对象(根据我有限的经验)在某个时候会转换为 canvas。创建一个额外的结构 canvas 来管理一组对象是毫无意义的,因为您只是在添加开销并模仿内置在组对象中的结构。
Fabric 对象基本上是 DOM canvases 包装器。
下面的例子展示了 fabric 如何使用 canvas 来存储组的内容。该演示创建一个组并将其添加到结构 canvas,然后获取组 canvas 并将其添加到 DOM。点击群组的 canvas 将添加一个圆圈。请注意它是如何成长以适应新圈子的。
const radius = 50;
const fill = "#0F0";
var pos = 60;
const canvas = new fabric.Canvas('fCanvas');
// create a fabric group and add two circles
const group = new fabric.Group([
new fabric.Circle({radius, top : 5, fill, left : 20 }),
new fabric.Circle({radius, top : 5, fill, left : 120 })
], { left: 0, top: 0 });
// add group to the fabric canvas;
canvas.add(group);
// get the groups canvas and add it to the DOM
document.body.appendChild(group._cacheContext.canvas);
// add event listener to add circles to the group
group._cacheContext.canvas.addEventListener("click",(e)=>{
group.addWithUpdate(
new fabric.Circle({radius, top : pos, fill : "blue", left : 60 })
);
canvas.renderAll();
pos += 60;
});
canvas {
border : 2px solid black;
}
div {
margin : 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.13/fabric.min.js"></script>
<div>Fabric's canvas "canvas = new fabric.Canvas('fCanvas');"</div>
<canvas id="fCanvas" width="256" height="140"></canvas>
<div>Fabric group canvas below. Click on it to add a circle.</div>
使用组而不是结构的新实例canvas。
如您所见,已为您生成 canvas。添加另一个 fabric canvas(注意 fabric canvas 与 DOM canvas 不同)只会增加 fabric 要做的更多工作,而 fabric 已经有很多工作要做。
您最好使用一个组,并让该组保存您希望隐藏的其他织物对象的内容。这也将其内容包含在一个组中。
只是一张图片
而且不是,DOM canvas 是一个图像,可以像任何其他图像一样被 fabric 使用。有时直接渲染到 canvas 而不是通过 fabric 会更好,这样可以避免 fabric 需要操作的渲染开销。
要将 DOM canvas 添加到织物中,只需将其添加为图像即可。边框和文本不是 fabric 对象,除了渲染它们的代码外,它们不占用内存,如果您使用 fabric canvas 和对象,则不会产生额外的 CPU 开销。
const canvas = new fabric.Canvas('fCanvas');
// create a standard DOM canvas
const myImage = document.createElement("canvas");
// size it add borders and text
myImage.width = myImage.height = 256;
const ctx = myImage.getContext("2d");
ctx.fillRect(0,0,256,256);
ctx.fillStyle = "white";
ctx.fillRect(4,4,248,248);
ctx.fillStyle = "black";
ctx.font = "32px arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText("The DOM canvas!",128,128);
// use the canvas to create a fabric image and add it to fabrics canvas.
canvas.add( new fabric.Image(myImage, {
left: (400 - 256) / 2,
top: (400 - 256) / 2,
}));
canvas {
border : 2px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.13/fabric.min.js"></script>
<canvas id="fCanvas" width="400" height="400"></canvas>
innerCanvas.setCoords();
是一个函数,但是你设置坐标后才需要它。或者更准确地说,设置这四个元素:
innerCanvas.scaleX = 1;
innerCanvas.scaleY = 1;
innerCanvas.left = 150;
innerCanvas.top = 150;
innerCanvas.setCoords();
canvas.renderAll();