How to move only one image on canvas - html

I have about 10 images I draw on canvas in html5. Then, I would like to move the first image only, the other one should remain in place. here is the code :
ctx.clearRect(0, 0, 500, 375);
ctx.translate(20, 0);
I understand that I move the whole canvas with that code... but how to move only one image not the whole canvas... I think about using two canvas... but look like a bad solution to me !...
i guest the save and restore will be used, but when i try, it repeat the images... not good !. i am kind of lost, and read a lot of tutorial and read that : Canvas - move image-problem but not usefull. HELP

Here is my final working code
function drawOnCanvas() {
ctx.save();
ctx.clearRect(0, 0, 500, 375);
ctx.globalAlpha = 1;
ctx.translate(image_objects[0].width/2, image_objects[0].height/2);
ctx.scale(scale,scale);
ctx.translate(-image_objects[0].width/2, -image_objects[0].height/2);
ctx.translate(image_objects[0].width/2, image_objects[0].height/2);
ctx.rotate(rotate);
ctx.translate(-image_objects[0].width/2, -image_objects[0].height/2);
ctx.translate(movex, movey);
ctx.drawImage(image_objects[0],0,0);
ctx.restore();
if (hide_images == false) {
for (var i = 1; i < image_objects.length; ++i) {
ctx.globalAlpha = opacity;
ctx.drawImage(image_objects[i], 0, 0);
}
}
}

Related

Any way to fill an image surface with a color? (Canvas)

I've searching a way to fill an image surface with a color with canvas but didn't find what i'm looking for.
Is there actually any way to do it?
There is an example of what i'm talking about:
If the image is like this:
I would need to paint this with canvas:
Just fill the actual image surface with a color (black in this case).
I think this Android method does the same, so I hope there is something similar on canvas.
imageView.setColorFilter(Color.RED);
Thank you in advance.
You can use composition mode to do this, more specifically the source-in:
ctx.globalCompositeOperation = "source-in";
ctx.fillRect(x, y, w, h); // fill the image area using current color
// Using the original colored logo in OPs post:
var img = new Image; img.onload = go; img.src = "//i.stack.imgur.com/kv435.png";
function go() {
var ctx = c.getContext("2d");
c.width = this.width; c.height = this.height;
ctx.drawImage(this, 0, 0);
// change color
ctx.globalCompositeOperation = "source-in";
ctx.fillRect(0, 0, c.width, c.height); // def. color is black
}
<canvas id=c></canvas>
What's important to be aware of though is that composite operations works with the alpha channel. If the image doesn't have an alpha channel but just a white background, this approach won't work. In that case you would need to iterate over each pixel and replace all non-white pixels to the target color pixel.
For this approach you can use getImageData(). But my recommendation is to prepare the image so it has an alpha channel embedded before processing.

HTML5 Canvas DrawImage Stutter / Choppiness

PROBLEM
I am trying to get an image on a canvas to move from left to right smoothly. It's not too bad on Chrome/Safari (still stutters a little), but there is noticeable stutter in Firefox on multiple machines (tried on Windows and Mac). I'm a bit stumped as to how to solve this.
WHAT I TRIED
I am using requestAnimationFrame instead of setTimeout. I am using clearRect instead of setting the canvas width, though I am clearing the entire canvas instead of the minimum bounding box as I wanted to test it in the worst case scenario. I did close extra tabs. I even disabled Firebug. I am using drawImage instead of the image data functions. Since I'm not doing anything else but clearRect and drawImage, I avoided using an offscreen canvas.
EXAMPLE 1: http://jsfiddle.net/QkvYs/
This one has a set framerate where it ensures that the position is correct regardless of how often the game loop runs. It displays the number of frames skipped. This example is closer to what I'm aiming for. Note that it looks choppy even when no frames are being skipped. I have also played around with the framerate with no success, though I'd like to aim for about 30 fps (var frameRate = 33;).
EXAMPLE 2: http://jsfiddle.net/R8sEV/
Here is a simple one where all it does is move the image. This stutters for me on multiple machines.
//loop
function loop() {
//request anim frame
requestAnimationFrame(loop);
//set canvas once able
if (!canvas) {
var temp = document.getElementById("testCanvas");
if (temp) {
canvas = temp;
ctx = canvas.getContext('2d');
}
}
//update and render if able
if (canvas) {
//increase x
x += 5;
//start from beginning
if (x > canvas.width) {
x = 0;
}
//clear
ctx.clearRect(0, 0, canvas.width, canvas.height);
//image
ctx.drawImage(image, x, 200);
}
}
//start
loop();
WHAT I LOOKED AT
I realize that this question has been asked before and I did look before asking. However, the answers given have unfortunately not helped.
https://gamedev.stackexchange.com/questions/37298/slow-firefox-javascript-canvas-performance
HTML5 Canvas Animation Has Occasional Jitter / Hesitation / Stutter
Canvas animation stutters in FireFox but is perfect in Chrome
Is there a solution for HTML5 canvas animation stutter?
Thanks for the help! I appreciate it.
For instance use time delta in your position calculations. This will ensure that object is moved by certain value in given time regardless of FPS and delay between frames.
Edited your fiddle:
http://jsfiddle.net/R8sEV/2/
wrong approach:
x += 5
good approach:
x += speed * delta / 1000
where delta is time in [ms] which passed from last frame - and speed is measured in [pixels/second]
You are getting the element every frame?!
That can cause a lot of lag.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var x = 0;
function loop() {
requestAnimationFrame(loop);
x += 5;
ctx.drawImage(IMAGE, x, 0);
}
loop();

html5 canvas: clipping by color

is there any way to choose an area on the canvas by color and clip it?
I want to be able to clip an undefined aread that the only thing in common between all the pixels is that they all have the same color.
thanks
Live Demo
Below is a way to select a color.. and do whatever you want with it. I pass a color I want to find iterate over every pixel and remove the color that matches, since Im not sure what you meant by clipping I assumed you mean remove. However please note on large images this method will be slow.
// Takes an array with 3 color components, rgb
function removeColor(color){
var canvasData = ctx.getImageData(0, 0, 256, 256),
pix = canvasData.data;
for (var i = 0, n = pix.length; i <n; i += 4) {
if(pix[i] === color[0] && pix[i+1] === color[1] && pix[i+2] === color[2]){
pix[i+3] = 0;
}
}
ctx.putImageData(canvasData, 0, 0);
}
removeColor([0,0,255]); // Removes blue.
And like Simon pointed out the code above will get the exact color. Below will grab the approximate color, which is good if you have colors overlapping or very close to each other.
Demo 2 with approximation

HTML Canvas: update globalAlpha property

I'm trying to update the globalAlpha of a canvas element after its painted. The canvas contains an image, and two texts. I show the code at the bottom.
I want to change the globalAlpha property from 0.6 to 1 afterwards. How can i do this most elegantly with performance in mind?
var ctx = canvasElement.getContext("2d");
ctx.globalAlpha = 0.6;
//background gradient
var gradient = ctx.createLinearGradient(0, 0, 0, options["height"]);
gradient.addColorStop(0, options["colorStop0"]);
gradient.addColorStop(1, options["colorStop1"]);
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, options["width"], options["height"]);
//program
ctx.font = options.programText["font"];
ctx.fillStyle = options.programText["color"];
ctx.fillText(prog.title, options.programText["x"], options.programText["y"]);
//channel number
ctx.font = options.channelNumber["font"];
ctx.fillStyle = options.channelNumber["color"];
ctx.fillText(item_index + 1, options.channelNumber["x"], options.channelNumber["y"]);
//channel logo
var channelLogo = new Image();
channelLogo.onload = function () {
var clX = options.channelLogo["x"];
var clY = options.channelLogo["y"];
ctx.drawImage(channelLogo, clX, clY, channelLogo.width, channelLogo.height);
};
channelLogo.src = this.getChannelLogo(channel);
You cannot update the globalAlpha of a shape after it is painted.
More to the point, you cannot "update" anything after it is painted. There is no updating in Canvas. You must instead redraw the thing(s) with the attributes changed.
So in your case you will simply want to clear your canvas and redraw everything with globalAlpha set back to 1.
You can update canvas after painting by just doing pixel manipulation.
Using the getImageData & putImageData method of context of canvas.
But there is not any method like "changeAlpha(x,y,width,height,alphaValue)" of context of canvas.
Same kind of problem i am also facing in my app.
If your alpha is going up to 100%, you can probably just repaint it without redrawing the whole scene (overwriting what was there previously). The only risk is some antialiasing artifacts if you're doing curves.
If you alpha is going down, however, you have to do as Simon says - repaint the whole scene.

html canvas shadow being applied to everything

If you define a shadow ONCE, then it applies to all "graphics" on the canvas from thereon after (which is what it's supposed to do).
Sample:
http://flanvas.com/development/flanvas/test.html
Does anyone know best practice to turn the shadow off after you've used it? I'm setting shadowColor to "rgba(0,0,0,0)" which is a no-alpha black. I'm sure there is a better way.
case sample: The text is also getting a shadow. I'm using the no-alpha black to combat this for now.
http://flanvas.com/development/flanvas/examples/filters-dropShadowFilter.html
By using save, translate and restore you can perform your tasks without worrying about the style changes, for eg.
ctx.save();
ctx.translate(X,Y);
ctx.shadowColor = 'rgba(255, 0, 0, 0.5)';
// do some stuff
ctx.restore();
here X & Y are the co-ordinates where you intended to draw and you do your stuff relative to the co-ordinates 0,0.
This method solves the problem of caching and restoring the previous styles/values and is also very helpful when you work with gradients as they are always plotted relative to the origin (0,0)
(EDIT: Oops! I see that's what you were already doing with a 0 alpha black.)
This is what you were looking for:
context.shadowColor = "transparent";
It's usually a good idea to store the old value of these kind of "global" attributes before you change it and use this stored value to restore it later on. Example:
var origShadowColor = ctx.shadowColor;
ctx.shadowColor = 'rgba(255, 0, 0, 0.5)';
// ... do some stuff
ctx.shadowColor = origShadowColor;
I created a function i can call to reset the shadow if needed.
resetShadow() {
this.ctx.shadowOffsetX = 0;
this.ctx.shadowOffsetY = 0;
this.ctx.shadowColor = "transparent";
}