Html5 canvas not drawing - javascript

I have a problem with an object not drawing it's image. I've set the onload property of the image to the draw function..
//ctor
function Sprite(someargs,pContext)
this.setContext(pContext); //This could be the problem?
this.setX(px);
this.setY(py);
this.setTexture(pImagePath);
//I run this in the constructor
Sprite.prototype.setTexture = function(pImagePath){
this.texture = new Image();
this.texture.onload = this.draw();
this.texture.src = pImagePath;
};
Sprite.prototype.draw = function(){
this.getContext().drawImage(this.texture,this.getX(),this.getY(),100,100);
};
Sprite.prototype.setContext = function(pContext){
this.mContext = pContext;
};
No errors at runtime, image not drawn onto canvas though.
I'v put alerts in all the above methods, all of which are being executed.
Anyone got any ideas as to why it's not drawing?
Cheers

this.texture.onload = this.draw();
you are not setting onload to the draw function but to the result of draw function
this.texture.onload = this.draw;
also wouldn't be good because you will lose your context of this in here.
this inside of draw function will point to texture instead of Sprite
you need to bind the function draw to this (which is the Sprite at the moment) and pass it to onload
this.texture.onload = this.draw.bind(this);
or:
var that = this;
this.texture.onload = function() { that.draw(); }

Related

How to remove bitmap image on click from canvas

I am using createjs as my framework. I've placed a Bitmap on the canvas and I created a function to try and remove it but I keep getting an error message in the console that image is not defined. This is what my code looks like:
// onload=init() called in html doc
function init(){
var canvas = new createjs.Stage("canvas");
// Add image to canvas
image = new createjs.Bitmap("image.png");
image.x = 200;
image.y = 180;
image.scaleX = 0.35;
image.scaleY = 0.35;
canvas.addChild(image);
image.addEventListener('click', pop);
canvas.update();
}
//remove image from canvas
function pop() {
console.log('pop');
canvas.removeChild(image);
}
When I click on it, I get the console message "pop" followed by the error I mentioned above. I've tried moving the function inside init but I appear to get the same problem.
Make image as global variable, so that it can be accessed by all the functions in your case function pop.
var image;// defining 'image' variable as global
function init(){
var canvas = new createjs.Stage("canvas");
// Add image to canvas
image = new createjs.Bitmap("image.png");
image.x = 200;
image.y = 180;
image.scaleX = 0.35;
image.scaleY = 0.35;
canvas.addChild(image);
image.addEventListener('click', pop);
canvas.update();
}
//remove image from canvas
function pop() {
console.log('pop');
canvas.removeChild(image);
}
This is a scope issue. You defined image inside your init function, so it is not accessible on the pop method.
There are two easy fixes. Either move the var image outside of the init function, or use the click target instead.
var image;
function init() {
init = new createjs.Bitmap();
// etc
}
// OR
function pop(event) {
stage.removeChild(event.target);
}
Scope is really important to understand when building JavaScript applications, so I suggest getting to know it a little better :)
Cheers,

Paper.JS create another function to draw a path

So I'm trying to read data and then pass that to another function so I can draw a path.
The data is fine, it's all working and I can view it in the console.
The normal drawing (Using the onMouseEvent) functions work fine.
The only way I can get it to draw using a different function, is if I declare the path at the top of the JS file:
var reloadPath = new Path();
The problem with this, is that when I call reloadPath, it automatically connects the lines (even if the user has clicked elsewhere) which is what I don't want.
I've tried var reloadPath; at the start of the file, and then this
function reloadDrawing(data) {
reloadPath = new Path();
reloadPath.strokeColor = 'black';
reloadPath.add(data);
view.draw();
}
But this just doesn't draw anything.
Thanks.
edit:
Tried the amendments but they didn't work. I'm using Jade instead of HTML (using node.js) so theres really nothing in my html: using socket.io as well
JS:
This does all the dynamic drawing stuff
io.on( 'reloadDrawing', function( data ) {
console.log("fired");
endDrawing(data);
startDrawing(data);
});
function endDrawing(data){
reloadPath.add(data);
view.draw();
reloadPath = new Path();
}
function startDrawing(data) {
reloadPath = new Path();
reloadPath.strokeColor = 'black';
reloadPath.add(data);
view.draw();
}
In your function, you overwrite the reloadPath and thus destroy the data that's already there. Delete the one line and add another function endDrawing (or any name you like). Call this new function in the onMouseUpEvent, in order "finish" the line. In the onMouseDown-event start a new line using the startDrawing function.
function reloadDrawing(data) {
reloadPath.add(data);
view.draw();
}
function endDrawing(data){
reloadPath.add(data);
view.draw();
reloadPath = new Path();
}
function startDrawing(data) {
reloadPath = new Path();
reloadPath.strokeColor = 'black';
reloadPath.add(data);
view.draw();
}

Html5 Canvas concept

I'm currently learning the basics of html5 canvas. I just ran into something that needs to be explain. I have this code.
function myApp() {
this.el = document.getElementById('canvas');
this.context = this.el.getContext('2d');
this.colors = ['#fff', '#000', '#f00'];
this.init();
}
myApp.prototype = {
init: function() {
var _this = this;
_this.draw();
},
draw: function() {
var _this = this;
_this.context.fillStyle = _this.colors[2];
_this.context.fillRect(10,10,100,100);
//_this.context.fillStyle = _this.colors[2];
}
}
var startThisBitch = new myApp();
If I try to fillStyle() after I create the Rect(), there's nothing on my canvas. But if I fill the color BEFORE creating the Rect(), it works. I just don't find it logical. Or maybe I'm missing the concept. Do you guys have any explainations?
I just don't find it logical.
Would you find it logical to first paint a wall, and then choose the color of the paint?
Edit: fillStyle() doesn't actually draw anything, it just sets the parameters of subsequent draw calls. fillRect() however does draw pixels on canvas, so it's necessary to set all parameters (color, line width, etc.) before calling fillRect().

How to hide and restore custom nodes in InfoVis/JIT force directed graph?

I am trying to use InfoVis / JIT to render a force directed graph visualizing a network.
I am a newbie to both java script and JIT.
I have created my own custom node types using following code in my js file, which lets me display my image on the node.
$jit.ForceDirected.Plot.NodeTypes.implement({
'icon1': {
'render': function(node, canvas){
var ctx = canvas.getCtx();
var img = new Image();
img.src='magnify.png';
var pos = node.pos.getc(true);
img.onload = function() {
ctx.drawImage(img, pos.x, pos.y);
};
},
'contains': function(node,pos){
var npos = node.pos.getc(true);
dim = node.getData('dim');
return this.nodeHelper.circle.contains(npos, pos, dim);
//return this.nodeHelper.square.contains(npos, pos, dim);
}
}
I am assigning this custom node type to the node using "$type": "icon1" in the json data object. I do get image on the node, but the problem is that I am not able to hide it when required. I am able to hide the in-built node types like circle,square etc. using following code.
node.setData('alpha', 0);
node.eachAdjacency(function(adj) {
adj.setData('alpha', 0);
});
fd.fx.animate({
modes: ['node-property:alpha',
'edge-property:alpha'],
duration: 2000
});
But the same code does not work for custom nodes.
Hence I tried to temporarily change the type of node to the built-in "circle" type, hid it and then re-setted the type of node to its original i.e. my custom node, icon1.
function hideNode( ){
var typeOfNode = node.getData('type');
node.setData( 'type','circle');
node.setData('alpha', 0);
node.eachAdjacency(function(adj) {
adj.setData('alpha', 0);
});
fd.fx.animate({
modes: ['node-property:alpha',
'edge-property:alpha'],
duration: 2000
});
node.setData('type',typeOfNode );
}
I think this should work but the custom image comes back in a while on the canvas.
If I don't reset the type of node to its original i.e. in the above code and comment out the following statement and call hide function, then the node gets hidden.
node.setData('type',typeOfNode );
I am not able to figure out how by only setting a node's type to some custom type, the node is being rendered. Any help with this question will be appreciated.
I need to re-set the node's type to its original because I want the node to be restored when required by calling unhide function. If I don't reset node's type to the original then it would be rendered as a circle when restored.
I have gone through the API and the google group for JIT but couldn't find an answer.
Can anyone help?
Here's a look at a snippet from the Plot's plotNode function:
var alpha = node.getData('alpha'),
ctx = canvas.getCtx();
ctx.save();
ctx.globalAlpha = alpha;
// snip
this.nodeTypes[f].render.call(this, node, canvas, animating);
ctx.restore();
As you can see, the node's alpha value is applied to the canvas immediately before the node's render function is called. After rendering the node, the canvas is restored to the previous state.
The issue here is that your custom node's render function does not render the node synchronously, and the canvas state is getting restored prior to the call to drawImage. So, you can do one of two things:
1) Preload and cache your image (preferred approach, as this will also prevent image flickering and help with performance):
// preload image
var magnifyImg = new Image();
magnifyImg.src = 'magnify.png';
// 'icon1' node render function:
'render': function(node, canvas){
var ctx = canvas.getCtx();
var pos = node.pos.getc(true);
ctx.drawImage(magnifyImg, pos.x, pos.y);
}
or 2) save the canvas state, reapply the alpha, and then restore the canvas state after drawing the image in your onload handler:
// 'icon1' node render function:
'render': function(node, canvas){
var ctx = canvas.getCtx();
var img = new Image();
img.src='magnify.png';
var pos = node.pos.getc(true);
img.onload = function() {
ctx.save(); // save current canvas state
ctx.globalAlpha = node.getData('alpha'); // apply node alpha
ctx.drawImage(img, pos.x, pos.y); // draw image
ctx.restore(); // revert to previous canvas state
};
}

HTML5 Canvas: Create a Image.onload() function via Image.prototype

So, my goal is to have a simple function that allows me to just type something like:
var map = new Image();
map.onloadDraw();
map.src = "images/" + worldmapCanvasShapeImage;
which will automatically refresh the canvas when loaded.
This is what I already came up with:
Image.prototype.onloadDraw = function(){
this.onload() = function() {
drawMap();
drawMarkers();
drawArticles();
}
}
It doesn't seem to work, it's probably a small error but I can't find a lot of information about it.
Image.prototype.onloadDraw = function(){
this.onload = function() {
drawMap();
drawMarkers();
drawArticles();
}
}
Skip the pair of parens after onload. You are defining it, not invoking it. :)

Categories