How to clear & save canvas layer as image using javascript - javascript

I am trying to paint in canvas using kinetic-v4.7.2.min.js. It successfully draw lines when user touch that layer. I am using jsFiddle for this feature.
How can i clear this ractangle layer & how can i save that layer of container as an image?
JSFiddle
// create a stage and a layer
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
// an empty stage does not emit mouse-events
// so fill the stage with a background rectangle
// that can emit mouse-events
var background = new Kinetic.Rect({
x: 0,
y: 0,
width: stage.getWidth(),
height: stage.getHeight(),
fill: 'white',
stroke: 'black',
strokeWidth: 1,
})
layer.add(background);
layer.draw();
// a flag we use to see if we're dragging the mouse
var isMouseDown = false;
// a reference to the line we are currently drawing
var newline;
// a reference to the array of points making newline
var points = [];
// on the background
// listen for mousedown, mouseup and mousemove events
background.on('mousedown', function () {
onMousedown();
});
background.on('mouseup', function () {
onMouseup();
});
background.on('mousemove', function () {
onMousemove();
});
// On mousedown
// Set the isMouseDown flag to true
// Create a new line,
// Clear the points array for new points
// set newline reference to the newly created line
function onMousedown(event) {
isMouseDown = true;
points = [];
points.push(stage.getMousePosition());
var line = new Kinetic.Line({
points: points,
stroke: "green",
strokeWidth: 5,
lineCap: 'round',
lineJoin: 'round'
});
layer.add(line);
newline = line;
}
// on mouseup end the line by clearing the isMouseDown flag
function onMouseup(event) {
isMouseDown = false;
}
// on mousemove
// Add the current mouse position to the points[] array
// Update newline to include all points in points[]
// and redraw the layer
function onMousemove(event) {
if (!isMouseDown) {
return;
};
points.push(stage.getMousePosition());
newline.setPoints(points);
// use layer.drawScene
// this is faster since the "hit" canvas is not refreshed
layer.drawScene();
}
Any help would be appreciated!!
Thanks.

Using toDataURL() method:
DEMO
$('button').on('click', function () {
var img = $('.kineticjs-content').find('canvas').get(0).toDataURL("image/png");
$('body').prepend('<img src="' + img + '">');
});

Related

Drag and drop inside an image with kineticjs

I want to drop the star on a tree and detect which tree the star has been dropped on so I can highlight and select it eventually. But I couldn't get more than just moving the star.
I chose for kineticjs because it works with touchscreen so I don't want to use something else if possible. (unless it works with both touchscreen and mouse too)
This is my javascript:
<script defer="defer">
function drawImage(imageObj) {
var stage = new Kinetic.Stage({
container: "star",
width: 900,
height: 500
});
var layer = new Kinetic.Layer();
// star
var star = new Kinetic.Image({
image: imageObj,
x: 376,
y: 30,
width: 40,
height: 46,
draggable: true,
draw: false
});
// add cursor styling
star.on('mouseover', function() {
document.body.style.cursor = 'pointer';
});
star.on('mouseout', function() {
document.body.style.cursor = 'default';
});
layer.add(star);
stage.add(layer);
}
var imageObj = new Image();
imageObj.onload = function() {
drawImage(this);
};
imageObj.src = 'http://upload.wikimedia.org/wikipedia/commons/d/df/Star_icon_1.png';
</script>
Please see the fiddle for the full code:
http://jsfiddle.net/hpq7rpnh/1/
Add the trees as their own objects, and then you can check collision between stars and trees:
var starLayer = new Kinetic.Layer(); // its own layer, index should be above tree layer
var treeLayer = new Kinetic.Layer(); // its own layer
stage.add(treeLayer);
stage.add(starLayer);
var tree = new Kinetic.Rectangle( ... );
treeLayer.add(tree);
var tree2 = new Kinetic.Rectangle( ... ); // another tree at another coordinate
treeLayer.add(tree2); // assuming you have a layer for Trees ONLY already
later on, when the user drops the star, you need to check collision
// sample bounding box collision detection
function checkCollision(){
var trees = treeLayer.getChildren(); // gets all the trees
for(tree in trees)
if(star.xCoord > tree.xCoord && star.xCoord + star.width < tree.xCoord + tree.width ... same for y coordinates)
}

kinetic layer is not working on touch event in javascript

I am trying to draw a line when user touch the Screen of Android/Iphone Device. I am using kinetic-v4.7.2.min.js. It works perfect on DeskTop. But not working on Devic. So i just change the mouse click events to Touch events. But, still its not working on touch of Device. It trigger the function perfect but it does not draw any line & does not add the line to the layer. Any idea?
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript"
src="http://code.jquery.com/jquery.min.js"></script>
<script
src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.2.min.js"></script>
<style>
#container {
border: solid 1px #ccc;
margin-top: 10px;
}
</style>
<script>
//create a stage and a layer
$(function() {
window.addEventListener('load', function(){ // on page load
document.body.addEventListener('touchstart', function(e){
// alert(e.changedTouches[0].pageX) // alert pageX coordinate of touch point
}, false)
}, false)
var isdrawing = false;
var stage;
var layer;
var background;
function InitLayer() {
stage = new Kinetic.Stage({
container : 'container',
width : 350,
height : 350
});
layer = new Kinetic.Layer();
stage.add(layer);
}
// an empty stage does not emit mouse-events
// so fill the stage with a background rectangle
// that can emit mouse-events
function drawRect() {
background = new Kinetic.Rect({
x : 0,
y : 0,
width : stage.getWidth(),
height : stage.getHeight(),
fill : 'white',
stroke : 'black',
strokeWidth : 1,
})
layer.add(background);
layer.draw();
// a flag we use to see if we're dragging the mouse
isMouseDown = false;
// a reference to the line we are currently drawing
newline;
// a reference to the array of points making newline
points = [];
}
//a flag we use to see if we're dragging the mouse
var isMouseDown;
// a reference to the line we are currently drawing
var newline;
// a reference to the array of points making newline
var points = [];
InitLayer();
drawRect();
// on the background
// listen for mousedown, mouseup and mousemove events
background.on('touchstart', function(e) {
//alert(e.changedTouches[0].pageX)
//onMousedown();
isdrawing = true;
isMouseDown = true;
points = [];
points.push(stage.getMousePosition());
var line = new Kinetic.Line({
points : points,
stroke : "green",
strokeWidth : 5,
lineCap : 'round',
lineJoin : 'round'
});
layer.add(line);
newline = line;
});
background.on('touchend', function() {
//onMouseup();
isMouseDown = false;
});
background.on('touchmove', function() {
//onMousemove();
if (!isMouseDown) {
return;
}
;
points.push(stage.getMousePosition());
newline.setPoints(points);
// use layer.drawScene
// this is faster since the "hit" canvas is not refreshed
layer.drawScene();
});
$('#clear').on('click', function() {
layer.removeChildren().add(background).draw();
isdrawing = false;
});
$('#save').on(
'click',
function() {
var img = $('.kineticjs-content').find('canvas').get(0)
.toDataURL("myimage/png");
if (isdrawing) {
$('body').prepend('<img src="' + img + '">');
}
});
});
</script>
</head>
<body>
<h3>Drag to sketch</h3>
<button id="save">SAVE as PNG</button>
<button id="clear">CLEAR</button>
<div id="container"></div>
</body>
</html>
Any Help would be appreciated!! Thanks.
You use stage.getMousePosition() to get the position in your touchmove event:
background.on('touchmove', function() {
//onMousemove();
if (!isMouseDown) {
return;
}
;
points.push(stage.getMousePosition());
newline.setPoints(points);
// use layer.drawScene
// this is faster since the "hit" canvas is not refreshed
layer.drawScene();
});
But you should use stage.getPointerPosition() instead.

KineticJS get shape object under the mouse position

I'm trying to write a little game using KineticJS. The cursor is a gun sight, and I want to use some keyboard keys as the triggers to fire different "bullets" for different effects, but I didn't find a way to do it using JS events.
stage = new Kinetic.Stage
container: 'container'
width: window.innerWidth
height: window.innerHeight
shape_layer = new Kinetic.Layer()
circle = new Kinetic.Circle
x: stage.getWidth() / 2
y: stage.getHeight() / 2
radius: 100
fill: 'red'
stroke: 'white'
strokeWidth: 20
circle.on 'click', (e) ->
console.log 'You get one point!'
shape_layer.add circle
stage.add shape_layer
$(document).on 'keydown', (e) ->
if e.keyCode == 90
mouse_p = stage.getMousePosition()
x = mouse_p.x
y = mouse_p.y
evt = document.createEvent 'MouseEvents'
evt.initMouseEvent 'mouseup'
, true
, true
, window
, null
, 0
, 0
, x
, y
shape_layer.fire 'click', evt, true
The event is actually fired, but it's on the layer, not the circle. So I start to think is it possible to get the shape using the mouse position and directly fire a click event on it?
Why not handle mouse events through KineticJS instead?
layer.on('click', function(evt) {
// get the shape that was clicked on
var shape = evt.targetNode;
alert('you clicked on \"' + shape.getName() + '\"');
});
Event Delegation: http://www.html5canvastutorials.com/kineticjs/html5-canvas-get-event-shape-with-kineticjs/
Events: http://www.html5canvastutorials.com/kineticjs/html5-canvas-path-mouseover/
UPDATE:
I misunderstood your question so my apologies.
You were looking to access the targetNode when pressing a key (keydown event). Here's how I would do it:
First you need to set a transparent rectangle background with the width and height of the stage, so that the layer can detect mouse events (in this case we need mousemove).
var bg = new Kinetic.Rect({
x: 0,
y: 0,
width: stage.getWidth(),
height: stage.getHeight(),
id: 'bg'
});
Then, I set an empty Kinetic.Shape for whenever the mouse is moving inside the stage but isn't on a target. So, target is always equal to empty unless mouse is over a node other than our transparent background. scoreText simply prints your score on the stage.
var empty = new Kinetic.Shape({
id: 'empty'
});
var target = empty;
var score = 0;
var scoreText = new Kinetic.Text({
text: 'Score: '+score,
x: 10,
y: 10,
fill: '#000',
fontSize: 20,
id: 'score'
});
Use the mousemove event in KineticJS:
layer.on('mousemove', function (e) {
var mousePos = stage.getMousePosition();
var x = mousePos.x;
var y = mousePos.y;
var node = e.targetNode;
var nodeID = node.getId();
if (nodeID !== 'bg') {
target = node;
} else {
target = empty;
}
});
Then use the jQuery keydown event:
$(document).keydown(function(e) {
if (e.keyCode == 90) {
var id = target.getId();
if (id == 'empty' || id == 'score') {
alert('MISS');
} else {
var targetID = target.getId();
var targetName = target.getName();
alert('ID: ' + targetID + ' NAME: ' + targetName + ' You get one point!');
target.destroy();
target = empty;
score++;
updateScore(scoreText, score);
randomCircle();
}
}
});
And finally, for the sake of making a game.. the randomCircle() and updateScore() functions:
function updateScore(text, score) {
text.setText('Score: ' + score);
//layer.draw(); //normally we would have to layer.draw() here, but I called it in randomCircle() instead to save the amount of draw() calls necessary
}
function randomCircle() {
var circle = new Kinetic.Circle({
x: Math.floor((Math.random() * 578)),
y: Math.floor((Math.random() * 200)),
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
id: 'someTarget',
name: 'targets'
});
layer.add(circle);
layer.draw();
}
jsfiddle (Don't forget to click on the javascript pane to be able to use the keydown event!)

KineticJS - Drawing Lines with Mouse

I'm using KinectJS to draw lines based on mouse movement. When a user holds down the mouse button, I want it to be the 'start' point of the line, and when the user release, it will be the 'end' of the line, but as they are holding the mouse down I want to be able to dynamically redraw the line as my mouse moves. Is this possible?
Yes, its possible.
Basically, you has to redraw your layer during onMouseMove event. You'll need a flag to control when the line is moving or not.
When the script initialize, this flag should be false.
At onMouseDown, the line start should receive the current mouse coordinates and set the flag to true.
At onMouseMouve, if the flag is true, you should update the line end to receive the current mouse coordinates.
At onMouseUp, the flag should be set to false.
See the example below:
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
canvas {
border: 1px solid #9C9898;
}
</style>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.0.1.js"></script>
<script>
window.onload = function() {
layer = new Kinetic.Layer();
stage = new Kinetic.Stage({
container: "container",
width: 320,
height: 320
});
background = new Kinetic.Rect({
x: 0,
y: 0,
width: stage.getWidth(),
height: stage.getHeight(),
fill: "white"
});
line = new Kinetic.Line({
points: [0, 0, 50, 50],
stroke: "red"
});
layer.add(background);
layer.add(line);
stage.add(layer);
moving = false;
stage.on("mousedown", function(){
if (moving){
moving = false;layer.draw();
} else {
var mousePos = stage.getMousePosition();
//start point and end point are the same
line.getPoints()[0].x = mousePos.x;
line.getPoints()[0].y = mousePos.y;
line.getPoints()[1].x = mousePos.x;
line.getPoints()[1].y = mousePos.y;
moving = true;
layer.drawScene();
}
});
stage.on("mousemove", function(){
if (moving) {
var mousePos = stage.getMousePosition();
var x = mousePos.x;
var y = mousePos.y;
line.getPoints()[1].x = mousePos.x;
line.getPoints()[1].y = mousePos.y;
moving = true;
layer.drawScene();
}
});
stage.on("mouseup", function(){
moving = false;
});
};
</script>
</head>
<body>
<div id="container" ></div>
</body>
</html>

Interactive drawing with kineticjs

I'd like to draw a rectangle with click and drag. How can I do this ? Where do I have to put my click event listener ? On the stage or on the layer ? I have the following code but it doesn't work :
stage = new Kinetic.Stage({...})
layer = new Kinetic.Layer({...})
stage.add(layer)
stage.on('click', function() {
var pos = stage.getMousePosition();
var rect = new Kinetic.Rect({
x: pos.x,
y: pos.y,
width: 10,
height: 10,
});
layer.add(rect);
layer.draw();
})
Thanks.
As far as i know there is no "click" event on stage in kineticjs. You should use something like this:
stage.getContainer().addEventListener('mousedown', function(evt) {});
Link to a fiddle that shows what I've been working on:
http://jsfiddle.net/robtown/SGQq7/22/
It's a set of drawing tools using KineticJS and Sketch.js
You need to select "make sketch" to draw freehand and then "copy sketch to Kinetic" to copy your sketch into the kinetic stage. Select "Make rectangle" make a rectangle.
I need to include code to post this so here's the code for when you select the "Make Rectangle" button:
$('#makeRect').click(function (e) {
followRect = new Kinetic.Rect({
width: 120,
height: 40,
x: -200,
y:-200,
stroke: 'red',
strokeWidth: 3
});
drawLayer.setVisible(true);
drawLayer.add(followRect);
drawLayer.draw();
makeRect = true;
drawLayer.on("mousemove", function (e) {
if (makeRect) {
followRect.setX(e.x+5);
followRect.setY(e.y+5);
drawLayer.draw();
}
});
This creates a rectangle that follows the mouse until you click on the canvas, then it drops the rectangle into the Redlines layer of the stage:
drawLayer.on("mousedown", function (e) {
//for (var f = 0 ; f < 1; f++) {
//alert(e.length);
if (makeRect) {
addToRedlineLayer(e.x, e.y);
}
//}
followRect.setX(-200);
drawLayer.setVisible(false);
return;
});
I had the exact same problem, and indeed the method of Guilherme works greatly.
But there's a simple alternative: create a transparent Rect (Kinetic rectangle) the same size as the canvas:
<script type='text/javascript'>//<![CDATA[
window.onload=function(){
function writeMessage(messageLayer, message) {
var context = messageLayer.getContext();
messageLayer.clear();
context.font = '18pt Calibri';
context.fillStyle = 'black';
context.fillText(message, 10, 25);
}
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var shapesLayer = new Kinetic.Layer();
var messageLayer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x:0,
y:0,
width:stage.getWidth(),
height:stage.getHeight(),
stroke:0
});
rect.on('mousemove', function() {
var mousePos = stage.getMousePosition();
var x = mousePos.x;
var y = mousePos.y;
writeMessage(messageLayer, 'x: ' + x + ', y: ' + y);
});
stage.getContainer().addEventListener('mouseout', function(evt) {
writeMessage(messageLayer, '');
});
shapesLayer.add(rect);
stage.add(shapesLayer);
stage.add(messageLayer);
}//]]>
</script>
The above code will print the x and y position of the mouse when you hover it over the canvas (a div with id "container"). You of course need to load the KineticJS library before using this code.

Categories

Resources