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>
Related
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.
I have JS object with 3 JSON entries, as JavaScript loops through the 3 it creates shapes on the canvas using KineticJS. I'm trying to make it so that when I pass a pixel threshold, in this case 400px, It creates an alert box with the JSON jstext tied to the shape. Here's the code
var tools = [{'title':'method', 'jstext':'function newMethod() {'},
{'title':'var', 'jstext':'var'},
{'title':'end', 'jstext':'}'},
]
var startX = 20;
var startY = 30;
for (var i=0; i<tools.length; i++) {
alert(tools[i].jstext)
var x = new Kinetic.Rect({
x: startX,
y: startY,
width: 100,
height: 50,
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 3,
draggable: true,
offset:10,
});
startY = startY + 65;
layer.add(x);
x.on('dragend', function() {
if (x.getAttr('x')>=400) {
console.log(tools[i].jstext)
};
}
It creates the rectangles, it just only logs if the last shape is moved and I want it to pull that text if any shape is moved. Any Ideas? Thanks!
You can:
Create new rectangle inside a function,
Add .originalX and originalY properties so each rect saves its original XY position,
Add a dragend handler that calculates if .getX/.getY are further than 400 px from original XY.
The code would be something like this:
<!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.7.2.min.js"></script>
<style>
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
var startX = 20;
var startY = 30;
// create 5 test rects
for (var i=0; i<5; i++) {
newRect(startX,startY,i);
startY = startY + 65;
}
// function to create a new rect
function newRect(x,y,id){
var rect = new Kinetic.Rect({
id:id,
x: startX,
y: startY,
width: 100,
height: 50,
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 3,
draggable: true,
offset:10,
});
// have the rect save its original XY
rect.originalX=x;
rect.originalY=y;
// on dragend, calc if the rect has moved >400px
rect.on("dragend",function(){
var dx=this.getX()-this.originalX;
var dy=this.getY()-this.originalY;
var id=this.getId();
if(dx*dx+dy*dy>400*400){
alert(id+" is currently beyond 400px of original XY");
}else{
console.log(id+" is currently inside 400px of original XY");
}
});
layer.add(rect);
layer.draw();
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
how to use draggable and double click together in kineticjs?
when using draggable then double click will not work.
Here is my code to draw the image..
function draw(images) {
abcImg= new Kinetic.Rect({
x: 50,
y: 150,
width: 50,
height: 50,
fillPatternImage: images.abc,
name: "abc",
draggable: true
});
}
and here the code when double click..
layer.on('dblclick', function(evt) {
var shape = evt.shape;
name = shape.getName();
$( "#dialog-form" ).dialog( "open" );
});
I'm use kineticjs and jquery.. Thank you..
Here is how to listen for mouse/touch events on the empty areas of the stage.
To listen for mouse/touch events on the stage (any non-object area), you need to add a new layer containing a rectangle that fills the stage. Then you can handle mouse/touch events on the empty stage areas: eventLayer.on(“dblclick”,function(e) {//do doubleclick stuff}
That layer code looks like this:
// Create a layer that will listen for mouse/touch events
var eventLayer = new Kinetic.Layer();
eventLayer.add(new Kinetic.Rect({
x:0,
y:0,
width:400,
height:300
}));
stage.add(eventLayer);
// TEST--listen for "dblclick"
eventLayer.on('dblclick', function(evt) {
alert("2click");
});
Here is the full code and a Fiddle: http://jsfiddle.net/m1erickson/gNMRq/
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.3.2-beta.js"></script>
</head>
<body>
<div id="container"></div>
<script>
var stage = new Kinetic.Stage({
container: 'container',
width: 400,
height: 300
});
var layer = new Kinetic.Layer();
var rectX = stage.getWidth() / 2 - 50;
var rectY = stage.getHeight() / 2 - 25;
var box = new Kinetic.Rect({
x: rectX,
y: rectY,
width: 100,
height: 50,
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 4,
draggable: true
});
// add cursor styling
box.on('mouseover', function() {
document.body.style.cursor = 'pointer';
});
box.on('mouseout', function() {
document.body.style.cursor = 'default';
});
// Create a layer that will listen for mouse/touch events
var eventLayer = new Kinetic.Layer();
eventLayer.add(new Kinetic.Rect({
x:0,
y:0,
width:400,
height:300
}));
stage.add(eventLayer);
// TEST--listen for "dblclick"
eventLayer.on('dblclick', function(evt) {
alert("2click");
});
layer.add(box);
stage.add(layer);
</script>
</body>
</html>
it is working fine. Take a look at this, it's using draggable and dblclick, and both works fine.
http://jsbin.com/oruhif/1/edit
Hi I am looking to make a floor plan editor (something like MsPaint) using JavaScript. I have shortlisted EaselJS or KinetiJS as my preferred libraries.
I would like to know how to create a dynamic rectangular box/line with these libraries. I intend to draw a rectangle by clicking the mouse and dragging it (while the mouse button remains pressed). Thus the size of the rectangle will depend on how far the mouse is dragged.
Any help will be appreciated. If anyone feels that any other library like fabrisJs or paperJs will be better alternative then I am open to solutions in these libraries as well.
Ok... by trial and error and lots of googling and reusing net code I got the answer for KineticJs.
Heres the complete solution:
http://jsfiddle.net/sandeepy02/8kGVD/
<html>
<head>
<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"
});
layer.add(background);
stage.add(layer);
moving = false;
stage.on("mousedown", function(){
if (moving){
moving = false;layer.draw();
} else {
var mousePos = stage.getMousePosition();
rect= new Kinetic.Rect({
x: 22,
y: 7,
width: 0,
height: 0,
fill: 'red',
stroke: 'black',
strokeWidth: 4
});
layer.add(rect);
//start point and end point are the same
rect.setX(mousePos.x);
rect.setY(mousePos.y);
rect.setWidth(0);
rect.setHeight(0);
moving = true;
layer.drawScene();
}
});
stage.on("mousemove", function(){
if (moving) {
var mousePos = stage.getMousePosition();
var x = mousePos.x;
var y = mousePos.y;
rect.setWidth(mousePos.x-rect.getX());
rect.setHeight(mousePos.y-rect.getY());
moving = true;
layer.drawScene();
}
});
stage.on("mouseup", function(){
moving = false;
});
};
</script>
</head>
<body>
<div id="container" ></div>
</body>
</html>
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.