KineticJs group.setSize(300,300) not working - javascript

I am trying to change size of kinetic group. but it gives JavaScript error message.
in kinetic js document its written than setSize works with group nodes

I think the documents are a bit outdated in that respect. Groups do not have a drawFunc so they do not have a width or height. If they ever do get width and height, it will be possible to create clipped groups, which will be nice. However, as they are now, groups are simply used to define a relative x and y starting coordinate for objects contained within them. This makes moving several objects at once possible (dragging, moveTo, event handlers, etc...), but that's about it.
JsFiddle as requested
var group = new Kinetic.Group({
x: 220,
y: 40,
draggable: true
});
Just make your group draggable and add your objects to the group.

The code below will allow you to create a group with clipping properties.
Instantiate it like a group, where width and height is your clipping box.
Kinetic.Clipper = function(config) {
this._initGroup(config);
};
Kinetic.Clipper.prototype = {
_initGroup: function(config) {
this.nodeType = 'Group';
Kinetic.Container.call(this, config);
},
drawScene: function() {
if(this.isVisible()) {
var context = this.getLayer().getContext();
var width = this.getWidth(), height = this.getHeight();
context.save();
context.beginPath();
context.rect(0, 0, width, height);
context.clip();
var children = this.children, len = children.length;
for(var n = 0; n < len; n++) {
children[n].drawScene();
}
context.restore();
}
},
};
Kinetic.Global.extend(Kinetic.Clipper, Kinetic.Container);

Document is outdated or wrong.
It is not possible to directly change group size

Related

Argument 1 of CanvasRenderingContext2D.drawImage could not be converted ( attempting draw image on canvas object )

I am trying to make a cache of objects that can be used with canvas.drawImage() to display images but only draw them once. I keep getting this error, I have tried some answers found online like: canvasObject.get(0) and canvasObject[0] and unwrap(canvasObject) before putting them in the draw context, but none of that works. I cant find anything on it. hopefully someone can help. here is my code:
var canvas = full canvas that cached drawings should draw to
var temp = {};
var h = heightOfGridSquare;
var w = widthOfGridSquare;
var canvasElementForCache = document.createElement('canvas');
canvasElementForCache.width = w * 2; // so that i can draw pictures larger then single grid square
canvasElementForCache.height = h * 2;
var cachedCanvas = canvasElementForCache.getContext(ctx);
// cache drawing in app object
var cacheDrawing = function ( name ){
app.cache[name] = objectRepo[name](cachedCanvas);
};
var objectRepo = {
someObjectName: function (canv) {
var m = temp.coordinates;
canv.fillStyle = "rgba(0,0,200,0.9)";
canv.fillRect(m.x + 25, m.y + 25,50, 50); // random filler (x and y are coordinates defined in the draw object funciton )
return canv;
},
};
var drawObejectAtCoordinates = function ( x, y ) {
var px = ( x - ( w / 2 ));
var py = ( y + ( h / 2 ));
if ( app.cache[name] === undefined ){
temp.coordinates = { x:px, y:py };
cacheDrawing(name);
}
// drawing on actual canvas
canvas.drawImage( app.cache[name], px, py );
};
var render = function () {
drawObejectAtCoordinates( coordinateX, coordinateY );
// this is just a place holder, my actual code is very long and has different rendering methods..
// just know that it is being rendered ( not super important though since the error occurs at drawImage not render )
window.requestAnimationFrame(render);
}
this mostly exact, i have changed small parts for brevity.. but there is nothing left out that would be related to the issue im having. if anyone can help I would appreciate it greatly!
the error message is:
TypeError: Argument 1 of CanvasRenderingContext2D.drawImage could not be converted to any of: HTMLImageElement, HTMLCanvasElement, HTMLVideoElement.
and when I console log the contents of the cached canvas object it looks like this:
CanvasRenderingContext2D { canvas: <canvas>, globalAlpha: 1, globalCompositeOperation: "source-over", strokeStyle: "#41471d", fillStyle: "#ff8800", shadowOffsetX: 0, shadowOffsetY: 0, shadowBlur: 0, shadowColor: "rgba(0, 0, 0, 0)", mozCurrentTransform: Array[6] }
heres a jsFiddle example: https://jsfiddle.net/1krgqeq7/3/
There are a number of issues here that make this code rather difficult to follow:
1) You are reusing the variable cachedDrawing in a confusing way (is it an element or a function?)
2) You use a variable named temp which is usually a code smell, especially when you don't use it close to its declaration (not present in the code sample). Its also not clear why your stashing coords in there.
3) You use a fair number of descriptive variable names but in addition to temp you also use the rather non-descript 'obj'
But the answer to your question (related to 1 above) is that you are passing a context, not the canvas it was gotten from. Don't reassign that var and pass it into the cache instead.
Problems like this will likely be easier to spot with more descriptive variable names like cachedCanvas being a canvas and cachedCtx being its context.

event data in pixi.js

I just started playing around with pixi and have drawn multiple rectangles from an array with pixel coordinates like this:
var rectangle = [....];
....
var stage = new PIXI.Stage();
var renderer = PIXI.autoDetectRenderer(wrapper.getWidth(), wrapper.getHeight(), { transparent: true });
....
var graphics = new PIXI.Graphics();
graphics.interactive = true;
graphics.on("mouseover", function(e) {
this.alpha = 0.5;
}).on("mouseout", function() {
this.alpha = 1;
});
graphics.beginFill(0xFFFFFF);
graphics.lineStyle(2, 0x000000);
for (var i = 0; i < rectangle.length; i++) {
graphics.drawRect(rectangle[i][0], rectangle[i][1], 10, 10);
}
graphics.endFill();
stage.addChild(graphics);
renderer.render(stage);
The events are triggered but the object I get by "e" or "this" inside the callback is the object for all graphics. I want to get that single "mouseovered" rectangles object I can see in the graphicsData, but there is no id or anything to identify it by. How can I do this?
Performance is of essence as I'm going to render 20k+ rectangles or circles.
Without drawing each rectangle onto it's own PIXI.Graphics object you won't be able to get individual mouseover events. This is because as far as PIXI is concerned the Graphics object is a single bitmap image.
I would suggest performing your own hit tests inside the mouseover function to detect which rectangle the cursor is over.
If you are using PIXI.Rectangles you can take advantage of the built in Rectangle.Contains function to check if a point (in this case the mouse position) is inside the bounds.

Animating Paper.js path segments & handle info

I'm trying to animate between two complex paths using Paper.js and Tween.js. I've gotten pretty close, I can move all of the points in the path to the correct final positions, but I'm having problems with the handleIn and handleOut for each segment. It doesn't seem to be updating them.
Here's my code: http://codepen.io/anon/pen/rVBaZV?editors=101
var endPathData = 'M740,342.9c-32,...etc...';
var endPath = new Path(endPathData);
endPath.fillColor = '#4CC7A4';
beginPathData = 'M762.8,262.8c-48,...etc...';
var beginPath = new Path(beginPathData);
beginPath.fillColor = '#FFC1D1';
var numberOfSegments = beginPath.segments.length;
for (var i = 0; i < numberOfSegments; i++) {
var tween = new TWEEN.Tween(beginPath.segments[i].point)
.to({
x: endPath.segments[i].point.x,
y: endPath.segments[i].point.y
}, 3000)
.easing(TWEEN.Easing.Linear.None)
.start();
}
view.draw();
view.onFrame = function (event) {
TWEEN.update();
};
I'd like the pink path to end up exactly like the green one, but now I'm stuck. Is there anyway to achieve this?
You need to tween the handles too.
Each segment has two handles: segment.handleIn and segment.handleOut
in your example code you tween the segment.point (the segments position) resulting in the right location of the segments.
I don't know your Tween library, so it is up to you to implement it.
But It looks like you can add to more new tween one for the
beginPath.segments[i].handleIn
and one for the
beginPath.segments[i].handleOut
You can easily check that your code is right by letting paperjs smooth your path and taking care of the handles. By updating the onFrame function like this:
view.onFrame = function (event) {
TWEEN.update();
beginPath.smooth();
endPath.smooth();
};
and this results in the same shaped path.

Animating Color with Tweenjs

I've recently switched to EaselJs and would like to animate the color of a circle.
The code I've got so far is this:
var shape = new createjs.Shape();
shape.graphics.beginFill(createjs.Graphics.getRGB(255, 0, 0));
shape.graphics.drawCircle(0, 0, 10);
stage.addChild(shape);
var tween = createjs.Tween.get(shape, { loop: true }).
to({color:"#00FF00" }, 1000);
but that doesn't work. What is the right property to animate?
I don't think it's possible to animate the color of a shape like that, afterall the drawing of your shape could include many different colors, how should the Tween know which of those colors to modify?
There are two ways that I can think of right know:
Method 1) Use a createjs.ColorFilter, apply it to your shape and then tween the properties of your filter:
var shape = new createjs.Shape();
//making the shape shape white, so we can work with the multiplyers of the filter
shape.graphics.beginFill(createjs.Graphics.getRGB(255, 255, 255));
shape.graphics.drawCircle(0, 0, 10);
stage.addChild(shape);
var filter = new createjs.ColorFilter(1,0,0,1); //green&blue = 0, only red and alpha stay
shape.filters = [filter];
var tween = createjs.Tween.get(filter, { loop: true }).
to({redMultiplier:0, greenMultiplier:1 }, 1000);
I did not test this, so...let me know it this works. Also note, that filters are only applied/updated when calling cache() or updateCache() on your shape, so you will have to add that to your tick-function.
Method 2) Or you just redraw the shape every frame...but 1) is probably easier.
I was just trying to do the same thing. My solution was to tween custom properties on the shape object and then call an update method on the tween 'change' event. hope it this helps, I'm really new to createjs but so far I really like it!
var s = new createjs.Shape();
s.redOffset = 157;
s.blueOffset = 217;
s.greenOffset = 229;
s.updateColor = function()
{
var color = createjs.Graphics.getRGB(
parseInt(this.redOffset),
parseInt(this.greenOffset),
parseInt(this.blueOffset),
1);
this.graphics.beginFill( color ).drawRect(0, 0, 300, 300);
}
createjs.Tween.get(this.background).to({
redOffset : 255,
greenOffset : 255,
blueOffset : 255
}, 3000).addEventListener('change', function()
{
s.updateColor ();
});
Non filter version.
var colorObj = { r:255, g:0, b:0 };
var shape = new createjs.Shape();
var command = shape.graphics.beginFill(createjs.Graphics.getRGB(colorObj.r, colorObj.g, colorObj.b)).command;
shape.graphics.drawCircle(60, 60, 10);
stage.addChild(shape);
var tween = createjs.Tween.get(colorObj, { loop: true }).to({ r:255, g:255, b:255 }, 1000);
tween.addEventListener( "change", function( event ) {
command.style = createjs.Graphics.getRGB(Math.floor(colorObj.r), Math.floor(colorObj.g), Math.floor(colorObj.b));
});
beginFill(...).command object is able to update.
fiddle
https://jsfiddle.net/MasatoMakino/uzLu19xw/
I just read another option for animating colors here: http://community.createjs.com/discussions/easeljs/4637-graphics-colour-animation
It makes use of the createjs inject-method. I copied the relevant code from the provided code-example with a little bit of explanation fo my own.
According to the docs:
inject ( callback, data ):
Provides a method for injecting arbitrary Context2D (aka Canvas) API calls into a Graphics queue. The specified callback function will be called in sequence with other drawing instructions (...)
With this method you can for example change the native context2d fillstyle so we can change the fill color that easeljs uses to draw on the canvas.
Here we tell createjs about our own setColor function (defined below), this function will thus get automatically executed before every redraw:
var shape = new createjs.Shape();
shape.graphics.beginFill(createjs.Graphics.getRGB(255, 0, 0));
shape.graphics.inject(setColor, data)
shape.graphics.drawCircle(0, 0, 10);
stage.addChild(shape);
The definition of the setColor-function which calls the canvas native fillStyle method:
function setColor(o) {
// sets the context2D's fillStyle to the current value of data.fill:
this.fillStyle = o.fill; // "this" will resolve to the canvas's Context2D.
}
And the tick-function which changes the value of the fill:
function tick(evt) {
count = (count+3)%360;
// update the value of the data object:
data.fill = createjs.Graphics.getHSL(count, 100, 50);
// redraw the stage:
stage.update();
}
Modifying fill Instructions will do the trick of changing the color. This might help in doing the animation.
I dont know the impacts of this, but this works very fine for me.
Try this,
var circle = new createjs.Shape();
circle.graphics.f('#ffffff').s('#000000').ss(0.7).arc((30 * j),50,10, 0, Math.PI * 2, 1);
circle.number = j;
circle.addEventListener('click', function(e) {
var fillStyle = e.target.graphics._fillInstructions[0].params;
var currentFillStyle=fillStyle[1]+"";
for (var i = 0; i < circles.length; i++) {
var resetFillStyle = circles[i].graphics._fillInstructions[0].params;
resetFillStyle[1] = "#ffffff";
}
if (currentFillStyle == "#00B4EA") {
fillStyle[1] = "#FFFFFF";
} else {
fillStyle[1] = "#00B4EA";
}
stage.update();
})
Hope this helps!

Collision Detection with Javascript, Canvas, and Alpha Detection

I'm currently working on a basic javascript game that has two sprites that are not to be collided together. However, basic bounding box collision won't suffice as there are portions of the sprites that are transparent and wouldn't 'count' as colliding. I found a solution to the problem that I am having, but I can't get it to work. What I would like to do is calculate the transparent portions of the sprites and make sure that if the transparent portions overlap, that there is no collision detected. Here is what I found that solves the problem.
http://blog.weeblog.net/?p=40#comments
/**
* Requires the size of the collision rectangle [width, height]
* and the position within the respective source images [srcx, srcy]
*
* Returns true if two overlapping pixels have non-zero alpha channel
* values (i.e. there are two vissible overlapping pixels)
*/
function pixelCheck(spriteA, spriteB, srcxA, srcyA, srcxB, srcyB, width, height){
var dataA = spriteA.getImageData();
var dataB = spriteB.getImageData();
for(var x=0; x<width; x++){
for(var y=0; y<height; y++){
if( (dataA[srcxA+x][srcyA+y] > 0) && (dataB[srcxB+x][srcyB+y] > 0) ){
return true;
}
}
}
return false;
}
And for calculating the image data:
/**
* creating a temporary canvas to retrieve the alpha channel pixel
* information of the provided image
*/
function createImageData(image){
$('binaryCanvas').appendTo('body');
var canvas = document.getElementById('binaryCanvas');
var ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0);
var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var imageData = [image.width];
for(var x=0; x<image.width; x++){
imageData[x] = [image.height];
for(var y=0; y<image.height; y++){
var idx = (x + y * image.width) * 4;
imageData[x][y] = canvasData.data[idx+3];
}
}
$("#binaryCanvas").remove();
return imageData;
}
The problem is that I don't know how to implement this solution, or if this is the best solution to my problem. Is this what I'm looking for? And if so, where do I put these methods? The thing that I'm most confused about is what I should be passing to spriteA and spriteB. I've tried passing Images and I've tried passing the imageData returned from the pixelCheck method, but receiving the same error: that the object or image has no method 'getImageData'. What am I doing wrong?
Two things are wrong with this.
You made a function:
function createImageData(image){...}
But what you are calling is:
spriteA.getImageData();
spriteB.getImageData();
The dot notates a property of an object. You were trying to call a function that was never part to the objects. There are some simple fixes.
add the createImageData() function to your constructor :
function Sprite(){
...
this.createImageData = function(image){...};
...
}
or :
Sprite.createImageData = function(image{...};
or just call it correctly:
createImageData(spriteA.image); // or whatever the image is
Second, your function calls for an image parameter, but you aren't supplying one. Simply remember to supply the image when you call it. You could also remove the parameter and get the image from within the function.
Sort of like this:
function Sprite(){
...
this.createImageData = function(){
var image = this.image;
// or just use this.image, or whatever it is
...
}
...
}
Hope this helped.

Categories