Image object color change using kineticjs - image

I am trying to convert an image to another color using kineticjs, actually my image will be on a layer and also a png one can i change only the image objects color? any help will be very greatful

You can replace non-transparent pixels with a new color using compositing.
In particular source-atop compositing will replace all existing non-transparent pixels with any color you draw.
KineticJS does not currently offer compositing out-of-the-box, but you can easily use an html5 Canvas element to do the compositing and then use that element as an image source for a Kinetic.Image element.
Here's example code and a Demo:
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
var canvas=document.createElement('canvas');
var ctx=canvas.getContext('2d');
var kImage;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/flower.png";
function start(){
cw=canvas.width=img.width;
ch=canvas.height=img.height;
ctx.drawImage(img,0,0);
kImage=new Kinetic.Image({
image:canvas,
width:img.width,
height:img.height,
draggable:true,
});
layer.add(kImage);
layer.draw();
document.getElementById('makeGreen').onclick=function(){
ctx.globalCompositeOperation='source-atop';
ctx.fillStyle='lightgreen';
ctx.fillRect(0,0,cw,ch);
layer.draw();
};
document.getElementById('makeOriginal').onclick=function(){
ctx.globalCompositeOperation='source-over';
ctx.drawImage(img,0,0);
layer.draw();
};
}
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.1.0.min.js"></script>
<button id=makeGreen>Green</button>
<button id=makeOriginal>Original</button>
<div id="container"></div>

Related

KineticJS - How can we move an image behind a mask without moving mask

Is it possible to move an image behind a mask without moving the mask itself ? I am looking for an operation which allow to move an image behind a mask and it should be accurate and smooth.
The best answer I am looking is to mask an Kinetic.Image object. Kinetic.Image is draggable and need to worry about it's movement. Please let me know if it's really possible to mask Kinetic.Image Object ?
A Demo: http://jsfiddle.net/m1erickson/u28MS/
Use a Kinetic.Shape to get access to the canvas context and then create a clipping region.
Create a new Kinetic.Shape
Define your non-rectangular path in the shape
Call clip() to restrict drawing to that path.
Draw the image into the clipping region.
Give the image x & y properties so that the image can be draw
Here's what that looks like in code:
// create a Kinetic.Shape which gives you access
// to a context to draw on
clippingShape = new Kinetic.Shape({
sceneFunc: function(context) {
// define your path here
// context.beginPath(); ...
// make your path a clipping region
context.clip();
// draw the image inside the clipping region
// img.x & img.y are offsets which can be used
// to "drag" the image around the clipping region
context.drawImage(img,img.x,img.y);
// KineticJS specific context method
context.fillStrokeShape(this);
},
stroke: 'black',
strokeWidth: 4,
listening:false
});
Listen for mouse events on the stage to cause the image to reposition when drawn in the Shape.
In mousedown: Save the mouse position and set a flag indicating the drag has begun.
In mousemove: Calc how much the mouse has moved and offset the image's x/y by that distance.
In mouseup: clear the dragging flag since the drag is over.
The mouse event handlers look like this:
var isdown=false;
stage.getContent().onmousedown=function(e){
var pos=stage.getPointerPosition();
img.lastX=parseInt(pos.x);
img.lastY=parseInt(pos.y);
isdown=true;
};
stage.getContent().onmouseup=function(e){
isdown=false;
};
stage.getContent().onmousemove=function(e){
if(!isdown){return;}
var pos=stage.getPointerPosition();
var mouseX=parseInt(pos.x);
var mouseY=parseInt(pos.y);
var dx=mouseX-img.lastX;
var dy=mouseY-img.lastY;
img.lastX=mouseX;
img.lastY=mouseY;
img.x+=dx;
img.y+=dy;
layer.draw();
};
[ Previous version of answer -- replaced with new answer above after questioners commments ]
This kind of clipping is traditionally done with a foreground image that contains a transparent "viewport" which lets the user see a portion of the background image beneath.
A Demo: http://jsfiddle.net/m1erickson/2f9yu/
Create a draggable background image on a bottom layer:
// create a background layer
var bottomLayer=new Kinetic.Layer();
stage.add(bottomLayer);
// put a draggable image on the background layer
var city=new Kinetic.Image({ image:bk,x:0,y:0,draggable:true,width:700,height:440, });
bottomLayer.add(city);
bottomLayer.draw();
Create a non-draggable foreground image on a top layer.
The top image has a transparent "viewport".
Important: the top layer does not listen for events, so dragging moves the bottom image, not the top image.
// create a top layer that does not respond to mouse events
// any mouse events will filter down to the background image
// this enables the background to be dragged even while behind the top image
var topLayer=new Kinetic.Layer({listening:false,});
stage.add(topLayer);
// create a top image with transparent pixels
// used as a viewport to see a portion of the bottom image
var mirror=new Kinetic.Image({ image:viewport,x:0,y:0 });
topLayer.add(mirror);
topLayer.draw();
Example code:
<!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://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.1.min.js"></script>
<style>
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:300px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 300
});
var layer = new Kinetic.Layer();
stage.add(layer);
var bottomLayer=new Kinetic.Layer();
stage.add(bottomLayer);
var topLayer=new Kinetic.Layer({listening:false,});
stage.add(topLayer);
var loadedCount=0;
//
var bk=new Image();
bk.onload=start;
bk.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/desert1.jpg";
//
var viewport=new Image();
viewport.onload=start;
viewport.src="https://dl.dropboxusercontent.com/u/139992952/multple/car4.png";
function start(){
if(++loadedCount<2){return;}
var city=new Kinetic.Image({ image:bk,x:0,y:0,draggable:true,width:700,height:440, });
bottomLayer.add(city);
bottomLayer.draw();
var mirror=new Kinetic.Image({ image:viewport,x:0,y:0 });
topLayer.add(mirror);
topLayer.draw();
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>Drag to move the background image in the mirror</h4>
<div id="container"></div>
</body>
</html>

KineticJS rotating/animating text

I have this fiddle where I have text arranged in a circle, I would like now to animate it and rotate the text in a clockwise/counter clockwise motion.
Every animation demo I have seen uses a container as the starting point however all the examples i could find about manipulating text in a circular arrangement have all started with the element. I have tried 100's of variations trying to get this working but I am either missing something or it's not possible with the construction i have used thus far.
Here is the fiddle for the circular text I have so far:
http://jsfiddle.net/jamesburt/Sa2G8/
<canvas id="canvas1" width="500" height="500"></canvas>
var can = document.getElementById('canvas1');
var ctx = can.getContext('2d');
Where as the animation examples start off with:
<div id="container"></div>
var stage = new Kinetic.Stage({container: 'container'});
I'm open to any ideas / rewrites needed as ultimately my goal is an animated text circle.
Also if this is easily accomplished in an alternative to KineticJS I'd be interested in trying that out.
Here is a demo I made using KineticJS: http://jsfiddle.net/Moonseeker/Xf7hp/
var stage = new Kinetic.Stage({
container: 'container',
width: 500,
height: 500
});
var layer = new Kinetic.Layer();
var myText = "My text in a circle. ";
var centerCoords = {x:250, y:250};
for(var i=0;i<myText.length;i++){
var rotation = i*360/myText.length;
var oneChar = new Kinetic.Text({
x: centerCoords.x,
y: centerCoords.y,
text: myText[i],
fontSize: 30,
fontFamily: 'Calibri',
fill: 'green',
offset: {x:0, y:100},
rotationDeg: rotation
});
layer.add(oneChar);
}
// add the layer to the stage
stage.add(layer);
var angularSpeed = Math.PI / 2;
var anim = new Kinetic.Animation(function(frame){
var angleDiff = frame.timeDiff * angularSpeed / 1000;
for(var i=0;i<layer.children.length;i++){
layer.children[i].rotate(angleDiff);
};
}, layer);
anim.start();
You can rotate at every direction or speed you wish, you can change the style of the circle.
You should be able to use layer.find('Text').each() instead of the for-loop for looping through the text to rotate but the KineticJS library at jsfiddle seems outdated as it doesn't know the find method.
One efficient way:
Render your text-around-a-circle on an offscreen canvas.
Save that offscreen canvas as an image using .toDataURL
Create a Kinetic.Image from that offscreen image.
You can then efficiently rotate/animate the Kinetic.Image as you need.

How To: Draw (HTML5) Video into (Custom) Canvas Shape with KinecticJS

Here's my example: http://jsbin.com/urofan/7/edit
I would like to draw the video into a custom shape, not in a rectangle shape, is that possible right now? (PS: The shape is draggable) All I found in StackO or in the web are for rectangular drawings...
In the future, the shape will be a circle with adjustable radius and position (draggable and resizable).
Thanks for your help.
Allan.
You can contain an image (video frame grab) into a path using the clip method.
First define the path you want the video frame to be contained in.
Note that you don’t have to do fill/stroke.
context.beginPath();
context.moveTo(200, 50);
context.lineTo(420, 80);
context.lineTo(250, 400);
context.lineTo(40, 80);
context.closePath();
Next, create a clipping path from your defined path.
Everything drawn after this will be clipped inside your clipping path.
context.clip();
Finally, draw a frame grab of the video and drawImage into the clipping path.
The frame grab will only appear inside your clipping path.
context.drawImage(0,0,canvas.width,canvas.height);
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/aMW74/
<!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://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.1.min.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 500,
height: 500
});
var layer = new Kinetic.Layer();
stage.add(layer);
var img=document.createElement("img");
img.onload=function(){
drawClippedImage(img);
}
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/KoolAidMan.png";
function drawPathForClipping(context){
context.beginPath();
context.moveTo(200, 50);
context.lineTo(420, 80);
context.lineTo(250, 400);
context.lineTo(40, 80);
context.closePath();
}
function drawClippedImage(img){
var shape = new Kinetic.Shape({
id: 'shape',
drawFunc: function(canvas) {
var context = canvas.getContext();
// define the path that will be used for clipping
drawPathForClipping(context);
// make the last path a clipping path
context.clip();
// draw a clipped image (frame grab)
context.drawImage(img,0,0,img.width,img.height);
// styling, draw the clip path for real as a border
drawPathForClipping(context);
canvas.stroke(this);
},
stroke: 'black',
strokeWidth: 4,
draggable: true
});
// add the shape shape to the layer
layer.add(shape);
layer.draw();
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>

set offset/position of polygon to rotate

I'm trying to perform a crop of a background image with different shapes.
The objective is to move/rotate around the polygons, crop the background with the shape of the polygon, somehow plot the cropped image over the polygon and save the cropped polygon as a new image.
So far I can drag and rotate(arrow keys) the polygons over the canvas.
First, I'm having problems rotating the polygons: I want them to rotate on its center.
And second, cropping the background with the polygon shape.
Here's a link to a jsbin: http://jsbin.com/efoqav/1/edit
Any ideas?
Thanks.
Here’s how to use your Kinetic polygon to clip a background image
First, use the background image as a fillPattern in your Kinetic polygon. Make the fill non-repeating and offset the pattern by the x/y position of the polygon:
var hexagon = new Kinetic.RegularPolygon({
x: 50,
y: 50,
sides: 6,
radius: 50,
fillPatternImage: img,
fillPatternRepeat: "no-repeat",
fillPatternOffset: [-50,-50],
stroke: 'black',
strokeWidth: 3,
draggable: true
});
Then when th user drags the polygon (or you move it with keystrokes), reposition the fillPatternOffset by the current position of the polygon. Essentially, the fill inside the polygon will “follow” the dragging polygon.
hexagon.on('dragmove', function() {
var position=this.getAbsolutePosition();
var x=position.x;
var y=position.y
this.setFillPatternOffset(x,y);
layer.draw();
});
To rotate your polygon around its center (centerX,centerY), do this trigonometry to each of your Kinetic Polygon Points and then reset the shape with yourKineticPolygon.setPoints.
// if the rotation angle is degrees, you must first convert it to radians:
var radianAngle = degreeAngle * Math.PI/180;
// modify each of your polygon points like this
var dx = centerX – pointX;
var dy = centerY – pointY;
var radius = Math.sqrt( dx*dx + dy*dy);
var rotatedX = centerX + radius * Math.cos(radianAngle);
var rotatedY = centerY + radius * Math.cos(radianAngle);
And to save the stage to an image, you can use stage.toDataURL like this:
// hide the background since you're just interested in the clip
background.hide();
// this saves the stage (your clipped polygon) to an image url
stage.toDataURL({
// just like an image object, you need an onload-ish callback
callback: function(dataUrl){
// testing -- put the image in an html img
var imgElement=document.getElementById("saved");
imgElement.src=dataUrl;
// reshow the background
background.show();
}
});
Here’s code and a Fiddle: http://jsfiddle.net/m1erickson/eQYB8/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.1.min.js"></script>
<style>
body{ background-color: ivory; padding:20px;}
img{border:1px solid red;}
</style>
<script>
$(function(){
// this just generates a sample image
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
var count=0;
canvas.width=300;
canvas.height=300;
for(var x=0;x<10;x++){
for(var y=0;y<10;y++){
ctx.beginPath();
ctx.arc(x*30+15,y*30+15,15,0,Math.PI*2,false);
ctx.fillText(count++,x*30+11,y*30+18);
ctx.stroke();
}
}
var img=new Image();
img.onload=function(){
draw();
}
img.src=canvas.toDataURL();
function draw(){
var stage = new Kinetic.Stage({
container: 'container',
width: 300,
height: 300
});
var layer = new Kinetic.Layer();
stage.add(layer);
var background = new Kinetic.Image({
x: 0,
y: 0,
image: img,
width: 300,
height: 300,
opacity:.25
});
layer.add(background);
var hexagon = new Kinetic.RegularPolygon({
x: 50,
y: 50,
sides: 6,
radius: 50,
fillPatternImage: img,
fillPatternRepeat: "no-repeat",
fillPatternOffset: [-50,-50],
stroke: 'black',
strokeWidth: 3,
draggable: true
});
layer.add(hexagon);
layer.draw();
hexagon.on('dragmove', function() {
var position=this.getAbsolutePosition();
var x=position.x;
var y=position.y
this.setFillPatternOffset(x,y);
layer.draw();
});
$("#save").click(function(){
background.hide();
stage.toDataURL({
callback: function(dataUrl){
var imgElement=document.getElementById("saved");
imgElement.src=dataUrl;
background.show();
}
});
});
}
}); // end $(function(){});
</script>
</head>
<body>
<button id="save">Save</button><br><br>
<p>Drag the Polygon to your desired clip</p><br>
<div id="container"></div><br>
<p>Saved results without background</p>
<img id="saved" width=300 height=300/>
</body>
</html>

Canvas with a image to jpeg

I want to get a .jpg on a canvas, add a rectangle and a String, which is working very good. After that I want to create a jpg out of the canvas, which works fine but the jpg of the canvas does only show the rectangle and the String. Quick Code-example - i know its a ugly canvas - just testing ;)
<!DOCTYPE html>
<html>
<body>
<canvas id="meinCanvas" width="600" height="600" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
</body>
<script type="text/javascript">
var canv = document.getElementById("meinCanvas");
var context = canv.getContext("2d");
context.fillStyle = "#000000";
context.fillRect(10,10, 200, 100);
var img = new Image();
img.onload = function() {
context.drawImage(img, 300, 300);
};
img.src="one.jpg";
context.font = "bold 12px sans-serif";
context.fillText("test", 500, 500);
imgsr = canv.toDataURL("image/jpeg");
document.write('<img src="' +imgsr +'"/>');
</script>
</html>
}
In the upper part (the canvas) the img is shown properly, but in the .jpeg beneth it the img is not shown. Help would be great. thanks.
Image is not loaded yet when you save it.
Put the toDataUrl in img.onload or link it to an event or timer

Resources