Reputation: 1397
How can we bind (two-way) KineticJS Objects to some data with AngularJS ?
For example, bind a Kinetic Shape's position to a variable or textbox.
I've figured out how to do this without AngularJS :
(using KineticJS with jQuery)
box.on('dragmove', function() {
$('#pos_x').val( myShape.getX() );
$('#pos_y').val( myShape.getY() );
});
$('#pos_x').change(function() {
var x = parseInt( $('#pos_x').val() );
var y = parseInt( $('#pos_x').val() );
box.setPosition( x, y );
});
// and the same for $('#pos_y');
Code explanation:
There are a box and two textboxes.
When the box is dragged, box's coordinates will show on both textboxes.
When both textboxes' values are changed, the box's position will also change
but I wanted to know how to do that with AngularJS
(IMO, it will be much easier when you have a large number of objects, each with its own textboxes)
Upvotes: 3
Views: 2716
Reputation: 105035
You have a few integration problems when trying to combine KineticJS with AngularJS
AngularJS is great at binding DOM elments.
But KineticJS objects are not DOM elements—they are just pixels on the canvas.
So AngularJS can’t control Kinetic objects directly.
To get Kinetic objects to move in response to text-input changes, you could use an AngularJS controller and make calls to the Kinetic object’s setX/setY.
To get text-input values to change as Kinetic objects are dragged, you might call the AngularJS controller from within a Kinetic dragmove event handler.
A complication is that by default, both Angular and Kinetic will want to control mouse events for their own purposes.
I'm not saying it can't be done, but...
Integrating KineticJS + AngularJS is more complicated than the Kinetic + jQuery method you’ve already got.
Before you give up on Kinetic + jQuery
Check out this code that integrates your Kinetic object and text-inputs.
You can quickly create as many shape+text pairs as you need.
And each pair is automatically integrated so that either dragging or text-input will move the shape and will show the current position in the text-input.
BTW, I used jQuery here for convenience, but you could very easily convert this to pure javascript and not need any external library at all.
Here’s code and a Fiddle: http://jsfiddle.net/m1erickson/X9QsU/
<!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.0.min.js"></script>
<style>
body{background:ivory; padding:10px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:300px;
height:300px;
}
.boundXY{
width:105px;
height:23px;
color:white;
padding:5px;
border:2px solid lightgray;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 300,
height: 300
});
var layer = new Kinetic.Layer();
stage.add(layer);
// each rect,textX,textY gets a unique id
var nextId=0;
// create some rect-textInput pairs in random colors
for(var i=0;i<6;i++){
randomPair();
}
function randomPair(){
var x=parseInt(Math.random()*250);
var y=parseInt(Math.random()*250);
var w=parseInt(Math.random()*40)+10;
var h=parseInt(Math.random()*40)+10;
addRectTextPair(nextId++,x,y,w,h,randomColor(),"lightgray");
}
function addRectTextPair(id,x,y,w,h,fill,stroke){
// new kinetic rect
var rect = new Kinetic.Rect({
id:"rect"+id,
x: x,
y: y,
width: w,
height: h,
fill: fill,
stroke: stroke,
strokeWidth: 3,
draggable:true
});
rect.on('dragmove', function() {
var id=this.getId().slice(4);
$('#x'+id).val( parseInt(this.getX()) );
$('#y'+id).val( parseInt(this.getY()) );
});
layer.add(rect);
// new div with same color as kinetic rect
var div = document.createElement("div");
div.id="div"+id;
div.className="boundXY";
div.style.background = fill;
div.innerHTML = "X/Y:";
// add xy text inputs
div.appendChild(newTextInput("x"+id,x));
div.appendChild(newTextInput("y"+id,y));
// add div to body
document.body.appendChild(div);
// change rect's X when the textInputX changes
$('#x'+id).change(function(e) {
var id=e.target.id.slice(1);
var rect=layer.get("#rect"+id)[0];
rect.setX( parseInt($(this).val()) );
layer.draw();
});
// change rect's Y when the textInputY changes
$('#y'+id).change(function(e) {
var id=e.target.id.slice(1);
var rect=layer.get("#rect"+id)[0];
rect.setY( parseInt($(this).val()) );
layer.draw();
});
layer.draw();
}
function randomColor(){
return('#'+Math.floor(Math.random()*16777215).toString(16));
}
function newTextInput(id,value){
var input=document.createElement("input");
input.id=id;
input.value=value;
input.type="text";
input.style.width="25px";
input.style.marginLeft="5px";
return(input);
}
$("#oneMore").click(function(){ randomPair(); });
}); // end $(function(){});
</script>
</head>
<body>
<p>Reposition rectangles by dragging or changing X/Y</p>
<button id="oneMore">Add another Rect and TextInput pair</button>
<div id="container"></div>
</body>
</html>
Upvotes: 9