I have little issue here (i obviously miss something). I simplified it from my bigger application:
When i click blue rectangle, i add another layer to the stage that includes red rectangle (clickable), when i click this red rectangle, it removes second layer with red rect.
Problem: When i click blue rect second time, nothing happens :( i.e. app works only once, and i need to add/remove second layer(with red rect) repeatedly. What's wrong? :)
You can see it here, Fiddle http://jsfiddle.net/mAX8r/
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.0.3.js">
</script>
<script>
window.onload = function() {
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layerBlue = new Kinetic.Layer();
var layerRed = new Kinetic.Layer();
var rectBlue = new Kinetic.Rect({
x: 100,
y: 75,
width: 100,
height: 50,
fill: 'blue',
stroke: 'black',
strokeWidth: 4
});
var rectRed = new Kinetic.Rect({
x: 300,
y: 75,
width: 100,
height: 50,
fill: 'red',
stroke: 'black',
strokeWidth: 4
});
// mouse events
rectBlue.on('click', function() {
stage.add(layerRed);
stage.draw();
});
rectRed.on('click', function() {
layerRed.remove();
stage.draw();
});
// add the shape to the layer
layerBlue.add(rectBlue);
layerRed.add(rectRed);
// add the layer to the stage
stage.add(layerBlue);
};
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
To hide and show a shape, we can the hide() and show() methods. Try this JSFIDDLE http://jsfiddle.net/mAX8r/5/. and You can see the sample code 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.3.js"></script>
<script>
var layerBlue;
var layerRed;
var rectBlue;
var rectRed;
window.onload = function() {
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
layerBlue = new Kinetic.Layer();
layerRed = new Kinetic.Layer();
rectBlue = new Kinetic.Rect({
x: 100,
y: 75,
width: 100,
height: 50,
fill: 'blue',
stroke: 'black',
strokeWidth: 4
});
rectRed = new Kinetic.Rect({
x: 300,
y: 75,
width: 100,
height: 50,
fill: 'red',
stroke: 'black',
strokeWidth: 4
});
// mouse events
rectBlue.on('click', function() {
rectRed.show();
stage.draw();
});
rectRed.on('click', function() {
rectRed.hide();
stage.draw();
});
// add the shape to the layer
layerBlue.add(rectBlue);
layerRed.add(rectRed);
// add the layer to the stage
stage.add(layerBlue);
stage.add(layerRed);
rectRed.hide();
stage.draw();
};
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
Refer this url http://www.html5canvastutorials.com/kineticjs/html5-canvas-hide-and-show-shape-with-kineticjs/ for HTML5 Canvas Hide and Show a Shape
Related
Disclaimer: it may be considered this post is a duplicate of this post but I have demonstrated my need specifically.
I have a case in my KonvaJS application where I need to propagate a click event from the Rectangle shape (that is a child of the Upper Layer) to several images that are added to the Lower Layer.
Please note that I have in the Lower layer more than 50 objects between images and shapes, so how can I now what is the target object in the Lower Layer.
Kindly here is an example to demonstrate my need:
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var lowerLayer = new Konva.Layer();
var upperLayer = new Konva.Layer();
//lion
var lionImage = new Image();
lionImage.onload = function() {
var lion = new Konva.Image({
x: 50,
y: 50,
image: lionImage,
width: 106,
height: 118
});
// add the shape to the layer
lowerLayer.add(lion);
stage.draw();
lion.on("click", function() {
alert("you clicked the lion");
});
};
lionImage.src = 'http://konvajs.github.io/assets/lion.png';
//monkey
var monkeyImage = new Image();
monkeyImage.onload = function() {
var monkey = new Konva.Image({
x: 200,
y: 50,
image: monkeyImage,
width: 106,
height: 118
});
// add the shape to the layer
lowerLayer.add(monkey);
stage.draw();
monkey.on("click", function() {
alert("you clicked the monkey");
});
};
monkeyImage.src = 'http://konvajs.github.io/assets/monkey.png';
var upperTransparentBox = new Konva.Rect({
x: 0,
y: 0,
height: stage.height(),
width: stage.width(),
fill: 'transparent',
draggable: false,
name: 'upperTransparentBox'
});
upperTransparentBox.on("click", function() {
alert("you clicked the upper Transparent Box");
});
upperLayer.add(upperTransparentBox);
// add the layer to the stage
stage.add(lowerLayer);
stage.add(upperLayer);
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.rawgit.com/konvajs/konva/1.0.2/konva.min.js"></script>
<meta charset="utf-8">
<title>Konva Image Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #F0F0F0;
}
</style>
</head>
<body>
<div id="container"></div>
</body>
</html>
Technically it is possible to manually trigger click event on any node.
But I think it is an antipattern. You can just find an intersection with 'getIntersection()' function and do what you need with a node.
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var lowerLayer = new Konva.Layer();
var upperLayer = new Konva.Layer();
//lion
var lionImage = new Image();
lionImage.onload = function() {
var lion = new Konva.Image({
x: 50,
y: 50,
name: 'lion',
image: lionImage,
width: 106,
height: 118
});
// add the shape to the layer
lowerLayer.add(lion);
stage.draw();
lion.on("click", function() {
alert("you clicked the lion");
});
};
lionImage.src = 'http://konvajs.github.io/assets/lion.png';
//monkey
var monkeyImage = new Image();
monkeyImage.onload = function() {
var monkey = new Konva.Image({
x: 200,
y: 50,
name: 'monkey',
image: monkeyImage,
width: 106,
height: 118
});
// add the shape to the layer
lowerLayer.add(monkey);
stage.draw();
monkey.on("click", function() {
alert("you clicked the monkey");
});
};
monkeyImage.src = 'http://konvajs.github.io/assets/monkey.png';
var upperTransparentBox = new Konva.Rect({
x: 0,
y: 0,
height: stage.height(),
width: stage.width(),
fill: 'transparent',
draggable: false,
name: 'upperTransparentBox'
});
upperTransparentBox.on("click", function() {
var target = lowerLayer.getIntersection(stage.getPointerPosition());
if (target) {
alert('clicked on ' + target.name());
}
});
upperLayer.add(upperTransparentBox);
// add the layer to the stage
stage.add(lowerLayer);
stage.add(upperLayer);
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.rawgit.com/konvajs/konva/1.0.2/konva.min.js"></script>
<meta charset="utf-8">
<title>Konva Image Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #F0F0F0;
}
</style>
</head>
<body>
<div id="container"></div>
</body>
</html>
In my application I use KonvaJS extensively, but I reached a step where I need to create a Bootstrap Popover on KonvaJS Image click, is that possible?
Please note that I have more than 50 images in this app and I need to create a popover for each.
If you want to have PopOver only for canvas images then I would suggest to use Konva.Label. You can set the pointer in whichever direction you want and set the position of label. Here's the plunkr which I have created.
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.rawgit.com/konvajs/konva/0.15.0/konva.min.js"></script>
<meta charset="utf-8">
<title>Konva Label Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #F0F0F0;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
var stage = new Konva.Stage({
container: 'container',
width: 300,
height: 300
});
var layer = new Konva.Layer();
// label with left pointer
var tooltip = new Konva.Label({
x: 170,
y: 75,
opacity: 0.75
});
tooltip.add(new Konva.Tag({
fill: 'black',
pointerDirection: 'down',
pointerWidth: 10,
pointerHeight: 10,
lineJoin: 'round',
shadowColor: 'black',
shadowBlur: 10,
shadowOffset: 10,
shadowOpacity: 0.5
}));
tooltip.add(new Konva.Text({
text: 'Yoda has powers...',
fontFamily: 'Calibri',
fontSize: 18,
padding: 5,
fill: 'white'
}));
var image = new Image();
image.onload = function() {
var lion = new Konva.Image({
image: image,
x: 70,
y: 75,
draggable: true
});
layer.add(lion);
// add the labels to layer
layer.add(tooltip);
layer.draw();
};
image.src = 'http://konvajs.github.io/assets/yoda.jpg';
// add the layer to the stage
stage.add(layer);
</script>
</body>
</html>
i have following code to drag a smaller rect in a bigger rect.
it is almost working, but its possible to move the orange rect out of the white one.
Is there any solution for this behavior?? that the bigger rect is the dragborder for the small rect??
And another question... would it be possible to do it for a rect in any polygon as border?
<!DOCTYPE HTML>
<html>
<head>
<style>
body {margin: 0px; padding: 20px;}
canvas {border: 1px solid #777;}
</style>
</head>
<body>
<div id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.3.2.js"></script>
<script>
var stage = new Kinetic.Stage({
container: 'container',
width: 300,
height: 300
});
var layer = new Kinetic.Layer();
// White box
var white = new Kinetic.Rect({
x: 100,
y: 50,
width: 150,
height: 100,
fill: 'white',
stroke: 'black',
strokeWidth: 2
});
// orange box
var orange = new Kinetic.Rect({
x: 150,
y: 100,
width: 50,
height: 30,
fill: 'orange',
stroke: 'black',
strokeWidth: 2,
draggable: true,
// this causes orange box to be stopped if try to leave white box
dragBoundFunc: function(pos){
if(theyAreColliding(orange,white)){
// orange box is touching white box
// let it move ahead
return ({ x:pos.x, y:pos.y });
} else{
// orange box is not touching white box
// don't let orange box move outside
if (white.getY() > orange.getY()){
return({x: pos.x, y: white.getY()+1});
}
else if (white.getY() + white.getHeight() - orange.getHeight() < orange.getY()){
return({x: pos.x, y: white.getY() + white.getHeight() - orange.getHeight() -1});
}
else if (white.getX() > orange.getX()){
return({x: white.getX() +1, y: pos.y})
}
else if (white.getX() + white.getWidth() - orange.getWidth() < orange.getX()){
return({x: white.getX() +white.getWidth() - orange.getWidth() -1, y: pos.y})
}
}
}
});
function theyAreColliding(rect1, rect2) {
return !(rect2.getX() > rect1.getX() ||
rect2.getX() + rect2.getWidth() - rect1.getWidth() < rect1.getX() ||
rect2.getY() > rect1.getY() ||
rect2.getY() + rect2.getHeight() - rect1.getHeight() < rect1.getY());
}
layer.add(white);
layer.add(orange);
stage.add(layer);
</script>
</body>
</html>
and also the jsfiddle link: http://jsfiddle.net/dNfjM/
This is an improved way of setting your dragBoundFunc
The secret with dragBoundFunc is to allow it to execute fast. Remember that it is being executed with every mousemove.
So, pre-calculate all the minimum and maximum boundaries before and outside dragBoundFunc, like this:
// pre-calc some bounds so dragBoundFunc has less calc's to do
var height=orangeRect.getHeight();
var minX=white.getX();
var maxX=white.getX()+white.getWidth()-orangeRect.getWidth();
var minY=white.getY();
var maxY=white.getY()+white.getHeight()-orangeRect.getHeight();
That way your dragBoundFunc can just test the current position against these pre-calc’ed bounds like this:
dragBoundFunc: function(pos) {
var X=pos.x;
var Y=pos.y;
if(X<minX){X=minX;}
if(X>maxX){X=maxX;}
if(Y<minY){Y=minY;}
if(Y>maxY){Y=maxY;}
return({x:X, y:Y});
}
Here’s code and a Fiddle: http://jsfiddle.net/m1erickson/n5xMs/
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 10px;
}
canvas{border:1px solid red;}
</style>
</head>
<body>
<div id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.4.1.min.js"></script>
<script>
var stage = new Kinetic.Stage({
container: 'container',
width: 400,
height: 400
});
var layer = new Kinetic.Layer();
var white = new Kinetic.Rect({
x: 20,
y: 20,
width: 300,
height: 300,
fill: 'white',
stroke: 'black',
strokeWidth: 2
});
var orangeGroup = new Kinetic.Group({
x: stage.getWidth() / 2,
y: 70,
draggable: true,
dragBoundFunc: function(pos) {
var X=pos.x;
var Y=pos.y;
if(X<minX){X=minX;}
if(X>maxX){X=maxX;}
if(Y<minY){Y=minY;}
if(Y>maxY){Y=maxY;}
return({x:X, y:Y});
}
});
var orangeText = new Kinetic.Text({
fontSize: 26,
fontFamily: 'Calibri',
text: 'boxed in',
fill: 'black',
padding: 10
});
var orangeRect = new Kinetic.Rect({
width: orangeText.getWidth(),
height: orangeText.getHeight(),
fill: 'orange',
stroke: 'blue',
strokeWidth: 4
});
orangeGroup.add(orangeRect).add(orangeText);
layer.add(white);
layer.add(orangeGroup);
stage.add(layer);
// pre-calc some bounds so dragBoundFunc has less calc's to do
var height=orangeRect.getHeight();
var minX=white.getX();
var maxX=white.getX()+white.getWidth()-orangeRect.getWidth();
var minY=white.getY();
var maxY=white.getY()+white.getHeight()-orangeRect.getHeight();
</script>
</body>
</html>
I have a draggable circle shape that the user drags to another circle shape [static, non-draggable]. When the draggable circle overlaps the static circle, I need to display a "Success" text. How can I do so ?
When the user drags the circle, you can handle the “dragmove” events.
In "dragmove": test whether the circles are colliding. If so, then declare success!
Circle1.on("dragmove",function(){
if(theyAreColliding(Circle1,Circle2)){
// Success!
}
});
The test for collision looks like this:
function theyAreColliding(c1,c2){
var dx=c1.getX()-c2.getX();
var dy=c1.getY()-c2.getY();
var radiiSum=c1.getRadius()+c2.getRadius();
console.log(dx+"/"+dy+": "+radiiSum);
return((dx*dx+dy*dy)<radiiSum*radiiSum);
}
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/3dQpL/
<!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://www.html5canvastutorials.com/libraries/kinetic-v4.3.3-beta.js"></script>
<style>
canvas{
border:solid 1px #ccc;
}
</style>
<script>
$(function(){
var layer = new Kinetic.Layer();
var stage = new Kinetic.Stage({
container: "container",
width: 400,
height: 400
});
stage.add(layer);
// mouse events don't fire on the empty part of the stage
// so fill the stage with a rect to get events on entire stage
// now stage.on("mouse... will work
var background = new Kinetic.Rect({
x: 0,
y: 0,
width: 400, //stage.getWidth(),
height: 400, //stage.getHeight(),
fill: "#eee"
});
layer.add(background);
var Radius1=50;
var Circle1=new Kinetic.Circle({
x: 225,
y: 125,
radius: Radius1,
fill: 'green',
stroke: 'orange',
strokeWidth: 2,
draggable:true
});
layer.add(Circle1);
var Radius2=50;
var Circle2=new Kinetic.Circle({
x: 75,
y: 175,
radius: Radius2,
fill: 'blue',
stroke: 'black',
strokeWidth: 2
});
layer.add(Circle2);
var message = new Kinetic.Text({
x: 10,
y: 15,
text: "",
fontSize: 30,
fontFamily: 'Calibri',
fill: 'green'
});
layer.add(message);
var instructions = new Kinetic.Text({
x: 10,
y: 285,
text: "Drag green on top of blue",
fontSize: 18,
fontFamily: 'Calibri',
fill: 'green'
});
layer.add(instructions);
layer.draw();
Circle1.on("dragmove",function(){
if(theyAreColliding(Circle1,Circle2)){
message.setText("Collision Detected!");
Circle1.setFill("red");
layer.draw();
}else{
}
});
function theyAreColliding(c1,c2){
var dx=c1.getX()-c2.getX();
var dy=c1.getY()-c2.getY();
var radiiSum=c1.getRadius()+c2.getRadius();
console.log(dx+"/"+dy+": "+radiiSum);
return((dx*dx+dy*dy)<radiiSum*radiiSum);
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
I'm having trouble creating an HTML5 canvas in which a an image is present, a shape is present, and the shape is draggable on the same stage. My gut tells me that I need to create multiple layers or multiple stages/canvases. Then have one be regular and the other be Kinetic. I've found some code for draggable shapes, code for displaying images and shapes, and I think my problem only lies in the implementation of the syntax. Here's the 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-v3.10.0.js"></script>
<script>
window.onload = function() {
var stage = new Kinetic.Stage({
container: "container",
width: 578,
height: 200
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
});
var layer1 = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function() {
var image = new Kinetic.Image({
x: stage.getWidth() / 2 - 53,
y: stage.getHeight() / 2 - 59,
image: imageObj,
width: 106,
height: 118
});
layer1.add(image);
stage.add(layer1);
// add cursor styling
box.on("mouseover", function() {
document.body.style.cursor = "pointer";
});
box.on("mouseout", function() {
document.body.style.cursor = "default";
});
layer.add(box);
stage.add(layer);
imageObj.src = "http://www.html5canvastutorials.com/demos/assets/yoda.jpg";
};
</script>
</head>
<body onmousedown="return false;">
<div id="container"></div>
</body>
</html>
Try this website: w3shools.com/html5/html5_draganddrop.asp