Can't get image with canvas.getObjects(); - javascript

Why next function can't find an image ( when i check with debugger i may see all other elements but not the image)
function getItemByName3(name) {
var object = null,
objects = canvas.getObjects();
objectsCount=canvas.getObjects().length;
for (var i = 0, len = objectsCount; i < len; i++) {
if (objects[i].type && objects[i].type == "image"){
if (objects[i].id && objects[i].id===name) {
object = objects[i];
break;
}
}
}
return object;
}
function backgroundSaveToJsonF(){ ////____________________________________________saveJsonF;
var backgroundImage=getItemByName3(document.getElementById("selectProject").value+"imageID");
var backgroundImageForDB=JSON.stringify(backgroundImage.toObject(['id','sendToBack','selectable']));
I am uploading image to canvas with next code:
document.getElementById('imgLoader').addEventListener("change", function(e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function(f) {
var data = f.target.result;
fabric.Image.fromURL(data, function(img) {
var oImg = img.set({
left: 0,
top: 0,
angle: 00,
width: canvas.width,
height: canvas.height,
id:document.getElementById("selectProject").value+"imageID"
});
canvas.setBackgroundImage(oImg).renderAll();
var dataURL = canvas.toDataURL({
format: 'png',
quality: 0.8
});
});
};
reader.readAsDataURL(file);
});
thank you

DEMO
document.getElementById('imgLoader').addEventListener("change", function(e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function(f) {
var data = f.target.result;
fabric.Image.fromURL(data, function(img) {
var oImg = img.set({
left: 0,
top: 0,
angle: 00,
width: canvas.width,
height: canvas.height
});
//canvas.setBackgroundImage(oImg).renderAll();
canvas.add(oImg);
console.log(canvas.getObjects());
var dataURL = canvas.toDataURL({
format: 'png',
quality: 0.8
});
});
};
reader.readAsDataURL(file);
});
var canvas = new fabric.Canvas('c');
canvas.add(new fabric.Rect({
left: 50,
top: 50,
height: 100,
width:100,
stroke: 'red',
fill: ''
}))
canvas.add(new fabric.Text('1',{
left: 20,
top: 50,
stroke: 'red',
fill: ''
}))
canvas.renderAll();
canvas{
border:2px dotted blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.16/fabric.min.js"></script>
<input type="file" id="imgLoader" accept="image/*"> <br>
<canvas id='c' width='400' height='400'></canvas>
Its because you are setting uploaded image as background image canvas.setBackgroundImage(oImg) you are not adding that as a object to canvas. If you want to get it in your object list then add as an object canvas.add(oImg). Check the demo.

Related

Canvas background image clears when drawing over it

The application I'm attempting to write has a user upload an image to a canvas and then draw lines over it. So far I have the uploading to the canvas down as well as the drawing of the lines, except that whenever I draw a line on the canvas, the uploaded image disappears. Below you'll see the html and javascript code I currently have for the app. The various elements were obtained from various tutorials so i'm assuming there is some incompatibility that they are overwriting each other.
HTML
<input type='file' id="fileUpload">
<canvas id="c" width = 750 height= 400 style="border:1px solid #ccc"></canvas>
Javascript
// begin file upload block
function el(id) { return document.getElementById(id); }
var canvas = el("c");
var context = canvas.getContext("2d");
function readImage() {
if (this.files && this.files[0]) {
var FR = new FileReader();
FR.onload = function (e) {
var img = new Image();
img.onload = function () {
context.drawImage(img, 0, 0,img.width,img.height,0,0,750,400);
};
img.src = e.target.result;
};
FR.readAsDataURL(this.files[0]);
}
}
el("fileUpload").addEventListener("change", readImage, false);
//end file upload block
//begin line drawing block
var canvas = new fabric.Canvas('c', { selection: false });
var line, isDown;
canvas.on('mouse:down', function(o){
isDown = true;
var pointer = canvas.getPointer(o.e);
var points = [ pointer.x, pointer.y, pointer.x, pointer.y ];
line = new fabric.Line(points, {
strokeWidth: 5,
fill: 'red',
stroke: 'red',
originX: 'center',
originY: 'center'
});
canvas.add(line);
});
canvas.on('mouse:move', function(o){
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
line.set({ x2: pointer.x, y2: pointer.y });
canvas.renderAll();
});
canvas.on('mouse:up', function(o){
isDown = false;
});
//end line drawing block
Use fabric.Image.fromURL to load image and then add to canvas using canvas.add().
DEMO
//begin line drawing block
var canvas = new fabric.Canvas('c', {
selection: false
});
var line, isDown;
canvas.on('mouse:down', function(o) {
isDown = true;
var pointer = canvas.getPointer(o.e);
var points = [pointer.x, pointer.y, pointer.x, pointer.y];
line = new fabric.Line(points, {
strokeWidth: 5,
fill: 'red',
stroke: 'red',
originX: 'center',
originY: 'center'
});
canvas.add(line);
});
canvas.on('mouse:move', function(o) {
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
line.set({
x2: pointer.x,
y2: pointer.y
});
canvas.renderAll();
});
canvas.on('mouse:up', function(o) {
isDown = false;
});
//end line drawing block
// begin file upload block
function el(id) {
return document.getElementById(id);
}
function readImage() {
if (this.files && this.files[0]) {
var FR = new FileReader();
FR.onload = function(e) {
fabric.Image.fromURL(e.target.result, function(img) {
img.set({
left: 0,
top: 0,
evented: false
});
img.scaleToWidth(canvas.width);
img.setCoords();
canvas.add(img);
})
};
FR.readAsDataURL(this.files[0]);
}
}
el("fileUpload").addEventListener("change", readImage, false);
//end file upload block
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<input type='file' id="fileUpload">
<canvas id="c" width = 750 height= 400 style="border:1px solid #ccc"></canvas>

Fabric js create a group of clip masks

I need help with fabric js
I want to create a group of clips, the group can have many clips next to each other. Each clip can have an image inside it.
similar to the grid function in canva
group of 2 clip masks with space between them
this is what I have so far it displays in a very weird shape
http://jsfiddle.net/SallyMagdyTadros/ZxYCP/1467/
<canvas id="c" width="400" height="400"></canvas>
var img01URL = 'https://www.google.com/images/srpr/logo4w.png';
(function() {
var canvas = this.__canvas = new fabric.Canvas('c');
fabric.Object.prototype.transparentCorners = false;
var img2;
fabric.Image.fromURL('http://fabricjs.com/lib/pug.jpg', function(img) {
img2 = img.scale(0.5).set({
left: 100,
top: 0,
clipTo: function(ctx) {
ctx.rect(0, 0, 100, 200);
}
});
});
fabric.Image.fromURL('https://www.google.com/images/srpr/logo4w.png',
function(img) {
img.scale(0.5).set({
left: 0,
top: 0,
clipTo: function(ctx) {
ctx.rect(0, 0, 200, 100);
}
});
var group = new fabric.Group([img, img2], {
});
group.left = 0;
group.top = 0;
canvas.add(group);
});
})();

Fabricjs drawImage alternative

I were looking for a drawImage() alternative for fabric.js lib, so I've made a function:
function drawImage(img,sx,sy,swidth,sheight,x,y,width,height) {
return new fabric.Image(img, {
left: x,
top: y,
width: width,
height: height,
id: "rhino",
clipTo: function (ctx) {
ctx.rect(sx,sy,swidth,sheight);
}
});
}
var imgElement = new Image();
imgElement.onload = function() {
var imgInstance = drawImage(imgElement, 33, 71, 104, 124, 21, 20, 87, 104);
canvas.add(imgInstance);
};
imgElement.src = "https://mdn.mozillademos.org/files/5397/rhino.jpg";
The result needs to be:
But I don't get nothing with my custom function. Where is the problem?
Codepen: http://codepen.io/anon/pen/RaxRqZ
I do not really know what you want to achieve, but using clipTo is not my advice, both for performance and complexity reasons.
Draw on a temp canvas the portion of image you need, then use this temp canvas a source for your fabricJS image.
var canvas = new fabric.Canvas('c');
function drawImage(img,sx,sy,swidth,sheight,x,y,width,height) {
var tmpc = document.createElement('canvas');
tmpc.width = swidth;
tmpc.height = sheight;
ctx = tmpc.getContext("2d");
ctx.drawImage(img,-sx,-sy);
return new fabric.Image(tmpc, {
left: x,
top: y,
width: width,
height: height,
id: "rhino"
});
}
var imgElement = new Image();
imgElement.onload = function() {
var imgInstance = drawImage(imgElement, 33, 71, 104, 124, 21, 20, 87, 104);
canvas.add(imgInstance);
};
imgElement.src = "https://mdn.mozillademos.org/files/5397/rhino.jpg";
<script src="http://www.deltalink.it/andreab/fabric/fabric.js"></script>
<canvas id="c" width="500", height="500"></canvas>
Here you can find solution,
var canvas = ctx = '';
canvas = new fabric.Canvas('canvas');
canvas.selection = false;
ctx = canvas.getContext('2d');
function drawImage(imgPath, x, y, width, height)
{
fabric.Image.fromURL(imgPath, function(img) {
img.set({
left: x,
top: y,
width: width,
height: height,
id: "rhino",
clipTo: function (ctx) {
ctx.rect(5,5,50,50);
}
});
canvas.add(img).renderAll().setActiveObject(img);
});
}
var imgElement = new Image();
imgElement.src = "https://mdn.mozillademos.org/files/5397/rhino.jpg";
imgElement.onload = function() {
drawImage(imgElement.src, 50, 50, 100, 100);
}
https://codepen.io/mullainathan/pen/wGpzvY

Remove drag property from uploaded image in canvas html5 (set area to uploaded image)

I am using fabric js for uploading image in canvas. Right now it is a draggable, But i want to remove drag property and set area to uploaded image on canvas.
HTML:
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.min.js"></script>
<canvas id="canvas" width="750" height="550"></canvas>
<input type="file" id="file">
CSS:
canvas{
border: 1px solid black;
}
JAVA SCRIPT:
var canvas = new fabric.Canvas('canvas');
document.getElementById('file').addEventListener("change", function (e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function (f) {
var data = f.target.result;
fabric.Image.fromURL(data, function (img) {
var oImg = img.set({left: 50, top: 100,width: 250, height: 200, angle: 00}).scale(0.9);
canvas.add(oImg).renderAll();
var a = canvas.setActiveObject(oImg);
});
};
reader.readAsDataURL(file);
var dataURL = canvas.toDataURL({
format: 'png',
opacity: 0.9
});
});
var canvas = new fabric.Canvas('canvas');
document.getElementById('file').addEventListener("change", function (e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function (f) {
var data = f.target.result;
fabric.Image.fromURL(data, function (img) {
var oImg = img.set({left: 50, top: 100,width:200,height:200, angle: 00}).scale(0.9);
canvas.add(oImg).renderAll();
var a = canvas.setActiveObject(oImg);
});
};
reader.readAsDataURL(file);
var dataURL = canvas.toDataURL({
format: 'png',
opacity: 0.9
});
console.log("Canvas Image " + dataURL);
});
canvas{
border: 1px solid black;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.min.js"></script>
<canvas id="canvas" width="750" height="550"></canvas>
<input type="file" id="file">
I want remove only drag property of uploaded image.
Just lock it with
.lockMovementX = true;
.lockMovementY = true;
var canvas = new fabric.Canvas('canvas');
document.getElementById('file').addEventListener("change", function (e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function (f) {
var data = f.target.result;
fabric.Image.fromURL(data, function (img) {
var oImg = img.set({left: 50, top: 100,width:200,height:200, angle: 00}).scale(0.9);
oImg.lockMovementX = true;
oImg.lockMovementY = true;
canvas.add(oImg);
var a = canvas.setActiveObject(oImg);
});
};
reader.readAsDataURL(file);
var dataURL = canvas.toDataURL({
format: 'png',
opacity: 0.9
});
console.log("Canvas Image " + dataURL);
});
canvas{
border: 1px solid black;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.min.js"></script>
<canvas id="canvas" width="750" height="550"></canvas>
<input type="file" id="file">

Kinetic JS Image layering and Animation issue

I'm trying to rotate and animate my multiple image layers seperatly ontop of each other. The problem is when I call the animate rotate function on one of the images, my debugger says the image has no function rotate. Here is what I have got
var stage = new Kinetic.Stage({
container: 'container',
width: 300,
height: 300
});
var layer1 = new Kinetic.Layer();
var layer2 = new Kinetic.Layer();
var layer3 = new Kinetic.Layer();
var layer4 = new Kinetic.Layer();
var logo4 = new Image();
var logo3 = new Image();
var logo2 = new Image();
var logo1 = new Image();
var logoRing, logoCross, logoCentreRings, logoCentre;
var loadCount = 0;
logo4.onload = function() {
loadCount ++;
if(loadCount == 4&& !loaded){
loaded = true;
putOnStage();
}
};
logo3.onload = function() {
loadCount ++;
if(loadCount == 4&& !loaded){
loaded = true;
putOnStage();
}
};
logo2.onload = function() {
loadCount ++;
if(loadCount == 4&& !loaded){
loaded = true;
putOnStage();
}
};
logo1.onload = function() {
loadCount ++;
if(loadCount == 4 && !loaded){
loaded = true;
putOnStage();
}
};
var loaded = false;
logo4.src = "logo_ring.png";
logo3.src = "logo_cross.png";
logo2.src = "logo_centre_rings.png";
logo1.src = "logo_centre.png";
var logoPosX = 0;
var logoPosY = 0;
var logoWidth = 300;
var logoHeight = 300;
function putOnStage(){
logoRing = new Kinetic.Image({
x: 0,
y: 0,
image: logo4,
width: logoWidth,
height: logoHeight
});
layer4.add(logoRing);
stage.add(layer4);
logoCross = new Kinetic.Image({
x: 0,
y: 0,
image: logo3,
width: logoWidth,
height: logoHeight
});
layer3.add(logoCross);
stage.add(layer3);
logoCentreRings = new Kinetic.Image({
x: 0,
y: 0,
image: logo2,
width: logoWidth,
height: logoHeight
});
layer2.add(logoCentreRings);
stage.add(layer2);
logoCentre = new Kinetic.Image({
x: 0,
y: 0,
image: logo1,
width: logoWidth,
height: logoHeight
});
layer1.add(logoCentre);
stage.add(layer1);
}
var angularSpeed = 360 / 4;
var rotateCentreRings = new Kinetic.Animation(function(frame) {
var angleDiff = frame.timeDiff * angularSpeed / 1000;
logoCross.rotate(angleDiff);
}, layer2);
rotateCentreRings.start();
Which version of KineticJS are you using? Latest version deprecated rotateDeg in favour of simply making rotate use degrees instead of radians.
Additionally, you are creating and starting the animation before the images are loaded. This is why logoCross is undefined when you try to rotate it. Move that inside of putOnStage and it should work.
function putOnStage(){
logoRing = new Kinetic.Image({
x: 0,
y: 0,
image: logo4,
width: logoWidth,
height: logoHeight
});
layer4.add(logoRing);
stage.add(layer4);
logoCross = new Kinetic.Image({
x: 0,
y: 0,
image: logo3,
width: logoWidth,
height: logoHeight
});
layer3.add(logoCross);
stage.add(layer3);
logoCentreRings = new Kinetic.Image({
x: 0,
y: 0,
image: logo2,
width: logoWidth,
height: logoHeight
});
layer2.add(logoCentreRings);
stage.add(layer2);
logoCentre = new Kinetic.Image({
x: 0,
y: 0,
image: logo1,
width: logoWidth,
height: logoHeight
});
layer1.add(logoCentre);
stage.add(layer1);
var angularSpeed = 360 / 4;
var rotateCentreRings = new Kinetic.Animation(function(frame) {
var angleDiff = frame.timeDiff * angularSpeed / 1000;
logoCross.rotate(angleDiff);
}, layer2);
rotateCentreRings.start();
}

Categories