Loading image with Kineticjs - image

I'm having trouble loading a simple image into a layer. Sometimes it appears, others it doesn't.
<div id="container0" style="position:absolute; top:5px; left: 5px;"></div>
<script>
Layer = new Kinetic.Layer();
window.onload = function () {
stage = new Kinetic.Stage({ container: "container0", width: 1000, height: 500 });
stage.add(Layer);
var img = new Image();
img.src = "Images/Start.png"
Image= new Kinetic.Image({ x: 250, y: 150, width: 251, height: 231,image: img});
Layer.add(Image)
Layer.draw();
};
</script>
I guess it showing or not depends on if the image load time is quick enough, but I'm probably not doing it right.
Any help is appreciated. Thanks

Use image.onload:
img.onload = function(){
Image= new Kinetic.Image({ x: 0, y: 0, width: 251, height: 231,image: img});
layer.add(Image);
layer.draw();
}
http://jsfiddle.net/lavrton/WeVW4/1/

Related

Fabric js Hovering doesn't function

I have few elements (triangles) and I want to be able to highlight(setShadow) them as I hover above each one (mouse:over/mouse:move), and reset highlight when mouse not over.
I tried this, but it doesn't do anything. Below is my code:
var canvas = new fabric.Canvas('canvas');
var petal1 = new fabric.Triangle({
width: 200,
height: 300,
fill: '#DBDBDB',
left: 500,
top: 350,
angle: 200,
strokeLineJoin: 'round',
strokeWidth: 20,
stroke: '#DBDBDB'
});
var petal2 = new fabric.Triangle({
// same options as above
});
var petal3 = new fabric.Triangle({
// same options as above
});
canvas.on('mouse:over', function(e) {
e.target.set('fill', 'red');
canvas.renderAll();
});
canvas.on('mouse:out', function(e) {
e.target.set('fill', 'green');
canvas.renderAll();
});
canvas.add(petal1, petal2, petal3);
I added console.log(e.target);, but it printed nothing.
Your snippet works and check target before setting property to it.
DEMO
var canvas = new fabric.Canvas('canvas');
var options = {
width: 100,
height: 200,
fill: '#DBDBDB',
strokeLineJoin: 'round',
strokeWidth: 20,
stroke: '#DBDBDB'
};
var petal1 = new fabric.Triangle(options);
var petal2 = new fabric.Triangle(options);
var petal3 = new fabric.Triangle(options);
canvas.on('mouse:over', function(e) {
if(e.target){
e.target.set('fill', 'red');
canvas.requestRenderAll();
}
});
canvas.on('mouse:out', function(e) {
if(e.target){
e.target.set('fill', 'green');
canvas.requestRenderAll();
}
});
canvas.add(petal1, petal2, petal3);
canvas{
border:1px solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.7.0/fabric.js"></script>
<canvas id="canvas" width="300" height="300"></canvas>

FabricJS image object clipTo shape object issue

Why this clipTo method doesn't work on the latest fabricjs version, which you could resize the object container and the image inside it. Also you able to move the container object and image object.
var imgInstance = new fabric.Image(img, {
width: instanceWidth,
height: instanceHeight,
top: (canvas.getHeight() / 2 - instanceHeight / 2),
left: (canvas.getWidth() / 2 - instanceWidth / 2),
originX: 'left',
originY: 'top'
});
canvas.add(imgInstance);
imgInstance.clipTo = function(ctx) {
/* image clipping method doesn't work on latest fabricjs version*/
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
clippingRect.render(ctx);
ctx.restore();
};
http://jsfiddle.net/efmbrm4v/2/
Or is their another approach shape object inside is the image object.
There is some caching issue with the latest version of FabricJS. To get around that, you need to set objectCaching property to false for the rectangle object.
$(document).ready(function() {
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);
});
var canvas = new fabric.Canvas('myCanvas');
var clippingRect = new fabric.Rect({
left: 100,
top: 100,
width: 100,
height: 100,
fill: 'transparent',
opacity: 1,
objectCaching: false //<-- set this
});
canvas.add(clippingRect);
function handleImage(e) {
var reader = new FileReader();
reader.onload = function(event) {
var img = new Image();
img.onload = function() {
var instanceWidth, instanceHeight;
instanceWidth = img.width;
instanceHeight = img.height;
var imgInstance = new fabric.Image(img, {
width: instanceWidth,
height: instanceHeight,
top: (canvas.getHeight() / 2 - instanceHeight / 2),
left: (canvas.getWidth() / 2 - instanceWidth / 2),
originX: 'left',
originY: 'top'
});
canvas.add(imgInstance);
imgInstance.clipTo = function(ctx) {
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
clippingRect.render(ctx);
ctx.restore();
};
canvas.renderAll();
};
img.src = event.target.result;
};
reader.readAsDataURL(e.target.files[0]);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.13/fabric.min.js"></script>
<canvas id="myCanvas" width="400" height="300" style="border: 1px solid black"></canvas>
<br />
<label>Choose a File:</label>
<br/>
<br />
<input type="file" id="imageLoader" name="imageLoader" />
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>

Fabric toDataUrl with multiplier not working as expected

In my code I created method to clip images using fabric shapes. I have used stackoverflow answer for achieving this. Somehow after using this method I cannot render the canvas using default fabric canvas render method.
var img01URL = 'https://www.google.com/images/srpr/logo4w.png';
var img02URL = 'http://fabricjs.com/lib/pug.jpg';
var canvas = new fabric.Canvas('c');
document.getElementById('download').addEventListener('click', function() {
canvas.renderAll();
this.href = canvas.toDataURL({
format: 'png',
multiplier: 2
});
this.download = "test.png";
}, false);
var clipRect1 = new fabric.Rect({
originX: 'left',
originY: 'top',
angle: 90,
left: 195,
top: 0,
width: 200,
height: 200,
fill: '#DDD', /* use transparent for no fill */
strokeWidth: 1,
lockMovementX: true,
lockMovementY: true,
angle: 5,
stroke: 'red'
});
var pugImg = new Image();
pugImg.onload = function (img) {
var pug = new fabric.Image(pugImg, {
angle: 0,
width: 500,
height: 500,
left: 245,
top: 35,
scaleX: 0.3,
scaleY: 0.3,
clipName: 'pug',
clipTo: function(ctx) {
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
clipRect1.render(ctx);
ctx.restore();
}
});
canvas.add(pug);
};
pugImg.src = img02URL;
pugImg.setAttribute('crossOrigin', 'anonymous');
#c {
border:0px solid #ccc;
}
<script src="//cdn.bootcss.com/fabric.js/1.5.0/fabric.js"></script>
<canvas id="c" width="500" height="400"></canvas>
<a id="download">Download as image</a>
Your problem is the multiplier.
When using that kind of clipTo functions, you are setting the transform of canvas to plain. When rendering with canvas with multiplier, the base canvas transformation is scaled by the multiplier.
Your rect will be drawn without this transform ( because of setTransform(1,0,0,1,0,0) and will clip out the image.
Instead of setting the transform to [1,0,0,1,0,0] you should set to the invers of the current transformation of the object you are clipping.
var img01URL = 'https://www.google.com/images/srpr/logo4w.png';
var img02URL = 'http://fabricjs.com/lib/pug.jpg';
var canvas = new fabric.Canvas('c');
document.getElementById('download').addEventListener('click', function() {
var data = canvas.toDataURL({
format: 'png',
multiplier: 2
});
console.log(data);
//var img = document.getElementById('export');
//img.src = data;
}, false);
var clipRect1 = new fabric.Rect({
originX: 'left',
originY: 'top',
angle: 90,
left: 195,
top: 0,
width: 200,
height: 200,
fill: '#DDD', /* use transparent for no fill */
strokeWidth: 1,
lockMovementX: true,
lockMovementY: true,
stroke: 'red',
angle: 5
});
var pugImg = new Image();
pugImg.onload = function (img) {
var pug = new fabric.Image(pugImg, {
angle: 0,
width: 500,
height: 500,
left: 245,
top: 35,
scaleX: 0.3,
scaleY: 0.3,
clipName: 'pug',
clipTo: function(ctx) {
ctx.save();
var myMatrix = this.calcTransformMatrix();
myMatrix = fabric.util.invertTransform(myMatrix);
ctx.transform.apply(ctx, myMatrix);
clipRect1.render(ctx);
ctx.restore();
}
});
canvas.add(pug);
};
pugImg.src = img02URL;
#c {
border:0px solid #ccc;
}
<script src="//www.deltalink.it/andreab/fabric/fabric.js"></script>
<canvas id="c" width="500" height="400"></canvas>
<a id="download">Download as image</a>
<img id="export" >

KineticJS image drag, rotate and scale

Im still learning but it seems everything I do does not work in getting the images to also be rotated along with being scaled and dragged. Can someone please help me out with this. Here is the code I am working with...
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body onmousedown="return false;">
<div style="height:1024px; width: 1280px; background-image: url(http://www.designmyprofile.com/images/graphics/backgrounds/background0172.jpg)" id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.2.min.js"></script>
<script>
function update(activeAnchor) {
var group = activeAnchor.getParent();
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var image = group.get('.image')[0];
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
// update anchor positions
switch (activeAnchor.getName()) {
case 'topLeft':
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
break;
case 'bottomRight':
bottomLeft.setY(anchorY);
topRight.setX(anchorX);
break;
case 'bottomLeft':
bottomRight.setY(anchorY);
topLeft.setX(anchorX);
break;
}
image.setPosition(topLeft.getPosition());
var width = topRight.getX() - topLeft.getX();
var height = bottomLeft.getY() - topLeft.getY();
if(width && height) {
image.setSize(width, height);
}
}
function addAnchor(group, x, y, name) {
var stage = group.getStage();
var layer = group.getLayer();
var anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: '#666',
fill: '#ddd',
strokeWidth: 2,
radius: 8,
name: name,
draggable: true,
dragOnTop: false
});
anchor.on('dragmove', function() {
update(this);
layer.draw();
});
anchor.on('mousedown touchstart', function() {
group.setDraggable(false);
this.moveToTop();
});
anchor.on('dragend', function() {
group.setDraggable(true);
layer.draw();
});
// add hover styling
anchor.on('mouseover', function() {
var layer = this.getLayer();
document.body.style.cursor = 'pointer';
this.setStrokeWidth(4);
layer.draw();
});
anchor.on('mouseout', function() {
var layer = this.getLayer();
document.body.style.cursor = 'default';
this.setStrokeWidth(2);
layer.draw();
});
group.add(anchor);
}
function loadImages(sources, callback) {
var images = {};
var loadedImages = 0;
var numImages = 0;
for(var src in sources) {
numImages++;
}
for(var src in sources) {
images[src] = new Image();
images[src].onload = function() {
if(++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
function initStage(images) {
var stage = new Kinetic.Stage({
container: 'container',
width: 1280,
height: 1024
});
var darthVaderGroup = new Kinetic.Group({
x: 270,
y: 100,
draggable: true
});
var yodaGroup = new Kinetic.Group({
x: 100,
y: 110,
draggable: true
});
var layer = new Kinetic.Layer();
/*
* go ahead and add the groups
* to the layer and the layer to the
* stage so that the groups have knowledge
* of its layer and stage
*/
layer.add(darthVaderGroup);
layer.add(yodaGroup);
stage.add(layer);
// darth vader
var darthVaderImg = new Kinetic.Image({
x: 0,
y: 0,
image: images.darthVader,
width: 200,
height: 138,
name: 'image'
});
darthVaderGroup.add(darthVaderImg);
addAnchor(darthVaderGroup, 0, 0, 'topLeft');
addAnchor(darthVaderGroup, 200, 0, 'topRight');
addAnchor(darthVaderGroup, 200, 138, 'bottomRight');
addAnchor(darthVaderGroup, 0, 138, 'bottomLeft');
darthVaderGroup.on('dragstart', function() {
this.moveToTop();
});
// yoda
var yodaImg = new Kinetic.Image({
x: 0,
y: 0,
image: images.yoda,
width: 93,
height: 104,
name: 'image'
});
yodaGroup.add(yodaImg);
addAnchor(yodaGroup, 0, 0, 'topLeft');
addAnchor(yodaGroup, 93, 0, 'topRight');
addAnchor(yodaGroup, 93, 104, 'bottomRight');
addAnchor(yodaGroup, 0, 104, 'bottomLeft');
yodaGroup.on('dragstart', function() {
this.moveToTop();
});
stage.draw();
}
var sources = {
darthVader: 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg',
yoda: 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg'
};
loadImages(sources, initStage);
</script>
</body>
</html>

KineticJS draw Image inside a circle

I am trying to place an image inside a circle using:
var gArrow2 = new Image();
gArrow2.src = '../../Content/images/green_s.png';
var circle2 = new Kinetic.Circle({
drawFunc: function(canvas) {
var context = canvas.getContext();
context.drawImage(gArrow2, 256, 256, 11, 23);
context.beginPath();
context.arc(256, 256, this.getRadius(), 0, 2 * Math.PI, false);
context.lineWidth = this.getStrokeWidth();
context.strokeStyle = this.getStroke();
context.stroke();
},
x: 256,
y: 256,
radius: 70,
stroke: '#00ffff',
strokeWidth: 4,
opacity: 0.5
});
layer2.add(circle2);
It does not work! I would appreciate your suggestions, thanks in advance.
You have to give gArrow2 time to load. You do this through gArrow2.onload.
Always put gArrow2.src after it's onload.
Then put any code that uses gArrow2 inside the onload function.
[Edit to add layer2.draw()]
I plugged your code in and got it working.
Looks like all that was needed was layer2.draw();
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/Qgnkx/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.3.3-beta.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 600,
height: 600
});
var layer2 = new Kinetic.Layer();
stage.add(layer2);
var gArrow2 = new Image();
gArrow2.onload=function(){
var circle2 = new Kinetic.Circle({
drawFunc: function(canvas) {
var context = canvas.getContext();
context.drawImage(gArrow2, 256, 256, 11, 23);
context.beginPath();
context.arc(256, 256, this.getRadius(), 0, 2 * Math.PI, false);
context.lineWidth = this.getStrokeWidth();
context.strokeStyle = this.getStroke();
context.stroke();
},
x: 256,
y: 256,
radius: 70,
stroke: '#00ffff',
strokeWidth: 4,
opacity: 0.5
});
layer2.add(circle2);
layer2.draw();
}
gArrow2.src = 'http://dl.dropbox.com/u/139992952/stackoverflow/house1.jpg';
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>

Resources