How to delete image(element) from canvas - javascript

I am developing hotel floor view using canvas with the help of kinetic js.I want to provide an option to delete current dragged,dropped image on canvas.
this is my code for only drag drop of image and not with delete option :
// get a reference to the house icon in the toolbar
// hide the icon until its image has loaded
var $house=$("#house");
$house.hide();
// get the offset position of the kinetic container
var $stageContainer=$("#container");
var stageOffset=$stageContainer.offset();
var offsetX=stageOffset.left;
var offsetY=stageOffset.top;
// create the Kinetic.Stage and layer
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
// start loading the image used in the draggable toolbar element
// this image will be used in a new Kinetic.Image
var image1=new Image();
image1.onload=function(){
$house.show();
}
image1.src="https://dl.dropboxusercontent.com/u/139992952/multple/4top.png";
// make the toolbar image draggable
$house.draggable({
helper:'clone',
});
// set the data payload
$house.data("url","house.png"); // key-value pair
$house.data("width","32"); // key-value pair
$house.data("height","33"); // key-value pair
$house.data("image",image1); // key-value pair
// make the Kinetic Container a dropzone
$stageContainer.droppable({
drop:dragDrop,
});
// handle a drop into the Kinetic container
function dragDrop(e,ui){
// get the drop point
var x=parseInt(ui.offset.left-offsetX);
var y=parseInt(ui.offset.top-offsetY);
// get the drop payload (here the payload is the image)
var element=ui.draggable;
var data=element.data("url");
var theImage=element.data("image");
// create a new Kinetic.Image at the drop point
// be sure to adjust for any border width (here border==1)
var image = new Kinetic.Image({
name:data,
x:x,
y:y,
image:theImage,
draggable: true
});
layer.add(image);
layer.draw();
}
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
#toolbar{
width:350px;
height:35px;
border:solid 1px blue;
}
<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>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.min.js"></script>
<h4>Drag from toolbar onto canvas. Then drag around canvas.</h4>
<div id="toolbar">
<img id="house" width=32 height=32 src="https://dl.dropboxusercontent.com/u/139992952/multple/4top.png"><br>
</div>
<div id="container"></div>

You can use Kinetic to image.remove(), then layer.draw() to refresh the canvas, in similar fashion to this answer.

If you want to temporarily remove an image (and later re-add it) you use:
// temporarily remove the image from the layer
yourImage.remove();
yourLayer.draw();
// and later re-add it
yourLayer.add(yourImage);
yourLayer.draw();
But if you want to permanently delete the image (and recover all its resources) you use:
// permanently delete the image and reclaim all the resources it used
yourImage.destroy();
yourLayer.draw();

Related

How to eliminate Image overlapping in canvas(kineticjs) [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am developing view of hotel floor using canvas with the help of kinetic js. But in that i am getting images overlapping each other in the canvas. help me out to eliminate that overlapping of images in the canvas.
this is my code:
// get a reference to the house icon in the toolbar
// hide the icon until its image has loaded
var $house=$("#house");
$house.hide();
// get the offset position of the kinetic container
var $stageContainer=$("#container");
var stageOffset=$stageContainer.offset();
var offsetX=stageOffset.left;
var offsetY=stageOffset.top;
// create the Kinetic.Stage and layer
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
// start loading the image used in the draggable toolbar element
// this image will be used in a new Kinetic.Image
var image1=new Image();
image1.onload=function(){
$house.show();
}
image1.src="https://dl.dropboxusercontent.com/u/139992952/multple/4top.png";
// make the toolbar image draggable
$house.draggable({
helper:'clone',
});
// set the data payload
$house.data("url","house.png"); // key-value pair
$house.data("width","32"); // key-value pair
$house.data("height","33"); // key-value pair
$house.data("image",image1); // key-value pair
// make the Kinetic Container a dropzone
$stageContainer.droppable({
drop:dragDrop,
});
// handle a drop into the Kinetic container
function dragDrop(e,ui){
// get the drop point
var x=parseInt(ui.offset.left-offsetX);
var y=parseInt(ui.offset.top-offsetY);
// get the drop payload (here the payload is the image)
var element=ui.draggable;
var data=element.data("url");
var theImage=element.data("image");
// create a new Kinetic.Image at the drop point
// be sure to adjust for any border width (here border==1)
var image = new Kinetic.Image({
name:data,
x:x,
y:y,
image:theImage,
draggable: true
});
layer.add(image);
layer.draw();
}
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
#toolbar{
width:350px;
height:35px;
border:solid 1px blue;
}
<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>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.min.js"></script>
<h4>Drag from toolbar onto canvas. Then drag around canvas.</h4>
<div id="toolbar">
<img id="house" width=32 height=32 src="https://dl.dropboxusercontent.com/u/139992952/multple/4top.png"><br>
</div>
<div id="container"></div>

Issues in design/implementation of a software with kineticjs

I want to create an application that the user will have the ability to click on a picture add points and for each (certain) pairs of points the software will draw a line between those two. The points are draggable so the line must be able to readjust itself to the new position of its two ancors. The points are pre-specified and more than 5 or 6 (it can be 10 or more)
So my design so far.
One kinetic stage
One backgroundLayer which will have the following children:
backgournImage (will hodl the image to click on)
The points aded
the lines between the points
I guess for each of the lines I will have to use a group that will contain the two ancors and the line. My problem is the following: Is there a convenient way to make sure a group is allready created for a certain pair of points so as not to create a new one when clicking on picture to add a new point?
stage.('contentClick', function(event){
//create a new point
// if a group for the specific pair of ancors exists
//add the point and draw the line
// else this is the first point of the pair we are talking about
// so create the group
//and add the new point
// add the group on the backgroundLayer
//redraw stage
);
All points can have a specific id the name of the point.
I know the code for creating points groups adding them removing them checking parents etc, just don't know how could I do it with the least manual method. I mean it's not very productive checking each and every one of the points right?
Hope I am making some sense...
One way is to track pairs of anchors that must be connected & reset their connecting lines when an anchor is dragged:
Create a Line to act as a connector.
Create a js object that holds references to the 2 anchors and the line connecting them.
Add the connection-object in an array.
When any anchor is dragged, iterate the array & reset the connectors for the anchor that was dragged.
Example code and a Demo: http://jsfiddle.net/m1erickson/b7h5dfg5/
<!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-v5.0.1.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 connectors=[];
var a1=addAnchor(50,50,'one');
var a2=addAnchor(150,50,'two');
var a3=addAnchor(100,100,'three');
addConnection(a1,a3);
addConnection(a2,a3);
function resetConnections(id){
for(var i=0;i<connectors.length;i++){
var c=connectors[i];
if(c.id1==id || c.id2==id){
c.line.points([
c.anchor1.x(),
c.anchor1.y(),
c.anchor2.x(),
c.anchor2.y()
]);
}
}
layer.draw();
}
function addAnchor(x,y,id){
var anchor=new Kinetic.Circle({
id:id,
x:x,
y:y,
radius: 10,
fill: 'red',
stroke: 'black',
strokeWidth:2,
draggable: true
});
anchor.on('dragstart',function(){
stage.find(".connector").each(function(n){ n.hide(); });
layer.draw();
})
anchor.on('dragend',function(){
stage.find(".connector").each(function(n){ n.show(); });
resetConnections(this.id());
})
layer.add(anchor);
layer.draw();
return(anchor);
}
function addConnection(anchor1,anchor2){
var line=new Kinetic.Line({
name:'connector',
points:[anchor1.x(),anchor1.y(),anchor2.x(),anchor2.y()],
stroke:'black'
});
layer.add(line);
line.moveToBottom();
layer.draw();
connectors.push({
line:line,
id1:anchor1.id(),
id2:anchor2.id(),
anchor1:anchor1,
anchor2:anchor2
});
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>Drag red anchors and connectors will follow</h4>
<div id="container"></div>
</body>
</html>

KineticJS canvas modified by CamanJS

I'm trying to apply CamanJS filter to a canvas created with KineticJS. It works:
Caman("#creator canvas", function()
{
this.lomo().render();
});
After applying a CamanJS filter I'm trying to do sth with canvas (eg. drag and move layer or just click on it), but then the canvas reverts to its original state (before applying CamanJS filter). So the question is: how to "tell" KineticJS to update cache(?) or do sth like stage.draw() to keep new canvas data?
Here is jsfiddle (click on "apply filter", when processing will be done, try to drag the star).
BTW: why is the processing so slow?
Thanks in advance.
As you've discovered, Kinetic will redraw the original image when it internally redraws.
Your Caman modified content is not used or saved.
To keep your Caman effect, you can create an offscreen canvas and instruct your Kinetic.Image to get its image from that offscreen canvas.
Then you can use Caman to filter that canvas.
The result is that Kinetic will do its internal redraws with your Caman modified canvas image.
Demo: http://jsfiddle.net/m1erickson/L3ACd/
Code Example:
<!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>
<script src="http://cdnjs.cloudflare.com/ajax/libs/camanjs/3.3.0/caman.full.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);
// create an offscreen canvas
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
// load the star.png
var img=new Image();
img.onload=start;
img.crossOrigin="anonymous";
img.src="https://dl.dropboxusercontent.com/u/139992952/stack1/star.png";
// when star.png is loaded...
function start(){
// draw the star image to the offscreen canvas
canvas.width=img.width;
canvas.height=img.height;
ctx.drawImage(img,0,0);
// create a new Kinetic.Image
// The image source is the offscreen canvas
var image1 = new Kinetic.Image({
x:10,
y:10,
image:canvas,
draggable: true
});
layer.add(image1);
layer.draw();
}
// lomo the canvas
// then redraw the kinetic.layer to display the lomo'ed canvas
$("#myButton").click(function(){
Caman(canvas, function () {
this.lomo().render(function(){
layer.draw();
});
});
});
}); // end $(function(){});
</script>
</head>
<body>
<button id="myButton">Lomo the draggable Star</button>
<div id="container"></div>
</body>
</html>

Using AngularJS with KineticJS

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)
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>

How to drag and drop a line segment (fragment only) in kinetic JS

There is a tut on line drag and drop here :
http://www.html5canvastutorials.com/kineticjs/html5-canvas-drag-and-drop-a-line-with-kineticjs/
But more interestingly how to do drag and drop a line segment (fragment only) in kinetic JS ?
There's no example for doing this.
In my use case the segment stays attached to polyline, it just changes angle. so I don't want to create another polyline with one segment only which would also be a waste of resource.
How to drag one segment of a polyline with the other segments remaining connected
You can create a series of 2-point kinetic.lines (just a start and end point).
Each new start point is the end point of the previous line
This screenshot shows the green segment being dragged and the other segments changing accordingly.
Result: A polyline made up of draggable segments.
Note: after any segment is dragged, the getX()/getY() contain the distance dragged from its original XY.
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/GrEEL/
<!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.5.min.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:300px;
height:300px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width:300,
height: 300
});
var layer = new Kinetic.Layer();
stage.add(layer);
var colors=['red','green','blue','orange'];
var lines=[];
var points=[];
points.push({x:125,y:50});
points.push({x:75,y:75});
points.push({x:200,y:200});
points.push({x:275,y:100});
for(var i=0;i<points.length-1;i++){
var p1=points[i];
var p2=points[i+1];
addSegment(i,p1.x,p1.y,p2.x,p2.y,colors[i]);
}
layer.draw();
function addSegment(i,x1,y1,x2,y2,color){
var line = new Kinetic.Line({
points: [x1,y1,x2,y2],
stroke:color,
strokeWidth: 25,
lineCap:"round",
lineJoin:"round",
draggable:true
});
line.index=i;
line.on("dragend",function(){
// get the amount of xy drag
var i=this.index;
var dx=this.getX();
var dy=this.getY();
// update the points array
var p0=points[i];
var p1=points[i+1];
p0.x+=dx;
p0.y+=dy;
p1.x+=dx;
p1.y+=dy;
// reset the dragged line
this.setPosition(0,0);
this.setPoints([p0.x,p0.y,p1.x,p1.y]);
layer.draw();
});
line.on("dragmove",function(){
// get the amount of xy drag
var i=this.index;
var dx=this.getX();
var dy=this.getY();
// adjust the ending position of the previous line
if(i>0){
var line=lines[i-1];
var pts=line.getPoints();
pts[1].x=points[i].x+dx;
pts[1].y=points[i].y+dy;
line.setPoints(pts);
}
// adjust the starting position of the next line
if(i<lines.length-1){
var line=lines[i+1];
var pts=line.getPoints();
pts[0].x=points[i+1].x+dx;
pts[0].y=points[i+1].y+dy;
line.setPoints(pts);
}
layer.draw();
});
layer.add(line);
lines.push(line);
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>

Categories

Resources