Clear canvas context without knowing the canvas dimensions - html5-canvas

To clear a canvas to transparency, you do this:
var ctx = canvas.getContext("2d");
ctx.clearRect(0,0, //Starting coordinates
canvas.width, canvas.height //Ending coordinates
);
But I'm writing a more complex abstract system. To avoid calling .getContext all over the place, I have a pseudo-class to manage contexts of all layers. Every sub-program is then passed a ctx variable without the canvas:
Something.prototype.renderMe = function(ctx) {
//draw Something
}
I occurred to need to clear all context area. Is that possible just with canvas context?

The context contains a property which refers to its canvas.
var myCanvas=ctx.canvas;
ctx.clearRect(0,0,myCanvas.width,myCanvas.height);

Related

How do I resize a p5.Graphic object?

In p5.js resizeCanvas(x, y) is a function for p5 objects but if I made a p5.Graphics object, can I resize it with a similar function?
Interestingly, p5.Graphics objects can run resizeGraphics() but nothing happens (including no error) and the height and width remain the same in the console.
g = createGraphics(50, 50); //creates p5.Graphics
g.resizeCanvas(100, 100); //fails: silently without error
g.resize(100, 100); //fails: resize has not been defined
Is there another function or would I need to actually extract the cooresponding graphics canvas and call a native javascript function instead?
Thanks!
If you want to resize a P5.Graphics, you can just create a new one, then draw the old one to the new one.
Here is an example:
var pg;
function setup() {
createCanvas(1000, 1000);
pg = createGraphics(100, 100);
pg.background(100);
pg.noStroke();
pg.ellipse(pg.width/2, pg.height/2, pg.width, pg.height);
}
function draw() {
background(200);
image(pg, 0, 0);
}
function mouseClicked(){
var newPG = createGraphics(mouseX, mouseY);
newPG.image(pg, 0, 0, newPG.width, newPG.height);
pg = newPG;
}
Using resizeCanvas on a graphics object created with "createGraphics" seems to stretch the graphics rather than resize the buffer.
Right now the best way to resize a graphics object is to simply set the width and height properties directly.
// Some graphics object
let graphics = createGraphics(w,h);
// Now simply resize like this
graphics.width = gWidth;
graphics.height = gHeight;
As suggested here:
https://github.com/processing/p5.js/issues/2064#issuecomment-315503533

Drawing an image on a canvas and returning as a texture

Firstly, I'd like to make it clear that I am an absolute beginner when it comes to canvas & three.js
I've taken an existing project and am trying to make some minor modifications, namely, drawing an image on to a texture instead of just writing text. I would like the texture to have a set background color and will be attempting to draw a transparent png image on top of it.
The method that I am attempting to modify returns a texture for use in another function which is currently doing a lot more stuff that I probably won't be able to explain here.
I've tried a few approaches and I can't seem to get the behaviour that I want.
Approach #1
In this approach, I am getting the background color but I am not getting the image displayed
var ts = calc_texture_size(size + size * 2 * margin) * 2;
canvas.width = canvas.height = ts;
context.fillStyle = back_color;
context.fillRect(0, 0, canvas.width, canvas.height);
var img = new Image();
function drawIcon() {
context.drawImage(img,0,0);
}
img.onload = drawIcon();
img.src = "img/test.png";
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
return texture;
Approach #2
After doing some research, it seemed I was supposed to use a TextureLoader but I couldn't figure out how to draw the color/shape on the canvas. In this case, the image appears on its own without any background color.
var imgTex = new new THREE.TextureLoader().load( "img/test.png",function(t){
texture.map = imgTex;
});
texture.needsUpdate = true;
return texture;
How can I successfully draw an image on top of a coloured background and return it as a texture for use by other functions?
Your problem is much related to JavaScript event handling, like a question I answered yesterday: How to make a Json model auto-rotates in the scene?. You can never have an "onload" and then expect that to return the variable for you - the variable is just not going to be defined until the callback is executed. Instead you need to defer the work to the callback, or elsewhere keep polling the variable until it's defined.
More specific to your question though:
With approach #1, you're sending the backfilled texture to the GPU, then rendering additional content to it, but not updating the texture that was sent to the GPU after the image was loaded. Moving the texture.needsUpdate = true; to your drawIcon() would probably solve it here. Untested example:
var ts = calc_texture_size(size + size * 2 * margin) * 2;
var img = new Image();
var texture = new THREE.Texture(canvas);
canvas.width = canvas.height = ts;
context.fillStyle = back_color;
context.fillRect(0, 0, canvas.width, canvas.height);
img.onload = function() {
context.drawImage(img,0,0);
texture.needsUpdate = true;
};
img.src = "img/test.png";
return texture;
NB: You should always define your var variables at the start of a scope in JavaScript to make things clearer ... drawIcon() has access to that texture variable, though it doesn't look like it from your example code because it appears to be defined after it, but that's not how JavaScript works: var variables are always global to the scope they're defined in.
With approach #2, you need a little extra work to paint on the texture, turning the texture back in to a canvas and sending the resulting canvas to the GPU. The ImageLoader and Texture documentation combined hint at how you need to paint to the image you get from the TextureLoader.
Combining the two approaches, it should be something like this (also utterly untested):
var ts = calc_texture_size(size + size * 2 * margin) * 2;
canvas.width = canvas.height = ts;
context.fillStyle = back_color;
context.fillRect(0, 0, canvas.width, canvas.height);
var textureLoader = new THREE.TextureLoader().load(
"img/test.png",
function( texture ) {
var image = texture.image;
context.drawImage( texture.image, 0, 0 0 );
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
// Now do something with texture, like assigning it
// to your material
}
);
NB: Don't forget about using data URL's, if the image you need to paint with is small then this can be included in your code as a "data:" URL and this avoids the need to go to the server and wait for it to load in an event handler. Example at MDN.

HTML5 canvas, scale image after drawing it

I'm trying to scale an image that has already been draw into canvas.
This is the code:
var canvas = document.getElementById('splash-container');
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
// draw image at its original size
context.drawImage(imageObj, 0, 0);
};
imageObj.src = 'images/mine.jpeg';
// Now let's scale the image.
// something like...
imageObj.scale(0.3, 0.3);
How should I do?
You're thinking about it wrong. Once you've drawn the image onto the canvas it has no relationship to the imageObj object. Nothing you do to imageObj will affect what's already drawn. If you want to scale the image, do in the drawImage function:
drawImage(imgObj, 0, 0, imgObj.width * 0.3, imgObj.height * 0.3)
If you want to animate the scaling or are looking to achieve some other effect which requires you to draw the image at full size initially you'll have to first clear it before drawing the scaled down image.
What robertc says is correct, but if you really wanted to scale an image on a canvas after drawing it for some reason, you could just scale the whole canvas using the CSS width/height properties and that would scale the image without having to redraw it.

Positioning an HTML5 Canvas Element

I am completely new to HTML5 and have been reading about it for the past few days mainly because I wanted to create a rotating image to put in a <div>. I found a code that does exactly what I want, but it throws the canvas on to the bottom left corner of my page (I'm not sure why, but I think it has something to do with the very first line of the code below). I'm not sure how to adapt the code to a element so that I can put it where I want. From looking at other people's scripts and trying to emulate them, I know you're supposed to do this sort of thing to hold the canvas "<canvas width="100" height="100" id="pageCanvas"></canvas>," but I don't know how to name the below code in order to do that. I greatly appreciate any help anyone can offer me - thank you so much for reading! :)
<script>
window.addEventListener("load", init);
var counter = 0,
logoImage = new Image(),
TO_RADIANS = Math.PI/180;
logoImage.src = 'IMG URL';
var canvas = document.createElement('canvas');
canvas.width = 100;
canvas.height = 100;
var context = canvas.getContext('2d');
document.body.appendChild(canvas);
function init(){
setInterval(loop, 1000/30);
}
function loop() {
context.clearRect(0,0,canvas.width, canvas.height);
drawRotatedImage(logoImage,100,100,counter);
drawRotatedImage(logoImage,300,100,counter+90);
drawRotatedImage(logoImage,500,100,counter+180);
counter+=2;
}
function drawRotatedImage(image, x, y, angle) {
// save the current co-ordinate system
// before we screw with it
context.save();
// move to the middle of where we want to draw our image
context.translate(x, y);
// rotate around that point, converting our
// angle from degrees to radians
context.rotate(angle * TO_RADIANS);
// draw it up and to the left by half the width
// and height of the image
context.drawImage(image, -(image.width/2), -(image.height/2));
// and restore the co-ords to how they were when we began
context.restore();
}
</script>
Create a canvas element in your HTML code so you can place it exactly where you want (with html + css) :
<canvas id='canvas' height='100' width='100'> Your browser does not support HTML5 canvas </canvas>
And replace this javascript code :
var canvas = document.createElement('canvas');
canvas.width = 100;
canvas.height = 100;
var context = canvas.getContext('2d');
document.body.appendChild(canvas);
by this one :
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

html5: copy a canvas to image and back

I implemented a zoom in and out function on a canvas element.
it works by scaling the canvas, translating it, and then redraw the whole scene again.
the problem is that it takes a lot of time to redraw everything because i got a lot of things on my canvas.
I need a way to copy the canvas to an image object and than copy the image back to the canvas without loosing quality. what are the specific methods to copy canvas to a javascript variable, and to to copy this variable back to the canvas later?
I'll be glad if you write down the code because I couldn't find any good explanation over the internet.
thanks,
The drawImage() method can draw to a canvas using another canvas instead of an image.
You could create a 'backup' canvas, of the same size as your original, draw the first one to there and then draw that one back to the original when you need it.
e.g.
// Assume we have a main canvas
// canvas = <main canvas>
ctx = canvas.getContext('2d');
..
// create backing canvas
var backCanvas = document.createElement('canvas');
backCanvas.width = canvas.width;
backCanvas.height = canvas.height;
var backCtx = backCanvas.getContext('2d');
// save main canvas contents
backCtx.drawImage(canvas, 0,0);
..
// restore main canvas
ctx.drawImage(backCanvas, 0,0);
There are a few ways to do it theres the getImageData and putImageData methods Reference, However putImageData and getImageData are pretty slow. Another way is to save the data to an image in memory and recall it from that which is much faster, then the third way is the one above mentioned by andrewmu which involves copying to another canvas element. I have included examples for the first and second type.
Image in memory method
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
savedData = new Image();
function save(){
// get the data
savedData.src = canvas.toDataURL("image/png");
}
function restore(){
// restore the old canvas
ctx.drawImage(savedData,0,0)
}
getImageData putImageData method
// Setup our vars, make a new image to store the canvas data
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
canvasData = '';
function save(){
// get the data
canvasData = ctx.getImageData(0, 0, 100, 100);
}
function restore(){
// restore the old canvas
ctx.putImageData(canvasData, 0, 0);
}
added image into canvas
var image = new Image();
image.src = "1.jpg";
image.onload = function () {
context.drawImage(image, 0, 0);
};

Resources