Добавление холста внутри другого холста: obj.setCoords не является функцией (fabric js)
Начните с использования fabric.js и попытайтесь добавить холст внутри другого холста, так что верхний холст остается постоянным, и я добавлю объекты на внутренний холст.
Вот фрагмент добавления холста к другому холсту.
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>
Как только они будут успешно добавлены, что я собираюсь сделать, добавьте координаты во внутренний холст, чтобы он выглядел как один на другом для конечного пользователя.
Однако, столкнулся с приведенной ниже ошибкой для проверенного кода
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
![введите описание изображения здесь]()
Может кто-то указать на ошибку в моих кодах?
Ответы
Ответ 1
После прохождения обсуждений и интернет-решений на данный момент я использую Fabric Rectangle в качестве клипера и устанавливаю его границы, чтобы пользователь мог сбрасывать/играть с помощью этого конкретного клипера.
Пунктирный красный (изображение ниже) - это мой клипер, и теперь я могу связать выпадение, а ниже - код для добавления изображения с клипером.
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);
});
}
![введите описание изображения здесь]()
Теперь, добавляя любое изображение/слой в холст, я привязываю этот образ/слой/текст к клиперу, который я создал.
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-адресом изображения.
https://jsfiddle.net/sureshatta/yxuoav39/
Так что я остаюсь с этим решением на данный момент, и я действительно чувствую, что это хаки и грязные. Ищете другие чистые решения.
Ответ 2
Насколько я знаю, вы не можете добавить холст к другому холсту - вы получаете эту ошибку, поскольку он пытается вызвать setCoords() для объекта, который вы добавили, но в этом случае это другой холст и ткань .Canvas не содержит этого метода (см. docs). Я думаю, что лучший подход состоял бы в том, чтобы иметь два холста и относить их относительно с помощью CSS - см. эта простая скрипка
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);
Это даст вам JSON для всех объектов на обеих полотнах
Ответ 3
У меня нет понимания, почему вы хотите сделать это, но чтобы поместить холст внутри другого холста, у вас есть один простой способ:
canvas = new fabric.Canvas('artcanvas');
innerCanvas = new fabric.Canvas("innerCanvas");
imageContainer = new fabric.Image(innerCanvas.lowerCanvasEl);
canvas.add(imageContainer);
Затем, в зависимости от того, что вы хотите сделать, вам могут потребоваться дополнительные настройки, но это должно работать из коробки.
Ответ 4
Не создавайте холст
Большинство объектов в ткани (из моего ограниченного опыта) в какой-то момент преобразуются в холст. Создание дополнительного холста ткани для управления группой объектов является бессмысленным, поскольку вы просто добавляете служебные и имитирующие ткани, созданные в объекте групп.
Объекты ткани в основном представляют собой обертки холлов DOM.
В следующем примере показано, как ткань использует холст для хранения содержимого группы. Демо создает группу и добавляет ее к холсту ткани, затем получает холст групп и добавляет его в DOM. Нажатие на холст группы добавит круг. Обратите внимание, как он растет для размещения новых кругов.
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 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>
Ответ 5
innerCanvas.setCoords();
- функция, но она вам нужна только после того, как вы установили координаты. Или более точно, установите эти четыре элемента:
innerCanvas.scaleX = 1;
innerCanvas.scaleY = 1;
innerCanvas.left = 150;
innerCanvas.top = 150;
innerCanvas.setCoords();
canvas.renderAll();