im trying to learn how to use javascript objects, and got some issue here.
var playerImg = new Image();
playerImg.src = 'player_stay.png';
var player = {
posX: 50,
posY: 50,
draw: function(){
ctx.drawImage(playerImg, player.posX, player.posY);
}
}
It is posible to insert playerImg into player object ?
Something like player.img
EDIT:
I can make it this way
var player = {
posX: 50,
posY: 50,
draw: function(){
playerImg = new Image();
playerImg.src = 'player_stay.png';
ctx.drawImage(playerImg, player.posX, player.posY);
}
}
But i think it will create new Image(); all the time when i use player.draw();
So im asking if there is a better way to do this and have all parametrs inside a player object ?
Yes, why not:
var player = {
posX: 50,
posY: 50,
draw: function(){
ctx.drawImage(playerImg, player.posX, player.posY);
},
playerImage: playerImg
}
If I understand correctly you don't want to build the playerImg object outside/before of the player one.
Well this is one way you could do it, but I wouldn't recommend it because it's not so readable:
var player = {
posX: 50,
posY: 50,
draw: function(){
ctx.drawImage(player.img, player.posX, player.posY);
},
img: (function(){
var playerImg = new Image();
playerImg.src = 'player_stay.png';
return playerImg;
})()
}
This construct (function(){})(); is called a self-executing/self-invoked anonymous function, or an Immediately-Invoked Function Expression
BTW: this expression is executed only once, when the player object is constructed, so you don't have to worry about repeatedly creating the Image.
Yes it is possible.
In general, you can have nested objects or lists, like this:
var player = {
posX: 50,
posY: 50,
draw: function(){
ctx.drawImage(playerImg, player.posX, player.posY);
},
playerImage:{
src = 'player_stay.png'
},
playerList:['elem1', 'elem2']
}
to refer to it in your code you just write (example in case of value assignment)
player.playerImage.src='anotherplayer.jpg';
this link can be of some help
http://www.json.org/
Related
Here is such a code snippet:
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create });
var emitter;
function preload() {
game.load.image('wasp', 'assets/glass.png');
game.load.image('glass', 'assets/glass.png');
game.load.image('water', 'assets/blue-raster-floor.png');
}
function create() {
game.physics.startSystem(Phaser.Physics.ARCADE);
game.add.tileSprite(0, 344, 800, 256, 'water');
emitter = game.add.emitter(game.world.centerX, 200);
emitter.makeParticles('glass');
emitter.setXSpeed(-200, 200);
emitter.setYSpeed(-150, -250);
emitter.bringToTop = true;
emitter.setAlpha(0.1, 1, 500);
emitter.setScale(-2, 2, 1, 1, 3000, Phaser.Easing.Sinusoidal.InOut, true);
emitter.gravity = 300;
emitter.start(false, 5000, 700, 50);
game.time.events.add(3000, destroyEmitter, this);
}
function tweens(cash) {
var bugs;
var index = 0;
var data;
var pos = [];
var tween;
var tweenData = { x: 0, y: 0 };
tween = game.make.tween(tweenData).to( { x: 100, y: 400 }, 2000, "Sine.easeInOut");
tween.yoyo(true);
data = tween.generateData(60);
bugs = game.add.group();
pos.push(new Phaser.Point(32, 0));
pos.push(new Phaser.Point(300, 100));
pos.push(new Phaser.Point(600, 70));
bugs.create(pos[0].x, pos[0].y, 'wasp');
bugs.create(pos[1].x, pos[1].y, 'wasp');
bugs.create(pos[2].x, pos[2].y, 'wasp');
tween.onUpdateCallback(function () {
bugs.getAt(0).x = pos[0].x + data[index].x;
bugs.getAt(0).y = pos[0].y + data[index].y;
bugs.getAt(1).x = pos[1].x + (data[index].x / 2);
bugs.getAt(1).y = pos[1].y + data[index].y;
// Inverse one of the values
bugs.getAt(2).x = pos[2].x - data[index].x;
bugs.getAt(2).y = pos[2].y + data[index].y;
index++;
if (index === data.length)
{
index = 0;
}
});
tween.start();
}
function destroyEmitter() {
console.log(emitter);
emitter.destroy();
tweens();
}
As you can see, I have made the particle-animation. Such steps need to be taken:
Particle-animation should be cached in the form of a set of shots (textures)
Particle-animation should be deleted. I have already done it (by means of ‘destroy‘)
Instead of the particle animation sprite animation should be realized by means of the function tweens using received textures
and passing these textures as the argument of the function tweens
Any refractoring is welcome.
In Phaser, the emitter particles are of the relatively simple DisplayObject class which do not support animations like the Phaser.Sprite does. Btw I don't know if using tweens is the best way to animate particles, because I suspect it will be heavy on CPU usage, using Sprite animations on the other hand is a bit more "light weight".
But either way, you could create a custom particle class which contains the code for your particle animation (using tweens, animations, timers, whatever) and then set that custom class as the emitter.particleClass, see a code example in link below:
http://codetuto.com/2016/02/phaser-animated-particles/
I'm working on a project with Fabric.js.
Now I need to create a custom class and to export it to SVG.
I'm using Fabric.js tutorial to begin:
http://www.sitepoint.com/fabric-js-advanced/
Here is the javascript code:
var LabeledRect = fabric.util.createClass(fabric.Rect, {
type: 'labeledRect',
initialize: function(options) {
options || (options = { });
this.callSuper('initialize', options);
this.set('label', options.label || '');
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'), {
label: this.get('label')
});
},
_render: function(ctx) {
this.callSuper('_render', ctx);
ctx.font = '20px Helvetica';
ctx.fillStyle = '#333';
ctx.fillText(this.label, -this.width/2, -this.height/2 + 20);
}
});
var canvas = new fabric.Canvas('container');
var labeledRect = new LabeledRect({
width: 100,
height: 50,
left: 100,
top: 100,
label: 'test',
fill: '#faa'
});
canvas.add(labeledRect);
document.getElementById('export-btn').onclick = function() {
canvas.deactivateAll().renderAll();
window.open('data:image/svg+xml;utf8,' + encodeURIComponent(canvas.toSVG()));
};
Here the HTML:
<canvas id="container" width="780" height="500"></canvas>
Export SVG
Here is my jsfiddle..
http://jsfiddle.net/QPDy5/
What I'm doing wrong?
Thanks in advance.
Every "class" in Fabric (rectangle, circle, image, path, etc.) knows how to output its SVG markup. The method responsible for it is toSVG. You can see toSVG of fabric.Rect, for example, or fabric.Text one.
Since you created subclass of fabric.Rect here and didn't specify toSVG, toSVG of the next object in prototype chain is used. The next "class" in the inheritance chain happens to be fabric.Rect, so you're seeing a result of fabric.Rect.prototype.toSVG.
The solution is simple: specify toSVG in your subclass. Theoretically, you would need to combine the code from fabric.Rect#toSVG and fabric.Text#toSVG, but to avoid repetition and keep things maintainable, we can utilize a bit of a hack:
toSVG: function() {
var label = new fabric.Text(this.label, {
originX: 'left',
originY: 'top',
left: this.left - this.width / 2,
top: this.top - this.height / 2,
fontSize: 20,
fill: '#333',
fontFamily: 'Helvetica'
});
return this.callSuper('toSVG') + label.toSVG();
}
The "fontSize", "fill", and "fontFamily" should ideally be moved to an instance-level property of course, to avoid repeating them there.
Here's a modified test — http://jsfiddle.net/fabricjs/QPDy5/1/
What #Sergiu Paraschiv suggested with a group is another just-as-viable solution.
Problem is there's no SVG equivalent to fillText so FabricJS seems to ignore it.
My workaround is to use a fabric.Group and build an inner Rect and Text
var LabeledRect = function(options) {
var rect = new fabric.Rect({
width: options.width,
height: options.height,
fill: options.fill
});
var label = new fabric.Text(options.label);
var group = new fabric.Group([rect, label]);
group.left = options.left;
group.top = options.top;
group.toSVG = function() {
var e=[];
for(var t = 0; t < this._objects.length; t++)
e.push(this._objects[t].toSVG());
return'<g transform="'+this.getSvgTransform()+'">'+e.join("")+"</g>"
};
return group;
};
The reason I overwrote toSVG is because the default implementation cycles through the children in reverse order (for(var t=this._objects.length;t--;)). I have no clue why it does that, but the text renders underneath the rectangle.
var ball = {
x: 20,
y: 500,
vx: 100,
vy: 100,
width: 13,
height: 13,
draw: function() {
var img = new Image();
img.src = 'images/ball.png';
img.onload = function(){
ctx.drawImage(img, this.x, this.y);
};
},
I want the drawImage() line of code to refer to the ball.x and ball.y. Instead of using ball.x and ball.y, I want to use "this" keyword so that i can turn the ball object into a function that is a mass constructor/prototype if i end up wanting to (able to make ball1, ball2, ball3 etc.). I think "this" is not referring to ball anymore because it's in a nested function? Is there any way around that without hard-coding ball.x and ball.y into the drawImage arguments?
This is one of the tricky things about JavaScript: this is dynamic. To put it simply, the solution is to put the this you want in a variable while you have it and use that variable to refer to it:
var ball = {
// ...
draw: function() {
// ...
var myself = this;
image.onload = function() {
// use myself rather than this
};
}
};
Another solution is to fix the value of this. That is done using bind:
var ball = {
// ...
draw: function() {
// ...
image.onload = function() {
// ...
}.bind(this);
}
};
That will bind the value of this inside the onload function to whatever it was when draw was called. This latter solution won't work on older browsers, but it is easily shimmed.
Yes, basically you need to use a closure. All you need to do is refer to the variables by their parent instead of by the use of this, which will actually refer to the img element in the function. So just change your code to
ctx.drawImage(img, ball.x, ball.y);
or even
ctx.drawImage(this, ball.x, ball.y);
var ball = function(){
this.x= 20;
this.y=500;
this.vx= 100;
this.vy= 100;
this.width= 13;
this.height= 13;
}
ball.prototype = {
draw: function() {
var img = new Image();
img.src = 'images/ball.png';
var balref = this;
img.onload = function(){
ctx.drawImage(img, balref .x, balref.y);
}
}
var myball = new ball();
myball.draw();
Note: not tested
I have this code:
var rect2 = new drawRect({
h: 100,
w: 100,
x: 280,
y: 20,
colour: '8CB5CF',
name: 'Office 2'
}
Is it possible for read the properties that I am passing to drawRect?
My first thought was:
alert(rect2.h)
But that results in undefined, didn't expect it to work really but I don't know how else to approach this.
I am fairly new to javascript. Thanks.
EDIT: Sorry here is drawRect:
function drawRect(rectOptions){
var ctx = document.getElementById('canvas').getContext('2d');
ctx.fillStyle = rectOptions.colour;
ctx.fillRect(rectOptions.x,rectOptions.y,rectOptions.h,rectOptions.w);
ctx.font = '12px sans-serif';
ctx.fillText(rectOptions.name, rectOptions.w + rectOptions.x, rectOptions.h + rectOptions.y);
}
here is the full code: Full code
Inside of the drawRect function you could add a line to add an option property to objects constructed by drawRect.
function drawRect(rectOptions) {
this.options = rectOptions;
//...
}
Then you could do
var rect2 = new drawRect({ /* ... */ });
alert(rect2.options.h);
Alternatively, you could have drawRect return the options passed to it.
function drawRect(rectOptions) {
//...
return rectOptions;
}
Then you could do, as you originally tried,
alert(rect2.h);
var rect2 = new drawRect({
h: 100,
w: 100,
x: 280,
y: 20,
colour: '8CB5CF',
name: 'Office 2'
})
function drawRect(rectOptions){
//your code
return rectOptions;//you have to return the value
}
alert(rect2.h);//alerts 100
link to jsfiddle
hello i have just start using Raphael but i'm very confused in the following code
WHY this code works
var paper = Raphael("canvas_container", 320, 200);
var mycir = paper.circle(50, 40, 30);
mycir.node.onclick = function() { alert("any thing") }
AND this doesn't
var paper = Raphael("canvas_container", 320, 200);
var mycir = paper.circle(50, 40, 30);
mycir.click = function() { alert("any thing") }
i also tried and it didn't work :
mycir.click(function(){alert("any thing")});
what the diffrence ? when i look at the raphaeal document they use Element.click() . why can't i use it them , is this is my version or What ?
The problem is that you are trying to assign to click, instead of calling it.
This should work:
var paper = Raphael("canvas_container", 320, 200);
var mycir = paper.circle(50, 40, 30);
mycir.click(function() { alert("any thing") });
Note that Raphael recommends not to use .node (as it says: "Don’t mess with it.")