I am using the latest kineticjs.(v.3.10)
Here is the problem
I am using a single function to send images to the canvas which are outside the canvas on click.
I am making the images draggable and all..
I have also added a remove image function on double click.
when I double click on any image..
the last added image gets removed and after that if I try to click on some other image..
I get this error: TypeError: this.children[child.index] is undefined
Here is a little code.:
Using this function to fetch the path from another file using ajax
function loadajax(imgpath,imgid){
sources = {
yoda1 : imgpath,
};
loadImages(sources,initStage1);
};
Sources function:----
function loadImages(sources, callback){
var images = {};
var loadedImages = 0;
var numImages = 0;
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];
}
}
Here is the function that I'm using to remove/drag and drop/etc..
function initStage1(images){
yodaGroup1 = new Kinetic.Group({
x: 100,
y: 110,
draggable: true,
});
layery = new Kinetic.Layer();
layery.add(yodaGroup1);
stage.add(layery);
var yoda1 = new Kinetic.Image({
image: images.yoda1,
x: 0,
y: 0,
width: 100,
height: 120,
name:"image",
detectionType:"Pixel"
});
yodaGroup1.add(yoda1);
yodaGroup1.on("dragstart", function() {
yodaGroup1.moveToTop();
layery.draw();
});
yodaGroup1.on("dblclick dbltap", function() {
layery.remove(yodaGroup1);
layery.draw();
});
yodaGroup1.on("dragend", function() {
layery.draw();
yoda1.saveImageData();
});
addAnchor(yodaGroup1,0, 0, "topLeft");
addAnchor(yodaGroup1, 100, 0, "topRight");
addAnchor(yodaGroup1, 100, 120, "bottomRight");
addAnchor(yodaGroup1, 0, 120, "bottomLeft");
stage.draw();
yoda1.saveImageData();
}
NOW according to this function
I should be able to add the images to the canvas(which is working fine)
Should be able to move one image over another when I drag it (.ie.moveToTop function)_Not working
Should be able to remove the images on double click(working only for the latest added image)
Please help
Thanks
layery.remove(yodaGroup1);
refers to this function :
remove() remove layer from stage
http://www.kineticjs.com/docs/symbols/Kinetic.Layer.php#remove
There is no function to remove only one node contained in the layer :/
To remove a node contained in a layer just use this:
node.remove();
So in your case you would do:
yodaGroup1.remove();
layery.draw();
http://kineticjs.com/docs/Kinetic.Image.html
Related
I'm fairly new to canvas and I'm having some issues.
I'm trying to accomplish one end goal: display two images in a single canvas; one image is the background, the other image is clipped to a PNG and appears over top.
I'm part way there but I've hit a wall and I don't know how to get past it.
I've create a jsFiddle for it at http://jsfiddle.net/jhp79yg9/
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('canvas');
var context = canvas.getContext('2d');
var sources = {
img1: 'https://scontent-iad3-1.cdninstagram.com/hphotos-xaf1/t51.2885-15/11351598_1454928098145798_1274636321_n.jpg',
img2: 'https://igcdn-photos-c-a.akamaihd.net/hphotos-ak-xaf1/t51.2885-15/11379733_1139595366067106_273993739_n.jpg',
mask: 'http://img12.deviantart.net/65e4/i/2013/003/6/6/png_floating_terrain_by_moonglowlilly-d5qb58m.png'
};
loadImages(sources, function(images) {
context.drawImage(images.img2, 0, 0, 240, 240);
context.drawImage(images.mask, 20, 95, 500, 349);
context.globalCompositeOperation = 'source-in';
context.drawImage(images.img1, 0, 0, 540, 540);
});
<canvas id="canvas" width="540" height="540"></canvas>
In this example I've reduced the size of the first image to 140x140 from 540x540 just so I can tell if it's messing up, which it is.
What's happening is that it's not showing the second image, it's showing the 'img1' variable twice instead of showing 'img2' at all.
Can anyone offer any assistance?
I also can't tell, because it's rendering the same image, which is in the foreground and which is in the background. Help there as well would be appreciated (the clipped image should be in the foreground).
Thanks!
Another approach would be to cut out the mask from the current content and then draw the background behind the current content:
loadImages(sources, function(images) {
context.drawImage(images.img2, 0, 0, 540, 540);
context.globalCompositeOperation = 'destination-out';
context.drawImage(images.mask, 20, 95, 500, 349);
context.globalCompositeOperation = 'destination-atop';
context.drawImage(images.img1, 0, 0, 540, 540);
})
http://jsfiddle.net/jhp79yg9/6/
I couldn't clearly understand what is your requirement, but making some assumptions I hope this will give you what you need
context.drawImage(images.img2, 100, 180, 350, 350);
context.globalCompositeOperation = 'destination-atop';
context.drawImage(images.mask, 100, 180, 350, 350);
context.drawImage(images.img1, 0, 0, 540, 540);
http://jsfiddle.net/jhp79yg9/5/
Below I have some code for an assignment I'm working on. Having been placed in a 2nd year course without taking foundations of JavaScript, I'm kind of in a rut.
I'm trying to place three images, and be able to call on them later with functions to change their opacity.
When I have the images placed, only one seems to want to appear at a time, and when I call to them, I'm told that they don't exist.
// Create the canvas based on the existing div for it in the HTML file
var stage = new Kinetic.Stage
({
container: 'canvasContainer',
width: 600,
height: 600
});
/* /////////////////////////////////////////////////////
C O D E F O R L O A D I N G U P I M A G E S
///////////////////////////////////////////////////// */
var characters = new Kinetic.Layer();
stage.add(characters);
window.onload = function()
{
var majoraCharacter = new Image();
majoraCharacter.src ="https://upload.wikimedia.org/wikipedia/commons/3/34/Red_star.svg"
majoraCharacter.onload = function()
{
character1= new Kinetic.Image({ x: 400, y: 300, width: 150, height: 150, offset: {x: 75, y: 75}, image: majoraCharacter});
characters.add(character1);
characters.draw();
}
}
window.onload = function()
{
var amaterasuCharacter = new Image();
amaterasuCharacter.src ="https://upload.wikimedia.org/wikipedia/commons/3/34/Red_star.svg"
amaterasuCharacter.onload = function()
{
character2= new Kinetic.Image({ x: 400, y: 200, width: 150, height: 150, offset: {x: 75, y: 75}, opacity:0.5, image: amaterasuCharacter});
characters.add(character2);
characters.draw();
}
}
window.onload = function()
{
var toothlessCharacter = new Image();
toothlessCharacter.src ="https://upload.wikimedia.org/wikipedia/commons/3/34/Red_star.svg"
toothlessCharacter.onload = function()
{
character3= new Kinetic.Image({ x: 400, y: 100, width: 150, height: 150, offset: {x: 75, y: 75}, image: toothlessCharacter});
characters.add(character3);
characters.draw();
}
}
/* /////////////////////////////////////////////////////
C A N V A S F U N C T I O N A L I T Y
///////////////////////////////////////////////////// */
// Create new layer for background images
// Create layer for character images
var character = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 100,
y: 100,
width: 150,
height: 150,
fill: 'grey',
strokeWidth: 4,
offset: {x: 75, y: 75},
});
// add the shape to the layer
character.add(rect);
// add the layer to the stage
stage.add(character);
Is there a way I can better add images to canvas?
And what is preventing them from co-existing, and being editable outside of their loading functions?
Any and all answers are greatly appreciated!
A Demo: http://jsfiddle.net/m1erickson/Bf88D/
Some KineticJS basics:
KineticJS starts with a stage.
The stage is a container for one or more layers which are added to the stage
Each layer is actually a canvas
Shapes (including images) are added to a layer.
Since you're new to javascript, here's an outline of how to structure your project
just use one window.onload and put all your javascript in that one window.onload
load all images in advance so they are available to draw on your canvas
When all the images are loaded, then create Kinetic.Image objects from them.
Here's an image loader that loads all your images in advance and then calls the start function when your images are fully loaded.
// image loader
var imageURLs=[]; // put the paths to your images here
var imagesOK=0;
var imgs=[];
imageURLs.push("");
loadAllImages(start);
function loadAllImages(callback){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
imgs.push(img);
img.onload = function(){
imagesOK++;
if (imagesOK>=imageURLs.length ) {
callback();
}
};
img.onerror=function(){alert("image load failed");}
img.crossOrigin="anonymous";
img.src = imageURLs[i];
}
}
function start(){
// the imgs[] array holds fully loaded images
// the imgs[] are in the same order as imageURLs[]
// use the images now!
}
After you have all your images loaded, you can use this reusable function to add Kinetic Images on the layer.
You send in one image that you've loaded in advance.
You also send in the x,y position where you want the image located.
You also send in the width,height that you want the image resized to.
This function adds one new image to the layer
function addKineticImage(image,x,y,w,h){
var image = new Kinetic.Image({
x:x,
y:y,
width:w,
height:h,
image:image,
draggable: true
});
layer.add(image);
layer.draw();
}
Being new to Javascript, my understanding of this is a bit shaky. I've read a few articles and SO posts and learned quite a bit, but I'm having issues implementing some code. I'm using the KineticJS library to implement some canvas functions. I was working with a fiddle and was able to get an image to resize with the mouse control, however, when I put the code into a prototype function, resizing no longer works.
Canvas.prototype.addImg = function(){
var self = this;
var image;
var imageObj = new Image();
imageObj.onload = function() {
image = new Kinetic.Image({
x: 200,
y: 50,
image: imageObj,
width: 106,
height: 118,
draggable: false
});
self.backgroundLayer.add(image);
self.stage.add(self.backgroundLayer);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
var circle1 = new Kinetic.Circle({
x: 150,
y: 150,
radius: 10,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: false
});
circle1.isResizing = false;
circle1.on("click", function (e) {
// toggle resizing true/false
var isResizing = !this.isResizing;
this.setDraggable(isResizing);
self.backgroundLayer.setDraggable(!isResizing);
this.setFill((isResizing ? "green" : "red"));
this.isResizing = isResizing;
self.backgroundLayer.draw();
});
circle1.on("dragmove", function () {
if (this.isResizing) {
var pos = this.getPosition();
var x = pos.x;
var y = pos.y;
var rectX = image.getX();
var rectY = image.getY();
image.setSize(x - rectX, y - rectY);
self.backgroundLayer.draw();
}
});
self.backgroundLayer.add(circle1);
self.backgroundLayer.draw();
}
I am assuming the problem lies within the use of this in the function, but I'm not sure how to fix the problem. Could somebody tell me what the problem is and how I would fix this?
I can see a problem with the line that is setting the size of image:
image.setSize(x - rectX, y - rectY);
For example if x is 100 and rectX is 200, you end up with a width of '-100', which is not legal.
In the fiddle you provided, when I use constant values, the image re-sizes perfectly:
rect.setSize(200, 200);
Modified fiddle.
The solution I've come upon, is that it is not an issue of this, but the setSize() method. For some reason or another, it is not working in my local application. When I replace this for setWidth() and setHeight(), everything works the way that it should.
I am pretty new to HTML5 and was wondering how I would go about adding 10 random Facebook friends profile image's using JavaScript to an HTML5 Canvas, I have searched all over the net and have yet to find a solution that works, below is an example that I have been playing about with, I have created a Facebook App with the required permissions and can get a list of friends and their profile images I just can not figure out how to add them to the HTML5 Canvas.
<script>
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];
}
}
window.onload = function(images) {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var sources = {
canvasbackground: "prof.jpg",
userpic1: "https://graph.facebook.com/1645410740/picture",
userpic2: "https://graph.facebook.com/100000557085310/picture"
};
loadImages(sources, function(images) {
context.drawImage(images.canvasbackground, 0, 0, 422, 464);
context.drawImage(images.userpic1, 33, 28, 70, 70);
context.drawImage(images.userpic2, 130, 28, 70, 70);
});
};
</script>
Any help would be greatly appreciated.
so, yea first of all i would change the numImages to just equal sources.length, then for the callback, do
if( ! -- numImages ){ // once it gets down to 0, it's done, probably want to name it loadingImages
//done
}
put some console logs in and see what's actually happening.
i'm trying to build a bike configurator. This is my problem.
How can i load and array of images to construct the bike and another array with parts on the right from which when the user click i take the part and load it on the left where is the bike without preloading the entire canvas again. the new image will be the same width and height and should be on the same x/y position. This is how i load and array of images, but then i don't know how to swap them. I know that i can't clear the image that is loaded on the canvas and i have to draw the new one on top but i don't know how.
<script type="text/javascript" charset="utf-8">
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];
}
}
window.onload = function(images){
var canvas = document.getElementById("config");
var context = canvas.getContext("2d");
var sources = {
one: "one.jpg",
two: "two.jpg"
};
loadImages(sources, function(images){
context.drawImage(images.one, 100, 100, 180, 200);
context.drawImage(images.two, 280, 100, 180, 200);
});
};
</script>
How can i change image two.jpg on button click. The button should be outside the canvas.
button.addEventListener('click', function () {
canvas.width = canvas.width; // redraws canvas
sources.two = 'three.jpg';
// fyi, you are drawing the images as many times as there are sources.
loadImages(sources, function(images){
context.drawImage(images.one, 100, 100, 180, 200);
context.drawImage(images.two, 280, 100, 180, 200);
});
}, false);