KineticJs Adds multiple canvas instead of a single canvas with multiple layers - javascript

Im new to kineticJs and working on adding multiple images on a kinetic.stage.
At first I had successfully created a canvas using this code:
var stage = new Kinetic.Stage({
container: 'content',
width: x,
height: y
});
//declare layer
var layer = new Kinetic.Layer();
//declare image
var baseImage = new Kinetic.Image({
image: $('#img')[0];
});
layer.add(baseImage);
stage.add(layer);
but I have to add more and more images to the canvas every once in a while and so I made a function that adds another image to the canvas. My code goes like this..
function addImageLayer(){
//declare layer
var layer2 = new Kinetic.Layer();
//declare image
var image2 = new Image();
image2.src = "../resources/images/frames/newYearBunny.png";
image2.onload = function(){
var KineticImage2 = new Kinetic.Image({
x: 200,
y: 50,
image: image2,
draggable: true
});
layer2.add(KineticImage2);
stage.add(layer2);
}}
Unfortunately, Ive just added a new on top of my existing whereas I must add a layer.
Thanks

You can add new images to the existing layer
(Make sure you layer.draw() after adding new objects to a layer so they are displayed)
function addImageLayer(){
//declare image
var image2 = new Image();
image2.src = "../resources/images/frames/newYearBunny.png";
image2.onload = function(){
var KineticImage2 = new Kinetic.Image({
x: 200,
y: 50,
image: image2,
draggable: true
});
layer.add(KineticImage2);
layer.draw();
}
}

Related

KineticJS: How can I prevent Image from overlapping the stroke?

I have an image which is in a KineticJS layer. When I set a stroke with width > 1 the image will overlap the stroke at some points. Here is a JSFiddle I made:
This image shows the problem:
My Code:
var stage = new Kinetic.Stage({
container: 'container',
width: 800,
height: 900
});
var layer = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function () {
var kimage = new Kinetic.Image({
x: 10,
y: 10,
image: imageObj
});
kimage.strokeEnabled(true);
kimage.stroke("#1788a8");
kimage.strokeWidth(11);
// add the shape to the layer
layer.add(kimage);
// add the layer to the stage
stage.add(layer);
};
imageObj.src = 'https://upload.wikimedia.org/wikipedia/commons/d/da/CatBlackHearts.png';
How can I prevent the image overlapping the stroke?
A canvas stroke is always drawn half-inside and half-outside its bounding box.
The bounding box is the image size.
Therefore your blue stroke is 11/2 = 6.5 pixels inside your image.
So to have your border fully outside the image, you must draw the border separately from the image.

Bouncing image balls with KineticJS

I'm just starting out the KineticJS library and been playing about with it creating shapes etc.. However, I'm struggling to create a custom circle with my own image in it. I have tried using the fillPattern but it doesn't scale/centre correctly at all. Am I meant to use my own circle image or a rectangle image and then let KineticJS take care of things?
Just to give a bit of background: What I want is 3 balls bouncing in and then settling in place.
Any advice is welcome.
Sorted it... needed the offset values
var ball = new Image();
ball.src = 'ball2.jpg';
ball.height = 230;
ball.width = 230;
var stage = new Kinetic.Stage({
container: 'container',
width: 1000,
height: 1000
});
var circle = new Kinetic.Circle({
x: 300,
y: 300,
radius: 115,
fillPatternImage: ball,
fillPatternOffset :{
x: -115,
y: -115
}
});
var layer = new Kinetic.Layer();
// add the shape to the layer
layer.add(circle);
// add the layer to the stage
stage.add(layer);
ball.onload = function () {
stage.draw();
}

How to extract an image from an other using kinetic JS?

I have an image and I need to extract and create another kinetic image from it (without modifying the original image).
The extracted image will be a rectangle, and I have the coordinates of its 4 points.
I checked on http://kineticjs.com/docs/Kinetic.Image.html if there is any function that enables to do that but didn't find anything.
I tried with the crop method:
var newImage = new Image();
newImage.onload = function () {
var roikImage = new Kinetic.Image({
x: 10,
y: 100,
image: this,
width:100,
heigth:100,
crop: {
x:0 , y:0 , width:100, heigth:100
}
});
//Here I add the image to the layer, and draw the stage
};
newImage.src= 'src/of/my/image';
but I got a small portion of the image. I couldn't figure out how to do to crop the image using the coordinates of the 4 points of the rectangle.
Any ideas?
If I understand correctly, than you are on the right track by using crop.
You can grab the image of another Kinetic Image by using the .getImage() function and then you can use the crop attribute or setCrop() and getCrop() methods to achieve what you want.
var imageObj = new Image();
imageObj.onload = function () {
var yoda = new Kinetic.Image({
x: 100,
y: 50,
image: imageObj,
width: 106,
height: 118
});
// add the shape to the layer
layer.add(yoda);
var newImage = new Kinetic.Image({
x: 300,
y: 50,
width: 100,
height: 100,
image: yoda.getImage(), //get the original image from yoda
crop: {
x:0 , y:0 , width:100, height:100
}
});
layer.add(newImage);
// add the layer to the stage
stage.add(layer);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
Change the x,y values inside crop to choose where you want to start the crop, and then set the width and height to the dimensions you would your crop size to be starting at the x,y point of the image. x:0, y:0 is the top left corner of the image.
jsfiddle

KineticJS not able to fill Polygon with Image

After updating KineticJS from v4.0.5 to v4.3.1, I can no longer fill a Polygon with an Image using this method:
polygon.setFill({
image: imageObj
});
I end up with a black background. Is there another way around this?
Attempt: I tried poly.setFillPattern(image)
jsfiddle: http://jsfiddle.net/eeSSN/
Remove "fill" config in Kinetic.Polygon.
You created thingImage but never used it.
You can use "setFillPatternImage"
You have to call stage.draw inside iamge.onload
Code:
var stage = new Kinetic.Stage({
container: 'canvas',
width: 600,
height: 600
});
var layer = new Kinetic.Layer();
// Outline
var poly = new Kinetic.Polygon({
points: [0, 0, 400, 0, 400, 400, 0, 400],
//fill: 'red',
stroke: '#000',
strokeWidth: 0,
name: 'poly',
draggable: false
});
var imageObj = new Image();
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
imageObj.onload = function() {
poly.setFillPatternImage(imageObj);
stage.draw();
}
layer.add(poly);
stage.add(layer);
http://jsfiddle.net/lavrton/eeSSN/1/

Is it possible to use several images as the Google Maps v3 MarkerImage?

I want a map marker composed of three images. Two images will be the same across all markers where one is variable. There doesn't seem to be a way to specify multiple images on the MarkerImage class. The only way that I can think of is to draw all the images to a canvas then outputting it as a png dataURL for the MarkerImage class. That seems like overkill though.
I don't think it is possible with three separate images.
If two of the images are always the same I guess you could combine them into one and store it in the icon property and then use the variable image in the shadow property or vise versa (the icon will always be on top of the shadow). You just need to manipulate the size and position of the MarkerImage objects.
working example: http://jsfiddle.net/mG4uz/1/
var image1 = new google.maps.MarkerImage(
'http://google-maps-icons.googlecode.com/files/sailboat-tourism.png',
new google.maps.Size(45, 90), //adjust size of image placeholder
new google.maps.Point(0, 0), //origin
new google.maps.Point(0, 25) //anchor point
);
var image2 = new google.maps.MarkerImage(
'http://google-maps-icons.googlecode.com/files/sailboat-tourism.png',
new google.maps.Size(45, 45),
new google.maps.Point(0, 0),
new google.maps.Point(0, 0)
);
var marker = new google.maps.Marker({
position: centerPosition,
map: map,
icon: image1,
shadow:image2
});
I would try to define a new class which would inherit from google.maps.MarkerImage that would allow it and then just call marker.setIcon() with this object.
Also have a look here and here.
Yes, you can use multiple images and set them as one image for each Marker Icon in your array of the map markers.
What's more important is that you can use images that are on a remote server.
For example, in my case, I loaded an array of sites that each has an image for the site, so I'm merging an image of a marker with the image of the site (received from server).
Here is my solution:
mergeImages(element) {
var canvas: HTMLCanvasElement = this.canvas.nativeElement;
var context = canvas.getContext('2d');
let img1 = new Image();
let img2 = new Image();
img1.onload = function () {
canvas.width = img1.width;
canvas.height = img1.height;
img2.crossOrigin = 'anonymous';
img2.src = element.info.image || './assets/img/markers/markerIcon42.png';
};
img2.onload = () => {
context.clearRect(0, 0, canvas.width, canvas.height);
context.globalAlpha = 1.0;
context.drawImage(img1, 0, 0);
context.globalAlpha = 1; //Remove if pngs have alpha
context.globalCompositeOperation = 'destination-over';
if (element.info.image === null) {
context.drawImage(img2, 11, 4, 42, 42);
} else {
context.drawImage(img2, 15, 7, 35, 35);
}
var dataURL = canvas.toDataURL('image/png', 1.0);
console.log(dataURL);
this.markers.push({
lat: element.info.location.latitude,
lng: element.info.location.longitude,
controllerInfo: element.info,
icon: {
url: dataURL,
labelOrigin: { x: 32, y: -10 },
scaledSize: {
width: 64,
height: 64
},
origin: { x: 0, y: 0 },
anchoriconAnchor: { x: 7, y: 7 },
},
controllerStaus: element.status,
label: {
text: element.info.siteName,
color: "#ED2C2C",
fontWeight: "500",
fontSize: "14px"
}
});
console.log(this.markers);
};
img1.src = './assets/img/markers/map-marker64.png';
}
One Important thing to add is "img2.crossOrigin = 'anonymous';" this will prevent toDataUrl cors-orign error.
This solution is good also for clustering
I hope it will help
You can use an excellent small library, RichMarker. Its documentation is here.
You can even inherit it and create a custom marker class, something like this:
Ns.Marker = function(properties) {
RichMarker.call(this, properties);
this.setContent('<div class="three-images-marker">' +
properties.NsImage1 ? '<div class="marker-image-1"><img src="'+properties.NsImage1+'"/></div>' : '' +
properties.NsImage2 ? '<div class="marker-image-2"><img src="'+properties.NsImage2+'"/></div>' : '' +
properties.NsImage3 ? '<div class="marker-image-3"><img src="'+properties.NsImage3+'"/></div>'+
'</div>');
};
Ns.Marker.prototype = Object.create(RichMarker.prototype);
And then use it like this:
var gorgeousMarker = new Ns.Marker({
position: yourMarkerLatlng,
map: yourMap,
NsImage1: 'example.com/image1.png',
NsImage2: 'example.com/image2.png',
NsImage3: 'example.com/image3.png',
});
'Ns' is whatever namespace you use, if you do.
From here on it's CSS work, you can position the images as you like.

Categories

Resources