KineticJS and HTML - html

I have a situation, the images moving left to right and viceversa, after a certain bound area the images have to hide(invisible) from the stage and when they return back it should be visible. My tween is like this :
var tween = new Kinetic.Tween({
node: puzzle,
duration: 22,
x: puzzle.getX()+700,
easing: Kinetic.Easings.Linear,
onFinish : function(){
this.reverse();
}
});
anyone please help me. Thanks in advance.

Use clipping regions
You can put your puzzle object on a group and set a clipping region on that group.
When your puzzle moves out of the group's clipping region it will not be displayed.
Demo: http://jsfiddle.net/m1erickson/hzTM7/
<!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 group=new Kinetic.Group({
clip:{x:50,y:50,width:100,height:100},
});
layer.add(group);
var bk=new Kinetic.Rect({
x:50,
y:50,
width:100,
height:100,
fill:"blue",
opacity:0.10,
});
group.add(bk);
var circle1 = new Kinetic.Circle({
x:70,
y:70,
radius: 15,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
});
group.add(circle1);
layer.draw();
var tween = new Kinetic.Tween({
node: circle1,
duration: 2,
x: circle1.getX()+120,
easing: Kinetic.Easings.Linear,
onFinish : function(){
this.reverse();
}
});
$("#myButton").click(function(){ tween.play(); });
}); // end $(function(){});
</script>
</head>
<body>
<button id="myButton">Tween</button>
<div id="container"></div>
</body>
</html>

Related

How to obtain ID of Konva Label from Konva's 'dblclick' event

I'm looking for a way to obtain ID (123 in the code below) of a Konva Label ("Hello World!" in the code below) from Konva's 'dblclick' event.
I could obtain ID (321 in the code below) of a Konva Image (Konva's LOGO "K" in the code below) from both of Konva's 'dblclick' and 'dragmove' events.
Also I could obtain the ID (123 in the code below) of the Konva Label ("Hello World!") from 'dragmove' event; however I couldn't obtain the ID (123 in the code below) of the Konva Label ("Hello World!") from Konva's 'dblclick' event.
My code:
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva#5.0.2/konva.min.js"></script>
<meta charset="utf-8" />
</head>
<body>
<span id="container"></span>
</body>
<script>
//Konva Stage
var stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight,
});
//Konva Layer
var layer = new Konva.Layer();
stage.add(layer);
//Konva Image
var imageObj = new Image();
imageObj.src = 'https://raw.githubusercontent.com/konvajs/konvajs.github.io/master/apple-touch-icon-180x180.png';
imageObj.addEventListener('load', function() {
var kImage = new Konva.Image({
x: window.innerWidth*2.5/10,
y: window.innerHeight*1/10,
image: imageObj,
id: 321,
draggable: true,
});
layer.add(kImage);
layer.draw();
});
//Konva Label
WordLabel = new Konva.Label({
x: window.innerWidth*3/10,
y: window.innerHeight*4/10,
opacity: 0.75,
draggable: true,
fill: 'green',
id: 123,
});
//Konva Tag
WordLabel.add(
new Konva.Tag({
fill: 'green',
})
);
//Konva Text
WordLabel.add(
new Konva.Text({
text: 'Hello World!',
fontFamily: 'Calibri',
fontSize: 18,
padding: 5,
fill: 'white',
strokeWidth: 0,
})
);
layer.add(WordLabel);
layer.draw();
//Konva dragstart event
stage.on('dragstart', function(e) {
console.log('ID (dragstart) = ' + parseInt(e.target.id()));
});
//Konva dblclick event
stage.on('dblclick dbltap', function (e) {
console.log('ID (dblclick) = ' +parseInt(e.target.id()));
});
</script>
</html>
If you look at the e.target object you can see that it is the text node rather than the label node that received the click.
Use e.target.findAncestors (see shape API) to get and iterate the shape hierarchy looking for an ancestor shape with the ID attribute you seek.
Working snippet below.
//Konva Stage
var stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight,
});
//Konva Layer
var layer = new Konva.Layer();
stage.add(layer);
//Konva Image
var imageObj = new Image();
imageObj.src = 'https://raw.githubusercontent.com/konvajs/konvajs.github.io/master/apple-touch-icon-180x180.png';
imageObj.addEventListener('load', function() {
var kImage = new Konva.Image({
x: window.innerWidth*2.5/10,
y: window.innerHeight*1/10,
image: imageObj,
id: 321,
draggable: true,
});
layer.add(kImage);
layer.draw();
});
//Konva Label
WordLabel = new Konva.Label({
x: 10,
y: 20,
opacity: 0.75,
draggable: true,
fill: 'green',
id: 123,
});
//Konva Tag
WordLabel.add(
new Konva.Tag({
fill: 'green'
})
);
//Konva Text
WordLabel.add(
new Konva.Text({
text: 'Hello World!',
fontFamily: 'Calibri',
fontSize: 18,
padding: 5,
fill: 'white',
strokeWidth: 0
})
);
layer.add(WordLabel);
layer.draw();
//Konva dragstart event
stage.on('dragstart', function(e) {
console.log('ID (dragstart) = ' + parseInt(e.target.id()));
});
//Konva dblclick event
stage.on('dblclick dbltap', function (e) {
// Looking for a specif attr on a parent shape. In this
// case we know the parent is a Label so search for ancestors of that type
var nodes = e.target.findAncestors('Label', true);
if (nodes.length > 0) {
for (var i = 0; i < nodes.length; i++){
var id = nodes[i].getAttr("id")
console.log('shape ' + i + ' ID (dblclick)', id )
}
}
else {
console.log('ID (dblclick) = ' + parseInt(e.target.id()));
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva#5.0.2/konva.min.js"></script>
<meta charset="utf-8" />
</head>
<body>
<span id="container"></span>
</body>
<script>
</script>
</html>

Draw rectangle between two mouse clicks on canvas using fabric js

I am beginner to fabric js. I want to draw a rectangle over an canvas having background image. First time when user mouse down on the canvas get that co-ordinates then user mouse up then again when he mouse down then rectangle should be drawn between these points these points are the upper left point and the bottom right point. I am very much confused how to do that.
I am sharing my code which I have used to draw canvas and set background image and it also draws and line.
<html lang="en" >
<head>
<meta charset="utf-8" />
<title>HTML5 canvas - Image color picker | Script Tutorials</title>
<link href="index.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.1.0/fabric.all.min.js" ></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</head>
<body>
<div class="container">
<div class="column1">
<canvas id="panel" width="700" height="350"></canvas>
</div>
<div style="clear:both;"></div>
</div>
</body>
<script>
(function() {
var canvas = new fabric.Canvas('panel', { selection: false });
var line, isDown;
canvas.on('mouse:down', function(o){
isDown = true;
var pointer = canvas.getPointer(o.e);
var points = [ pointer.x, pointer.y, pointer.x, pointer.y ];
console.log(points);
line = new fabric.Line(points, {
strokeWidth: 5,
fill: 'red',
stroke: 'red',
originX: 'center',
originY: 'center'
});
canvas.add(line);
});
canvas.on('mouse:move', function(o){
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
line.set({ x2: pointer.x, y2: pointer.y });
canvas.renderAll();
});
canvas.on('mouse:up', function(o){
isDown = false;
});
fabric.Image.fromURL('fedex.jpg', function (img) {
canvas.add(img.set({
width: 700,
height:350,
left: 350,
top: 175,
selectable: false,
}));
});
})();
</script>
Modify your code like this:
(function() {
var canvas = new fabric.Canvas('panel');
var line, isDown, startPosition={}, rect,drawingMode=true;
canvas.on('mouse:down', function(event){
if (!drawingMode) return;
isDown = true;
console.log(event.e.clientX,event.e.clientY);
startPosition.x=event.e.clientX;
startPosition.y=event.e.clientY;
console.log(startPosition);
rect=new fabric.Rect({
left:event.e.clientX,
top:event.e.clientY,
width:0,
height:0,
stroke:'red',
strokeWidth:3,
fill:''
});
canvas.add(rect);
});
canvas.on('mouse:move', function(event){
if (!isDown || !drawingMode) return;
rect.setWidth(Math.abs( event.e.clientX-startPosition.x ));
rect.setHeight(Math.abs( event.e.clientY -startPosition.y ));
canvas.renderAll();
});
canvas.on('mouse:up', function(){
isDown = false;
canvas.add(rect);
});
canvas.on('object:selected', function(){
drawingMode = false;
});
canvas.on('object:selected', function(){
drawingMode = false;
});
canvas.on('selection:cleared', function(){
drawingMode = true;
});
})();
This will draw rectangle with mouse.
See in Fiddle

HTML 5 - add Shape on mouseover

I use KineticJS to create shape and animate them.
I have a triangle :
var triangle1Over = new Kinetic.Polygon({
points: [120, 10, 225, 140, 15, 140, 120, 10],
stroke: 'red',
strokeWidth: 2
});
I would like to make it appears one time on mouseover event.
triangle1.on('mouseover', function () {
layer.add(triangle1Over);
layer.draw();
});
The issue : on every cursor move in triangle1, the shape triangle1Over is added > this is bad because it's blinking.
I try to find something: "if the shape hasn't already been added to the layer, add it". But nothing.
Any help would be great. Thanks :)
How about changing the colors of the triangle on mouseenter and on mouseleave?
That would eliminate any “flicker” that’s causes when your 2 triangles overlap:
triangle1.on('mouseenter', function () {
console.log("over");
triangle1.setStroke("orange");
triangle1.setFill("green");
layer.draw();
});
triangle1.on('mouseleave', function() {
triangle1.setStroke("red");
triangle1.setFill("white");
layer.draw();
});
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/35hKX/
<!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.4.min.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:400px;
height:400px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 400,
height: 400
});
var layer = new Kinetic.Layer();
stage.add(layer);
var triangle1 = new Kinetic.Polygon({
points: [120, 10, 225, 140, 15, 140, 120, 10],
stroke: 'red',
strokeWidth: 2,
fill:"white"
});
layer.add(triangle1);
layer.draw();
triangle1.on('mouseenter', function () {
console.log("over");
triangle1.setStroke("orange");
triangle1.setFill("green");
layer.draw();
});
triangle1.on('mouseleave', function() {
triangle1.setStroke("red");
triangle1.setFill("white");
layer.draw();
});
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
If you give triangle1Over an ID like this:
var triangle1Over = new Kinetic.Polygon({
points: [120, 10, 225, 140, 15, 140, 120, 10],
stroke: 'red',
strokeWidth: 2,
id: triangle1OverID
});
You can check if it exists in the layer like this:
triangle1.on('mouseover', function () {
if(typeof stage.get('#triangle1OverID')[0] == 'undefined') {
layer.add(triangle1Over);
layer.draw();
}
});
Or you can use a name:
var triangle1Over = new Kinetic.Polygon({
points: [120, 10, 225, 140, 15, 140, 120, 10],
stroke: 'red',
strokeWidth: 2,
name: triangle1OverName
});
You can check if it exists in the layer like this:
triangle1.on('mouseover', function () {
var shapes = stage.get('.triangle1OverName');
if(shapes.length) {
layer.add(triangle1Over);
layer.draw();
}
});
Well I think you need callback functions like mouseenter and mouseleave just draw the triangle1Over when the mouseenter function is triggered over the triangle1 and make the triangle1Over disappear when the mouseleave event over the triangle1Over is fired. Maybe this link of mouseevents might help..

KineticJS layer index when dragging

So my problem seems to be that a draggable object always is drawn over other objects.
Check out my fiddle.
and my code:
<!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.3.1-beta.js"></script>
<script>
window.onload = function() {
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var cableLayer = new Kinetic.Layer();
// build cable
var cable = new Kinetic.Line({
strokeWidth: 40,
stroke: 'green',
points: [{
x: stage.getWidth() / 2,
y: stage.getHeight() / 2
}, {
x: 100,
y: 100
}],
draggable: true
});
// build center
var c1 = new Kinetic.Circle({
radius: 60,
fill: 'black',
draggable: true,
x: stage.getWidth() / 2,
y: stage.getHeight() / 2
});
var c2 = new Kinetic.Circle({
x: 100,
y: 100,
radius: 60,
fill: 'black',
draggable: true,
});
//add everything to the layer
cableLayer.add(cable);
cableLayer.add(c1);
cableLayer.add(c2);
//add all to stage
stage.add(cableLayer);
//What to do when something is changed...
cable.on('dragmove', (function () {
c1.setPosition([cable.getPosition().x + cable.getPoints()[0].x, cable.getPosition().y + cable.getPoints()[0].y]);
c2.setPosition([cable.getPosition().x + cable.getPoints()[1].x, cable.getPosition().y + cable.getPoints()[1].y]);
cableLayer.draw();
}));
c1.on('dragstart', (function () {
c1.getLayer().afterDraw(function () {
cable.attrs.points[0].x = c1.getX()-cable.getX();
cable.attrs.points[0].y = c1.getY()-cable.getY();
cableLayer.draw();
});
}));
c2.on('dragstart', (function () {
c2.getLayer().afterDraw(function () {
cable.attrs.points[1].x = c2.getX()-cable.getX();
cable.attrs.points[1].y = c2.getY()-cable.getY();
cableLayer.draw();
});
}));
}
</script>
</head>
<body onmousedown="return false;">
<div id="container"></div>
</body>
</html>
So, I tried to set the index using
cable.on('dragmove', (function () {
c1.setPosition([cable.getPosition().x + cable.getPoints()[0].x, cable.getPosition().y + cable.getPoints()[0].y]);
c2.setPosition([cable.getPosition().x + cable.getPoints()[1].x, cable.getPosition().y + cable.getPoints()[1].y]);
c2.setIndex(1);
c1.setIndex(1);
cable.setIndex(2);
cableLayer.draw();
}));
Doesn't seem to work? Why is this? How do I get the circles to draw over the line in all cases? Mainly the case that you drag the line.
Is there somewhere I'm setting this differently somewhere else?
Thanks for your help
http://jsfiddle.net/nYHrg/3/
So the problem is that kineticjs (4.3.0) added a new 'drag' layer to improve dragging performance. Any time that you drag an object, it is put in the drag layer, and when you stop dragging, it is put back in it's own layer. This does not preserve your original z-index. Anytime you create a new object and you want to override this functionality you will have to set one of the attributes of the object as:
"dragOnTop: false"
see jsfiddle for exact implementation.

How to add labels to KineticJS shapes?

I am using KineticJs to create shapes with some text label(draggable along with the shape). There wasn't any info on the tutorial. Neither did I find this a very clean approach. What's a good approach to do so? The code below only creates the shape.
HTML:
<html>
<body>
<div id="container"> </div>
<button id="new_state">New State</button>
</body>
</html>
JS:
$(document).bind("ready", function () {
stage = new Kinetic.Stage({
container: 'container',
width: 600,
height: 500
});
layer = new Kinetic.Layer();
$('#new_state').click(function() {
newState();
});
});
newState = function() {
var circle = new Kinetic.Circle({
x: stage.getWidth()/2,
y: stage.getHeight()/2,
radius: 20,
fill: 'white',
stroke: 'black',
strokeWidth: 2,
text: 'tet',
draggable: true
});
circle.on('mouseover', function() {
$('body').css('cursor', 'pointer');
});
circle.on('mouseout', function() {
$('body').css('cursor', 'default');
});
layer.add(circle);
stage.add(layer);
};
JsFiddle here
You just need to add both the circle and text to a group and make the group draggable.
When grouped, the objects act as one item.
var group = new Kinetic.Group({
draggable: true
});
group.add(circle);
group.add(text);
then add the group to the layer
layer.add(group);
http://jsfiddle.net/e8KwC/1/