Konva how to transform image - javascript

I follow the Documentation that Konva have.
https://konvajs.github.io/docs/select_and_transform/Basic_demo.html
and
https://konvajs.github.io/docs/sandbox/Image_Resize.html
But the problem is they only have transform demo for rectangle shape. My plan is to have it on image. But so far I cant get it right. Here's my example code.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/konvajs/konva/master/konva.min.js"></script>
<meta charset="utf-8">
<title>Konva Image Resize Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #F0F0F0;
}
</style>
</head>
<body class="col-md-12">
<div id="container" class="col-md-10">
</div>
<script>
var width = window.innerWidth;
var height = window.innerHeight;
function testFunction() {
addCanvas();
}
function update(activeAnchor) {
var group = activeAnchor.getParent();
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var image = group.get('Image')[0];
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
// update anchor positions
switch (activeAnchor.getName()) {
case 'topLeft':
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
break;
case 'bottomRight':
bottomLeft.setY(anchorY);
topRight.setX(anchorX);
break;
case 'bottomLeft':
bottomRight.setY(anchorY);
topLeft.setX(anchorX);
break;
}
image.position(topLeft.position());
var width = topRight.getX() - topLeft.getX();
var height = bottomLeft.getY() - topLeft.getY();
if (width && height) {
image.width(width);
image.height(height);
}
}
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var layer = new Konva.Layer();
stage.add(layer);
// darth vader
var darthVaderImg = new Konva.Image({
width: 200,
height: 137,
name: 'imgs'
});
// yoda
var yodaImg = new Konva.Image({
width: 93,
height: 104,
name: 'imgs'
});
var darthVaderGroup = new Konva.Group({
x: 180,
y: 50,
draggable: true,
id: 'test1',
name: 'Imgs'
});
var num = 0;
function addCanvas() {
var test = new Konva.Group({
x: 200,
y: 100,
draggable: true
});
var testImg = new Konva.Image({
width: 93,
height: 104
});
layer.add(test);
test.add(testImg);
console.log('test');
var imageObjs = new Image();
imageObjs.onload = function() {
testImg.image(imageObjs);
layer.draw();
};
imageObjs.src = './pic/test2.png';
}
layer.add(darthVaderGroup);
darthVaderGroup.add(darthVaderImg);
var yodaGroup = new Konva.Group({
x: 20,
y: 110,
draggable: true,
id: 'Imgs',
});
layer.add(yodaGroup);
yodaGroup.add(yodaImg);
var imageObj1 = new Image();
imageObj1.onload = function() {
darthVaderImg.image(imageObj1);
layer.draw();
};
imageObj1.src = './pic/test2.png';
var imageObj2 = new Image();
imageObj2.onload = function() {
yodaImg.image(imageObj2);
layer.draw();
};
imageObj2.src = './pic/test1.jpg';
stage.on('click', function(e) {
if (e.target === stage) {
stage.find('Transformer').destroy();
layer.draw();
return;
}
// do nothing if clicked NOT on our rectangles
if (!e.target.hasName('imgs')) {
return;
}
// remove old transformers
// TODO: we can skip it if current rect is already selected
stage.find('Transformer').destroy();
// create new transformer
var tr = new Konva.Transformer();
layer.add(tr);
tr.attachTo(e.target);
layer.draw();
});
function addTrans(e) {
}
</script>
</body>
</html>
The output
Here's the output. Whenever I click the image the transform will be out of place and will on stay in 1 place.

I finally figure it out. Turn out I place the draggable in the wrong place. I put the draggable into the Konva.Image instead in the group.
Thanks

Related

Collision detection algorithm in Javascript

I want to create a function that make collision detection with two objects in canvas using JavaScript. I have coin objects and piggy bank objects. I am trying to create a function that when the coin touches the piggy bank, the coin object will disappear. Can anyone help me to explain the algorithm of the collision detection please?
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/konva#4.0.5/konva.min.js"></script>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
body{
margin:0;
padding: 0;
overflow: hidden;
background-color: lightyellow;
}
.konvajs-content{
background-color: aliceblue;
margin: 5%;
border: solid 5px gray;
}
#stage-parent{
width: 100%;
}
</style>
</head>
<body>
<div id="stage-parent">
<div id="container"></div>
</div>
<script>
var stageWidth = 1200;
var stageHeight = 1200;
var stage = new Konva.Stage({
width: stageWidth,
height: stageHeight,
container: 'container'
});
var layer = new Konva.Layer();
stage.add(layer);
//1yen
var ichiYenImg = new Konva.Image({
x:20,
y:20,
width:100,
height: 100,
draggable: true
});
layer.add(ichiYenImg);
//5yen
var goYenImg = new Konva.Image({
x:200,
y:20,
width:100,
height: 100,
draggable: true
});
layer.add(goYenImg);
//10yen
var jyuYenImg = new Konva.Image({
x:200,
y:50,
width:100,
height: 100,
draggable: true
});
layer.add(jyuYenImg);
//50yen
var gojyuYenImg = new Konva.Image({
x:20,
y:50,
width:100,
height: 100,
draggable: true
});
layer.add(gojyuYenImg);
//500yen
var gohyakuYenImg = new Konva.Image({
x:100,
y:20,
width:100,
height: 100,
draggable: true
});
layer.add(gohyakuYenImg);
//100yen
var hyakuYenImg = new Konva.Image({
x:100,
y:50,
width:100,
height: 100,
draggable: true
});
layer.add(hyakuYenImg);
//piggy bank 1yen
var ichiYenpiggyImg = new Konva.Image({
x:100,
y:500,
width:100,
height: 100,
draggable: false
});
layer.add(ichiYenpiggyImg);
//piggy bank 5yen
var goYenpiggyImg = new Konva.Image({
x:450,
y:500,
width:100,
height: 100,
draggable: false
});
layer.add(goYenpiggyImg);
//piggy bank 10yen
var jyuYenpiggyImg = new Konva.Image({
x:800,
y:500,
width:100,
height: 100,
draggable: false
});
layer.add(jyuYenpiggyImg);
//piggy bank 50yen
var gojyuYenpiggyImg = new Konva.Image({
x:100,
y:650,
width:100,
height: 100,
draggable: false
});
layer.add(gojyuYenpiggyImg);
//piggy bank 100yen
var hyakuYenpiggyImg = new Konva.Image({
x:450,
y:650,
width:100,
height: 100,
draggable: false
});
layer.add(hyakuYenpiggyImg);
//piggy bank 500yen
var gohyakuYenpiggyImg = new Konva.Image({
x:800,
y:650,
width:100,
height: 100,
draggable: false
});
layer.add(gohyakuYenpiggyImg);
//1yen
var imageObj1 = new Image();
imageObj1.onload = function(){
ichiYenImg.image(imageObj1);
layer.draw();
};
var sourceImg1 = "https://illustrain.com/img/work/2016/illustrain09-okane5.png";
drawImage(sourceImg1, ichiYenImg);
//5yen
var sourceImg2 = "https://illustrain.com/img/work/2016/illustrain09-okane7.png";
drawImage(sourceImg2, goYenImg);
//10yen
var sourceImg3 = "https://illustrain.com/img/work/2016/illustrain09-okane6.png";
drawImage(sourceImg3, jyuYenImg);
//50yen
var sourceImg4 = "https://illustrain.com/img/work/2016/illustrain02-money04.png";
drawImage(sourceImg4, gojyuYenImg);
//100yen
var sourceImg5 = "https://illustrain.com/img/work/2016/illustrain09-okane8.png";
drawImage(sourceImg5, hyakuYenImg);
//500yen
var sourceImg6 = "https://illustrain.com/img/work/2016/illustrain02-money06.png";
drawImage(sourceImg6, gohyakuYenImg);
//piggy1yen
var sourceImg7 = "https://user-images.githubusercontent.com/31402838/63416628-a322b080-c3b4-11e9-96e8-e709ace70ec1.png";
drawImage(sourceImg7, ichiYenpiggyImg);
//piggy5yen
var sourceImg8 = "https://user-images.githubusercontent.com/31402838/63416629-a322b080-c3b4-11e9-94a8-eb6c008d4584.png";
drawImage(sourceImg8, goYenpiggyImg);
//piggy10yen
var sourceImg9 = "https://user-images.githubusercontent.com/31402838/63416630-a322b080-c3b4-11e9-95ef-a04228fc3c0d.png";
drawImage(sourceImg9, jyuYenpiggyImg);
//piggy50yen
var sourceImg10 = "https://user-images.githubusercontent.com/31402838/63416631-a322b080-c3b4-11e9-9e99-43061e2eaf2c.png";
drawImage(sourceImg10, gojyuYenpiggyImg);
//piggy100yen
var sourceImg11 = "https://user-images.githubusercontent.com/31402838/63416626-a322b080-c3b4-11e9-9ff6-00b3babf3fe9.png";
drawImage(sourceImg11, hyakuYenpiggyImg);
//piggy500yen
var sourceImg12 = "https://user-images.githubusercontent.com/31402838/63416627-a322b080-c3b4-11e9-86c4-4edf13a57063.png";
drawImage(sourceImg12, gohyakuYenpiggyImg);
// This will draw the image on the canvas.
function drawImage(source, konvaImage) {
var image = new Image();
image.src = source;
image.onload = function() {
konvaImage.image(image);
layer.draw();
}
}
//use event delegation to update pointer style
layer.on('mouseover', function(evt){
var shape = evt.target;
document.body.style.cursor = 'pointer';
shape.strokeEnabled(false);
layer.draw();
});
layer.on('mouseout', function(evt){
var shape = evt.target;
document.body.style.cursor = 'default';
shape.strokeEnabled(false);
layer.draw();
});
function fitStageIntoParentContainer(){
var container = document.querySelector('#stage-parent');
var containerWidth = container.offsetWidth;
var scale = containerWidth / stageWidth;
stage.width(stageWidth * scale);
stage.height(stageHeight * scale);
stage.scale({x:scale, y: scale});
stage.draw();
}
fitStageIntoParentContainer();
window.addEventListener('resize', fitStageIntoParentContainer);
</script>
</body>
</html>
First thing when debugging these problems is to reduce your code to a small example.
Once you have that, then you can go into more complicated things.
Below is your code with working collision:
var stage = new Konva.Stage({
width: 400,
height: 200,
container: 'container'
});
var layer = new Konva.Layer();
stage.add(layer);
layer.on('dragmove', function(e) {
var target = e.target;
var targetRect = e.target.getClientRect();
layer.children.each(function(obj) {
if (obj === target) {
return;
}
if (haveIntersection(obj.getClientRect(), targetRect)) {
alert("Intersection")
}
});
});
function haveIntersection(r1, r2) {
return !(
r2.x > r1.x + r1.width/2 ||
r2.x + r2.width/2 < r1.x ||
r2.y > r1.y + r1.height/2 ||
r2.y + r2.height/2 < r1.y
);
}
// This will draw the image on the canvas.
function drawImage(source, konvaImage) {
layer.add(konvaImage);
var image = new Image();
image.src = source;
image.onload = function() {
konvaImage.image(image);
layer.draw();
}
}
//1yen
var ichiYenImg = new Konva.Image({
x: 20,
y: 20,
width: 100,
height: 100,
draggable: true
});
var sourceImg1 = "https://illustrain.com/img/work/2016/illustrain09-okane5.png";
drawImage(sourceImg1, ichiYenImg);
//piggy bank 1yen
var ichiYenpiggyImg = new Konva.Image({
x: 300,
y: 100,
width: 100,
height: 100,
draggable: false
});
var sourceImg7 = "https://user-images.githubusercontent.com/31402838/63416628-a322b080-c3b4-11e9-96e8-e709ace70ec1.png";
drawImage(sourceImg7, ichiYenpiggyImg);
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/konva#4.0.5/konva.min.js"></script>
</head>
<body>
<div id="stage-parent">
<div id="container"></div>
</div>
</body>
</html>
The key here is the function haveIntersection there we assume that the collision boxes are squares 1/2 the with and height of the objects.
The conditions inside that functions are:
Is the RIGHT edge of r1 to the RIGHT of the LEFT edge of r2? OR
Is the LEFT edge of r1 to the LEFT of the RIGHT edge of r2? OR
Is the BOTTOM edge of r1 BELOW the TOP edge of r2? OR
Is the TOP edge of r1 ABOVE the BOTTOM edge of r2?
There are more details here:
http://jeffreythompson.org/collision-detection/rect-rect.php

How to propagate a click event from a shape in the Upper layer to an image in the Lower Layer using KonvaJS?

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>

Javascript: No response after preload of images

Okay, I now tried to load two Kinetic images, but it still doesn't work. I also tried to put it on another layer and on another stage. Nothing helped. But with one image everything is fine.
var stage = new Kinetic.Stage({
container: 'container',
width: 1600,
height: 1000
});
var layer = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function() {
var yoda = new Kinetic.Image({
x: 200,
y: 50,
image: imageObj,
width: 106,
height: 118
});
var imageObj2 = new Image();
imageObj2.onload = function() {
var vader = new Kinetic.Image({
x: 400,
y: 200,
image: imageObj2,
width: 206,
height: 218
});
// add the shape to the layer
layer.add(yoda);
layer.add(vader);
// add the layer to the stage
stage.add(layer);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
imageObj2.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
OLD:
This is a sample code from http://www.html5canvastutorials.com/. I want to load two (or more) images and animate them both by clicking one button. Everything works fine with one picture, but this code confuses me. After the loadImages function is called there is no more reaction, even an alert isn't displayed. Where and how can I place my anim function?(I will implement the other animation later) Thanks for your ideas!
CSS
body {
margin: 0px;
padding: 0px;
}
#buttons {
position: absolute;
top: 50px;
left: 100px;
}
#buttons > input {
padding: 10px;
display: block;
margin-top: 5px;
}
HTML
<div id="container"></div>
<div id="buttons">
<input type="button" id="start" value="Start">
</div>
<canvas id="myCanvas" width="578" height="200"></canvas>
JS
document.getElementById('start').addEventListener('click', function() {
anim.start(); //button should start animation
}, false);
function loadImages(sources, callback) {
var images = {};
var loadedImages = 0;
var numImages = 0;
// get num of sources
for(var src in sources) {
numImages++;
}
for(var src in sources) {
images[src] = new Image();
images[src].onload = function() {
if(++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var sources = {
darthVader: 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg',
yoda: 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg'
};
loadImages(sources, function(images) {
context.drawImage(images.darthVader, 100, 30, 200, 137);
context.drawImage(images.yoda, 150, 55, 93, 104);
});
var angularSpeed = 360 / 4; //from this line on it's like the js-code doesn't exist
var anim = new Kinetic.Animation(function(frame) { exist
var angleDiff = frame.timeDiff * angularSpeed / 1000;
images.yoda.rotate(angleDiff); //sources. instead images.?
}, layer);
You are mixing html5 canvas code with KineticJS library code.
You must create Kinetic.Image objects from each of your image objects.
Only then you can use Kinetic.Animation to animate them into rotation.

kineticjs: rotate image by certain angle and stop

I'm completely new in HTML and kineticjs and I want to create an animation, which rotates an image around a certain point and by a certain angle. Then it has to stop.
Later I want to implement a way to control the angle by clicking a button. But to the first problem: This is the code so far:
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.0.min.js"> </script>
<script defer="defer">
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function() {
var yoda = new Kinetic.Image({
x: 200,
y: 50,
image: imageObj,
width: 106,
height: 118,
//offset: [x:250, y: 100]
});
/*var imageObj2 = new Image();
imageObj.onload = function() {
var background = new Kinetic.Image({
x: 200,
y: 50,
image: imageObj,
width: 106,
height: 118,
}); */
// add the shape to the layer
layer.add(yoda);
//layer.add(background)
// add the layer to the stage
stage.add(layer);
var angularSpeed = 360 / 4;
var anim = new Kinetic.Animation(function(frame) {
var angleDiff = frame.timeDiff * angularSpeed / 1000;
yoda.rotate(angleDiff);
}, layer);
anim.start();
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
//other image source
</script>
</body>
</html>
Source: http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-image-tutorial/
So how can I make the animation stop after - say - 50°?
Thanks for your help!
You can use Tween:
var tweaktween = new Kinetic.Tween({
node : yoda,
rotation : 50,
duration: 1
});
tween.start();
demo: http://jsfiddle.net/lavrton/2DDtW/

Giving a canvas using kinetic an id

I am trying to download a canvas to my computer as an image, I can get this working fine while inspecting the element within chrome by editing the generated html via kinetic.js, simply adding id="canvas" to the canvas. However I cannot find how to do this through the code itself.
I know that each time I create a new kinetic layer I am essentially creating a new canvas class but am unsure of how to add an id or if it is do-able.
Any help would be greatly appreciated,
Melissa
HTML:
<!DOCTYPE HTML>
<html>
<head>
<title>Test Page</title>
<style>
body {
margin: 0px;
padding: 0px;
}
canvas {
border: 1px solid #9C9898;
}
</style>
<script src="kinetic-v3.9.7.min.js"></script>
<script src="canvas2image.js"></script>
<script src="base64.js"></script>
<script src="script.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"> </script>
<script>
$( document ).ready(function() {
function downloadCanvas(link, canvasId, filename) {
link.href = document.getElementById(canvasId).toDataURL();
link.download = filename;
}
document.getElementById('download').addEventListener('click', function() {
downloadCanvas(this, 'canvas', 'test.png');
}, false);
});
$(function() {
$("canvas").attr("id","canvas");
});
</script>
</head>
<body onmousedown="return false;">
<div id="right" style="float: right;">
<a id="download" href="#">Download as image</a>
<input type='file' onchange="readURL(this);" />
<img src="#" name="addimg" id="addimg" onClick="addClickedImage('addimg')" /><br /><br />
download<br /><br />
clear
</div><!-- #right -->
<div role="main">
<div id="container">
</div><!-- #container -->
</div><!-- main -->
</body>
JS
var stage;
var layer;
var selected;
var wasSelected;
var haveBackground; // first dragged image sets stage size
/*
* Set up canvas stage and layer
*/
function initCanvas(canvas) {
stage = new Kinetic.Stage({
container: canvas,
width: 850,
height: 500
});
layer = new Kinetic.Layer();
stage.add(layer);
stage.draw();
}
/*
* Clear canvas, start again
*/
function clearCanvas() {
layer.removeChildren();
layer.draw();
haveBackground = false;
}
/*
* Resize
*/
function resize(group, activeAnchor) {
var tl = group.get(".tl")[0];
var tr = group.get(".tr")[0];group
var br = group.get(".br")[0];
var bl = group.get(".bl")[0];
var handle = group.get(".handle")[0];
var ghost = group.get(".ghost")[0];
var flip = group.get(".flip")[0];
var image = group.get(".image")[0];
switch (activeAnchor.attrs.name) {
case "tl":
bl.setPosition(tl.attrs.x, br.attrs.y);
tr.setPosition(br.attrs.x, tl.attrs.y);
break;
case "tr":
br.setPosition(tr.attrs.x, bl.attrs.y);
tl.setPosition(bl.attrs.x, tr.attrs.y);
break;
case "bl":
br.setPosition(tr.attrs.x, bl.attrs.y);
tl.setPosition(bl.attrs.x, tr.attrs.y);
break;
case "br":
bl.setPosition(tl.attrs.x, br.attrs.y);
tr.setPosition(br.attrs.x, tl.attrs.y);
break;
}
handle.setPosition((tr.attrs.x + tl.attrs.x) / 2, tl.attrs.y - 20);
ghost.setPosition(handle.getPosition());
flip.setPosition((tr.attrs.x + tl.attrs.x) / 2, bl.attrs.y + 20);
image.setPosition(tl.attrs.x, tl.attrs.y);
image.attrs.width = tr.attrs.x - tl.attrs.x;
image.attrs.height = bl.attrs.y - tl.attrs.y;
}
/*
* Rotate
*/
function rotate(group) {
var c = group.getAbsolutePosition();
var p0 = {x: c.x, y: c.y - 50};
var p1 = stage.getUserPosition();
var p0c = Math.sqrt(Math.pow(c.x-p0.x,2) + Math.pow(c.y-p0.y,2)); // p0->c (b)
var p1c = Math.sqrt(Math.pow(c.x-p1.x,2) + Math.pow(c.y-p1.y,2)); // p1->c (a)
var p0p1 = Math.sqrt(Math.pow(p1.x-p0.x,2) + Math.pow(p1.y-p0.y,2)); // p0->p1 (c)
var deg = Math.acos((p1c*p1c+p0c*p0c-p0p1*p0p1)/(2*p1c*p0c));
// fix for negative rotation
if(p1.x < c.x) {
deg = (360 * (Math.PI/180)) - deg;
}
group.setRotation(deg);
}
/*
* Flip
*/
function flip(group) {
group.attrs.scale.x = group.attrs.scale.x * -1;
}
/*
* Fix center offset (due to resizing from a corner)
*/
function fixCenterOffset(group) {
var image = group.get(".image")[0]
var currentOffset = group.getCenterOffset();
var currentPosition = group.getPosition();
var newOffset = {x: image.attrs.width /2, y: image.attrs.height /2};
var newPosition = {
x: currentPosition.x - (currentOffset.x - newOffset.x),
y: currentPosition.y - (currentOffset.y - newOffset.y)
}
group.setCenterOffset(newOffset);
group.setPosition(newPosition);
layer.draw();
}
/*
* Add an image plus anchors to the canvas using group
*/
function initImage(img, type) {
var kimggroup = initNormalImage(img);
layer.add(kimggroup);
stage.add(layer);
// Draw the img
stage.draw();
}
/*
* Add normal image
*/
function initNormalImage(img) {
var kimggroup = new Kinetic.Group({
x: stage.attrs.width / 2,
y: stage.attrs.height / 2,
draggable: true,
centerOffset: [img.width/2, img.height/2]
});
// Make the img and add it to the group
var kimg = new Kinetic.Image({
x: 0,
y: 0,
image: img,
width: img.width,
height: img.height,
name: "image"
});
kimggroup.add(kimg);
// Add anchors for resizing and rotation
addAnchor(kimggroup, 0, 0, "tl");
addAnchor(kimggroup, img.width, 0, "tr");
addAnchor(kimggroup, img.width, img.height, "br");
addAnchor(kimggroup, 0, img.height, "bl");
addAnchor(kimggroup, img.width / 2, -20, "handle");
addAnchor(kimggroup, img.width / 2, -20, "ghost");
addAnchor(kimggroup, img.width / 2, img.height +20, "flip");
// On click make the image selected
kimggroup.on("mousedown", function() {
wasSelected = selected;
selected = this;
updateSelected();
this.moveToTop();
stage.draw();
});
kimg.on("mouseover", function() {
document.body.style.cursor = "move";
});
kimg.on("mouseout", function() {
document.body.style.cursor = "default";
});
// Double click to remove
kimg.on("dblclick dbltap", function() {
layer.remove(kimggroup);
layer.draw();
});
return kimggroup;
}
/*
* Create anchor and add to group
*/
function addAnchor(group, x, y, name) {
var config = {
x: x,
y: y,
stroke: "#000",
fill: "#000",
strokeWidth: 1,
radius: 4,
name: name,
draggable: true
}
switch (name) {
case "handle":
config.draggable = false;
var anchor = addRotateAnchor(group, config);
break;
case "ghost":
config.stroke = "#993333";
var anchor = addRotateGhostAnchor(group, config);
break;
case "flip":
config.stroke = "#0000ff";
config.draggable = false;
var anchor = addFlipAnchor(group, config);
break;
default:
var anchor = addResizeAnchor(group, config);
break;
}
anchor.hide();
group.add(anchor);
}
/*
* Set up resize anchor
*/
function addResizeAnchor(group, config) {
var anchor = new Kinetic.Circle(config);
anchor.on("dragmove", function() {
resize(group, this);
layer.draw();
});
anchor.on("mousedown touchstart", function() {
group.draggable(false);
this.moveToTop();
});
anchor.on("dragend", function() {
fixCenterOffset(group);
group.draggable(true);
layer.draw();
});
anchor.on("mouseover", function() {
var layer = this.getLayer();
document.body.style.cursor = "pointer";
this.setStrokeWidth(3);
layer.draw();
});
anchor.on("mouseout", function() {
var layer = this.getLayer();
document.body.style.cursor = "default";
this.setStrokeWidth(2);
layer.draw();
});
return anchor;
}
/*
* Set up rotation anchor
*/
function addRotateAnchor(group, config) {
var anchor = new Kinetic.Circle(config);
anchor.on("mouseover", function() {
var layer = this.getLayer();
document.body.style.cursor = "pointer";
this.setStrokeWidth(3);
layer.draw();
});
anchor.on("mouseout", function() {
var layer = this.getLayer();
document.body.style.cursor = "default";
this.setStrokeWidth(2);
layer.draw();
});
return anchor;
}
/*
* Set up rotation ghost anchor
*/
function addRotateGhostAnchor(group, config) {
var anchor = new Kinetic.Circle(config);
anchor.on("dragmove", function() {
rotate(group);
layer.draw();
});
anchor.on("mousedown touchstart", function() {
group.draggable(false);
this.moveToTop();
});
anchor.on("dragend", function() {
var handle = group.get(".handle")[0];
this.setPosition(handle.getPosition());
group.draggable(true);
layer.draw();
});
anchor.on("mouseover", function() {
var layer = this.getLayer();
document.body.style.cursor = "pointer";
this.setStrokeWidth(3);
layer.draw();
});
anchor.on("mouseout", function() {
var layer = this.getLayer();
document.body.style.cursor = "default";
this.setStrokeWidth(2);
layer.draw();
});
return anchor;
}
/*
* Set up flip anchor
*/
function addFlipAnchor(group, config) {
var anchor = new Kinetic.Circle(config);
anchor.on("mousedown touchstart", function() {
flip(group);
layer.draw();
});
anchor.on("mouseover", function() {
var layer = this.getLayer();
document.body.style.cursor = "pointer";
this.setStrokeWidth(3);
layer.draw();
});
anchor.on("mouseout", function() {
var layer = this.getLayer();
document.body.style.cursor = "default";
this.setStrokeWidth(2);
layer.draw();
});
return anchor;
}
/*
* Show anchors only when group selected
*/
function updateSelected() {
// Deselect the old img if there was any
if (wasSelected) {
wasSelected.get(".tl")[0].hide();
wasSelected.get(".tr")[0].hide();
wasSelected.get(".br")[0].hide();
wasSelected.get(".bl")[0].hide();
wasSelected.get(".handle")[0].hide();
wasSelected.get(".ghost")[0].hide();
wasSelected.get(".flip")[0].hide();
}
// Select the new image
selected.get(".tl")[0].show();
selected.get(".tr")[0].show();
selected.get(".br")[0].show();
selected.get(".bl")[0].show();
selected.get(".handle")[0].show();
selected.get(".ghost")[0].show();
selected.get(".flip")[0].show();
}
/*
* Add clicked images to the canvas
*/
function addClickedImage(name) {
console.log(document.getElementById(name).getAttribute("src"));
var newImg = new Image();
newImg.src = document.getElementById(name).getAttribute("src");
//var img = document.getElementById(name);
initImage(newImg, "normal");
}
/*
* Listen for images dragged into canvas and add them
*/
function setupDragAndDrop() {
stage.content.addEventListener("dragover", function (evt) {
evt.preventDefault();
}, false);
// Handle dropped image file - only Firefox and Google Chrome
stage.content.addEventListener("drop", function (evt) {
dragImg = new Image();
var files = evt.dataTransfer.files;
if (files.length > 0) {
var file = files[0];
if (typeof FileReader !== "undefined" && file.type.indexOf("image") != -1) {
var reader = new FileReader();
reader.onload = function (evt) {
dragImg.src = evt.target.result;
};
reader.readAsDataURL(file);
dragImg.onload = function(){
var type = "normal";
initImage(this, type);
}
}
}
evt.preventDefault();
}, false);
}
window.onload = function() {
initCanvas("container");
setupDragAndDrop();
};
//upload images
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#addimg')
.attr('src', e.target.result)
.width(150)
.height(200);
};
reader.readAsDataURL(input.files[0]);
}
}

Categories

Resources