Ajouter un canevas dans un autre canevas: obj.setCoords n'est pas une fonction (tissu js)

Commencé à utiliser fabric.js et à essayer d'ajouter une toile à l'intérieur d'une autre toile, de sorte que la toile supérieure reste constante et j'ajoute des objets à une toile intérieure.

Voici l'extrait d'ajouter une toile à un autre canevas.

canvas = new fabric.Canvas('artcanvas'); innerCanvas = new fabric.Canvas("innerCanvas"); canvas.add(innerCanvas); 

Et mon html ressemble à ça

 <canvas id="artcanvas" width="500" height="500"></canvas> <canvas id="innerCanvas" width="200" height="200" ></canvas> 

Une fois que vous les avez ajouté, ce que je vais faire, ajoutez les coordonnées à la toile intérieure, de sorte qu'il ressemble à l'utilisateur final.

Cependant, a rencontré l'erreur ci-dessous pour le code essayé

  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 

En regardant le message d'erreur, il suffit de passer à la ligne d'erreur et voici ce que j'ai trouvé dans la console Chrome

Entrez la description de l'image ici

Quelqu'un peut-il indiquer l'erreur dans mes codes?

Après avoir traversé des discussions et des solutions Internet, je suis en train d'utiliser le Rectangle de tissu comme un clipper et de définir ses limites pour que l'utilisateur puisse être capable de laisser tomber / jouer avec ce clipper particulier.

Le rouge pointu ( image ci-dessous ) est mon clipper et maintenant je peux lier la goutte et ci-dessous est le code pour ajouter une image avec un clipper.

 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); }); } 

Entrez la description de l'image ici

Maintenant, en ajoutant n'importe quelle image / couche à la toile, je lier cette image / couche / texte à la clipper que j'ai créée.

 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"); } 

Et l'apparence, après la restriction des limites, Entrez la description de l'image ici

Voici le violon que j'ai créé avec une url d'image statique.

https://jsfiddle.net/sureshatta/yxuoav39/

Je reste donc avec cette solution pour l'instant et j'ai l'impression que cela est dangereux. Vous recherchez d'autres solutions propres.

Pour autant que je sache, vous ne pouvez pas ajouter une toile sur un autre canevas – vous obtenez cette erreur car elle essaie d'appeler setCoords () sur l'objet que vous avez ajouté, mais dans ce cas, c'est une autre toile et un canevas.Canvas doesn 'Contient cette méthode (voir docs ). Je pense qu'une meilleure approche serait d'avoir deux toiles et de les positionner relativement en utilisant CSS – voir cette simple violon

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); }) 

Pour gérer la sérialisation de l'objet, vous pouvez faire quelque chose comme ceci:

 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); 

Cela vous donnera alors le JSON pour tous les objets sur les deux toiles

Je ne comprends pas pourquoi vous voulez faire cette chose, mais pour mettre une toile dans une autre toile, vous avez une façon simple:

 canvas = new fabric.Canvas('artcanvas'); innerCanvas = new fabric.Canvas("innerCanvas"); imageContainer = new fabric.Image(innerCanvas.lowerCanvasEl); canvas.add(imageContainer); 

Ensuite, selon ce que vous voulez faire, vous devrez peut-être des réglages supplémentaires, mais cela devrait fonctionner hors de la boîte.

Ne créez pas un canevas

La plupart des objets en tissu (de mon expérience limitée) sont à un certain point convertis en toile. La création d'une toile de tissu supplémentaire pour gérer un groupe d'objets est un peu inutile car vous n'ajoutez que des éléments généraux et des tissus imitant les objets construits dans des groupes.

Les objets en tissu sont essentiellement des enveloppes de toiles DOM.

L'exemple suivant montre comment le tissu utilise un canevas pour stocker le contenu d'un groupe. La démo crée un groupe et l'ajoute à la toile de tissu, puis obtient la toile de groupe et l'ajoute au DOM. En cliquant sur le canevas du groupe, vous ajouterez un cercle. Notez comment cela se développe pour accueillir les nouveaux cercles.

 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> 

innerCanvas.setCoords(); C'est une fonction, mais vous n'en avez besoin qu'après avoir configuré les coordonnées. Ou plus précis, définissez ces quatre éléments:

 innerCanvas.scaleX = 1; innerCanvas.scaleY = 1; innerCanvas.left = 150; innerCanvas.top = 150; innerCanvas.setCoords(); canvas.renderAll();