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.")
Related
I am most likely misusing this call back feature but in the following code, the "testCircle" performs no animation before disappearing.
var paper = Raphael(0, 0, 1280,600);
var testCircle = paper.circle(300, 300, 50);
testCircle.animate({
cx: 700
}, 1000, testCircle.remove())
I want the animation to actually finish before the circle is removed. Am I misusing this function?
Here you go: DEMO
var paper = Raphael(0, 0, 1280,600);
var testCircle = paper.circle(300, 300, 50).attr('fill','red');
testCircle.animate({cx: 700}, 1000, hideCircle);
function hideCircle()
{
testCircle.remove();
}
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.
i am using fabric.js to work on canvas . i have created text on canvas .now,onclick of button i want to increase font-size .
canvas.set({fontSize,40});
this is not working ? any other method .i have created fiddle please Check
var canvas = window._canvas = new fabric.Canvas('c');
var text = new fabric.Text('Sample', {
left: 100,
top: 100,
fill: 'navy'
});
canvas.add(text);
document.getElementById('textinput').addEventListener('change', function (e) {
var obj = canvas.getActiveObject();
if (!obj) return;
obj.setText(e.target.value);
canvas.renderAll();
});
document.getElementById('btn').addEventListener('click', function (e) {
var obj = canvas.getActiveObject();
alert('button clicked');
if (!obj) return;
obj.set(fontSize,40);
canvas.renderAll();
});
Here is a working code,
var canvas = window._canvas = new fabric.Canvas('c');
var text = new fabric.Text('Sample', {
left: 100,
top: 100,
fontSize: 80,
fill: 'navy'
});
canvas.add(text);
document
.getElementById('btn')
.addEventListener('click', function (e) {
canvas.getActiveObject().set("fontSize", "30");
canvas.renderAll();
});
First of all, I was able to make this work by changing
obj.set('fontSize',40);
to
obj.setFontSize(40);
Second, I think that it is not the fontSize of your object that is changed when you resize it, but its scaleX and scaleY. Hope this helps.
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
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/