How to make KineticJs custom shape - html

I am trying to make KineticJs html 5 custom shape.
But it is not working in Google chrome. Not draggable in Firefox and also shape are not same in size.
Can anybody tell why?
live code http://jsfiddle.net/prantor19/wGE2a/8/
var stage = new Kinetic.Stage({
container: 'canvas-container',
width: 500,
height: 500,
});
var layer = new Kinetic.Layer();
drawWindow = function(canvas) {
var context = canvas.getContext();
context.beginPath();
context.moveTo(this.attrs.x,this.attrs.y);
context.lineTo(this.attrs.width,this.attrs.y);
context.lineTo(this.attrs.width,this.attrs.height);
context.lineTo(this.attrs.x,this.attrs.height);
context.closePath();
context.clip();
context.drawImage(img,this.attrs.img_x,this.attrs.img_y);
}
img = document.createElement('img');
img.src= "http://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Nature_reserve_Kladrubska_hora_in_summer_2011_(17).JPG/1024px-Nature_reserve_Kladrubska_hora_in_summer_2011_(17).JPG";
var window1 = new Kinetic.Shape({
drawFunc: drawWindow,
x: 0,
y: 0,
width: 100,
height: 100,
img:img,
img_x:0,
img_y:0,
draggable: true
});
var window2 = new Kinetic.Shape({
drawFunc: drawWindow,
x: 10,
y: 60,
width: 100,
height: 100,
img:img,
img_x:-250,
img_y:0,
draggable: true
});
pointercursor = function() {
document.body.style.cursor = 'pointer';
}
defaultCursor = function() {
document.body.style.cursor = 'default';
}
window1.on('mouseover',pointercursor );
window1.on('mouseout', defaultCursor);
window2.on('mouseover',pointercursor );
window2.on('mouseout', defaultCursor);
layer.add(window1);
layer.add(window2);
stage.add(layer);

Your script has errors in it
Unable to get image data from canvas because the canvas has been tainted by cross-origin data. kinetic-v4.3.2-beta.js:4365
Uncaught Error: SecurityError: DOM Exception 18
Chrome refuse to work with cross domain images on cavas.
For dragging, you need to add this set stroke for the shape
stroke: 'black',
and at the end of drawFunc
canvas.fillStroke(this);
Here is the my working version from yours
http://jsfiddle.net/W7SGT/

You should be using the canvas renderer when drawing a custom shape in KienticJS, or else it has no way to handle the events on the shape. Here's a tutorial on custom shapes:
http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-shape-tutorial/
you might also take a look at the Kinetic.Image shape to see how it handles images specifically:
https://github.com/ericdrowell/KineticJS/blob/master/src/shapes/Image.js

Related

How to rotate image using HTML5 canvas library like: KineticJS or KonvaJS?

I am able to rotate a rectangle (shape) using KineticJS library I would like now to rotate an image, How I can do that?
var stage = new Kinetic.Stage({
container: 'container',
width: 530,
height: 530
});
var layer = new Kinetic.Layer();
var bg = new Kinetic.Image({
x: 0,
y: 0,
width: 530,
height: 530,
fill: '#D7D7D7',
});
/****************** image **********************/
//sticker.setRotationDeg(90);
var imageObj = new Image();
function sticker(v) {
if(!imageObj.src){
var sticker = new Kinetic.Image({
x: 280,
y: 300,
image: imageObj,
draggable: true
});
layer.add(sticker);
}
imageObj.src = 'http://cdn.sstatic.net/photo/img/apple-touch-icon.png';
layer.draw();
}
/****************** image **********************/
layer.add(bg);
stage.add(layer);
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.4.2.min.js"></script>
<div id="container"></div>
<input type="button" value="ShowSticker" onclick="sticker();"> click show sticker
<input type="button" value="rotate"> up + 5
I want to Click The rotation
step 1 click button show sticker
step 2 click button rotate
Each time you press + 5
or see web : http://jsfiddle.net/m1erickson/Z6Yg8/
As I have understood from you that you want to rotate an image, here is the following:
First I suggest you to use KonvaJS library which is forked from KineticJS but is supported by a community, as now KeniticJS is no longer supported.
In order to rotate in image you need to load it into the layer:
imageObj.onload = function() {
var yoda = new Konva.Image({
x: 50,
y: 50,
image: imageObj,
width: 106,
height: 118,
name: "yoda"
});
And then rotate it:
$("#rotate").click(function () {
layer.find('Image').rotate(500 * Math.PI / 180);
layer.draw();
});
Here is a full example

Crop an image and then apply filter Kinetic

I am using Kinetic for some image processing. What happens is that I crop my image and then by clicking a button I want to make it black and white. For some reason the simple setFilter function is not working in this case, when you do crop first.
This is the code for cropping:
layer.removeChildren();
layer.clear();
image = new Kinetic.Image({
image: canvasImage,
x: (canvasWidth/2-theSelection.w/2),
y: (canvasHeight/2-theSelection.h/2),
width: theSelection.w,
height: theSelection.h,
crop: [theSelection.x, theSelection.y, theSelection.w, theSelection.h],
name: "image_tmp"
});
layer.add(image);
stage.draw();
And here is the function I decided to use for applying the filter:
var imgPixels = ctx.getImageData(xx, yy, imgW, imgH);
for(var y = 0; y < imgPixels.height; y++){
for(var x = 0; x < imgPixels.width; x++){
var i = (y * 4) * imgPixels.width + x * 4;
var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
imgPixels.data[i] = avg;
imgPixels.data[i + 1] = avg;
imgPixels.data[i + 2] = avg;
}
}
ctx.putImageData(imgPixels, xx, yy, 0, 0, imgPixels.width, imgPixels.height);
So now I get my cropped image with the filter, but if I want to continue doing something to the image object, I am getting:
TypeError: a.getType is not a function
I think also that the image object I used to use in my code, is now like undefined.
So for example I want after the filter to do layer.add(image) and I want image variable to be the new black and white one and not the old one.
So does anyone have an idea what is the problem, or how can I make the new imgPixels to be the same as my image. Thanks in advance
Is there any reason you didn't use the Kinetic.Filters.Grayscale filter?
Here are 2 ways you can do it:
1) Use setFilter (it works!)
var imageObj = new Image();
imageObj.onload = function() {
var yoda = new Kinetic.Image({
x: 200,
y: 50,
image: imageObj,
crop: [0, 0, 50, 100]
});
// add the shape to the layer
layer.add(yoda);
// add the layer to the stage
stage.add(layer);
yoda.setFilter(Kinetic.Filters.Grayscale);
layer.draw();
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
2) Set the filter property on the image beforehand
var imageObj = new Image();
imageObj.onload = function() {
var yoda = new Kinetic.Image({
x: 200,
y: 50,
image: imageObj,
crop: [0, 0, 50, 100],
filter: Kinetic.Filters.Grayscale
});
// add the shape to the layer
layer.add(yoda);
// add the layer to the stage
stage.add(layer);
//yoda.setFilter(Kinetic.Filters.Grayscale);
//layer.draw();
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
Either way you don't need to add any new images, the original Kinetic.Image is filtered black & white.
UPDATE
Open this link: http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-image-tutorial/
And copy and paste this code, replacing all the code in the link. It's working fine for me..
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<button id="crop">Crop</button>
<button id="gray">Grayscale</button>
<button id="both">Both</button>
<div id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.0.min.js"></script>
<script defer="defer">
var yoda;
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function() {
yoda = new Kinetic.Image({
x: 200,
y: 50,
image: imageObj,
width: 106,
height: 118
});
// add the shape to the layer
layer.add(yoda);
// add the layer to the stage
stage.add(layer);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
document.getElementById('crop').addEventListener('click', function() {
yoda.setCrop([20, 20, 50, 50]);
layer.draw();
});
document.getElementById('gray').addEventListener('click', function() {
yoda.setFilter(Kinetic.Filters.Grayscale);
layer.draw();
});
document.getElementById('both').addEventListener('click', function() {
yoda.setCrop([20, 20, 50, 50]);
yoda.setFilter(Kinetic.Filters.Grayscale);
layer.draw();
});
</script>
</body>
</html>

Moving an image in an canvas on page load

Demo
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function() {
var yoda = new Kinetic.Image({
x: 200,
y: 50,
image: imageObj,
width: 106,
height: 118
});
// add the shape to the layer
layer.add(yoda);
// add the layer to the stage
stage.add(layer);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
var amplitude = 150;
var period = 2000;
// in ms
var centerX = stage.getWidth() / 2;
var anim = new Kinetic.Animation(function(frame) {
yoda.setX(amplitude * Math.sin(frame.time * 2 * Math.PI / period) + centerX);
}, layer);
anim.start();
How would I have the yoda image animate from left to right, say 50px, once on page load? Is it possible to do this with easing as well? Very new to canvas, thanks for any help. Would this be better suited to be left to jQuery instead?
If you look at console you'll see that yoda is not defined. This is happening because image.onload is a function and variables created inside a function are visible only inside that function. So you need to create yoda outside a function.
Also start the animation only after the image is loaded.
Modified Fiddle

add image as tooltip for rectangle on canvas

I have a grid and I'm looking to basically add a tooltip Image for each rectangle in the grid. Basically, first I need to be able to add an image to the canvas on the rectangle mouse over event. Eventually each rectangle would have it's own image so I need to keep track of the rectangles...do I add them to an array?
Here is my fiddle for what I've got so far:
http://jsfiddle.net/marseilles84/7ZzTh/1/
Here is a sample image source to use:
'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
<div id="container"></div>​
var stage = new Kinetic.Stage({
container: 'container',
width: 1000,
height: 500
});
var layer = new Kinetic.Layer();
for (var i=0; i<7; i++)
{
for(c=0; c<18; c++)
{
var colorPentagon = new Kinetic.Rect({
x: (45*c),
y: 45*i,
width:40,
height:40,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: true
});
colorPentagon.on('mouseover touchstart', function() {
//code here
});
layer.add(colorPentagon);
}
}
stage.add(layer);
http://jsfiddle.net/7ZzTh/2/
This is probably more of what you're looking for.
colorPentagon.on('mouseover touchstart', function() {
var userPos = stage.getUserPosition();
yoda.setPosition(userPos.x,userPos.y);
layer.add(yoda);
layer.draw();
});
colorPentagon.on('mouseout touchstart', function() {
yoda.remove();
layer.draw();
});
At the beginning you want:
var imageObj = new Image();
var yoda = new Kinetic.Image({
x: 0,
y: 0,
image: imageObj,
width: 106,
height: 118
});
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';

Html 5 canvas update with KinetickJS

I am using KinetickJS to draw images on screen.
I have a layer on the stage, and recieve 1000 of images in base64 format.
First I try to draw them with Kinetic
Example 1, works fine BUT after 1000 of images when I try to drag or do something with layer it became veeeeeeeery slow.So I try next example
var imageObj = new Image();
imageObj.onload = function () {
var image = new Kinetic.Image({
x: imageInfo.LocationX,
y: imageInfo.LocationY,
image: imageObj,
width: imageInfo.Width,
height: imageInfo.Height,
name: "Update"
});
layer.add(image);
layer.draw();
};
imageObj.src = "data:image/jpeg;base64," + imageInfo.Image;
Example 2, but in this case canvas began blinking for each update
var imageObj = new Image();
imageObj.onload = function () {
var canvas = layer.canvas;
var context = canvas.getContext('2d');
// context.globalCompositeOperation = "destination-over";
context.drawImage(imageObj, imageInfo.LocationX, imageInfo.LocationY);
};
imageObj.src = "data:image/jpeg;base64," + imageInfo.Image;
So do you have any ideas how to make it faster and/or disable blinking?
The newest KineticJS 4.3 speeds up dragging and other functionality quite a lot. This would probably fix your problem.
http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.3.0.min.js