I want to implement a clothing design website, but I'm encountering a problem.
I have 1 image shirt, 1 image cloth. I draw shirt to canvas. Now, I want to change cloth shirt by image cloth. But I do not know how to do it.
Example: http://sbhvietnam.vn/shirt-by-hand.html
You can use composite modes to achieve this. Provided the images are loaded and the background behind the image is transparent, and you have set up canvas and context (here ctx) you could do something like this:
/// clear if you reuse this method to avoid pixelated outline
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
/// draw shirt shape
ctx.drawImage(imgShirt, 0, 0);
/// change composite mode for next draw
ctx.globalCompositeOperation = 'source-atop'; /// source-in is an option
/// draw cloth image on top and it will take the shape of the shirt image.
ctx.drawImage(imgCloth, 0, 0);
/// reset composite mode to default mode
ctx.globalCompositeOperation = 'source-over';
Notice that if you should choose to use source-in instead of source-atop you will have to redraw imgShirt every time you want to change the image on top of it.
You can wrap it up in a function you call each time you need to redraw the cloth.
Related
I'm making a Zelda-like game on canvas + js and I don't how to do (or even if it can be done) to apply a filter to a sprite.
I have a scenario drawn, I have multiple characters (enemies, npcs and the player) and I'm trying to do an animation when the player kills an enemy. I'd like to make them "tilt" before I change the enemy sprite with an explosion animation. I'd like to change the whole color of the enemy sprite something like "enemy sprite -> red enemy sprite -> enemy sprite -> red enemy sprite -> explosion".
My question, can I apply a color filter to an image drawn with canvas drawImage? The code to draw the enemy into the canvas scenario is pretty simple:
ctx.drawImage(img, posX, posY, img.width, img.height);
And I have also tried this (as suggested in this other question):
ctx.globalAlpha = 0.62;
ctx.globalCompositeOperation = 'source-atop';
ctx.fillStyle = 'red';
ctx.fillRect(posX, posY, img.width, img.height);
But it applies a mask to a rectangle and not just the sprite (in this picture I applied the above code to every sprite just to watch if it worked):
Any suggestions or help? Thanks!!
I'm trying to create a platform game in Canvas. I have main character and some enemies. When player touch enemy, he will lose some HP and he will be untouchable for about 3s. Now I have one problem. After loosing HP, I want to set opacity of character image to 0.5 (to show that untouchable thing).
var mainchar = new Image();
mainchar.src = 'mainch.png';
I don't want to use ctx.globalCompositeOperation = "lighter" or ctx.globalAlpha = 0.5 becouse both of them change the opacity of all elements (it's global). Is there any way to change the image opacity? For example 'mainchar.changeopacity' ?
You have to either change globalAlpha or draw the image to an off-screen canvas that has globalAlpha set, then draw this canvas onto the main canvas.
Just set alpha, draw the image and reset alpha back to full opacity. Setting alpha does not change the content that is already drawn to the canvas - it only applies to the next thing drawn (which would be the image in this case).
And of course, you can always prep your image with an alpha-channel in case of PNG images.
/// only image will have alpha affected:
context.globalAlpha = 0.5;
context.drawImage(image, x, y);
context.globalAlpha = 1.0;
You can also use save and restore.
context.save();
context.globalAlpha = 0.5;
....
context.restore(); //this will restore canvas state
The simplest method possible is preferable. I unfortunately don't know much about image manipulation!
You can use the globalCompositeOperation ,"hue","saturation","color", and "luminosity"
Where
"hue" will change the destination hue to the hue to that of the source.
"saturation" will change the destination saturation to that of the source
"color" will change the destination color to that of the source.
"luminosity" will change the destination luminosity to that of the source
For example if you want to change the image saturation to full saturation
ctx.drawImage(image,0,0); // image to change
ctx.globalCompositeOperation = "saturation";
ctx.fillStyle = "hsl(0,100%,50%)"; // saturation at 100%
ctx.fillRect(0,0,image.width,image.height); // apply the comp filter
ctx.globalCompositeOperation = "source-over"; // restore default comp
If you want finer control you will have to do it pixel by pixel using getImageData and setimagedata but this can be very slow. For speed you are best to use a webGL filter that will compare to the above comp modes in terms of speed, but the trade off is code complexity.
I wish to draw a rectangle on my canvas but stretching the start point. but how do i erase the previous rectangles drawn during the process. I mean if my background color is red and i want to draw a black rectangle over it. while erasing the intermediate rectangles drawn during rubber banding, i wish to retain the background.
The question is a little hard to understand, but I'm assuming what you want to do is the following using getImageData and putImageData:
// save the entire canvas (in this example, its 500 x 500) to be restored later
image = context.getImageData(0, 0, 500, 500);
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height); // clear entire canvas
context.putImageData(image, 0, 0); // restore entire canvas saved previously
/** Now, draw other stuff on top of the canvas **/
}
You need to redraw the portion of the background the black rectangle previously occupied. It may be simpler to just redraw the entire background.
You simply have to keep track of every single object you want to draw and redraw every single one of them each frame.
You can optimize the process a bit, but you must keep track of each thing drawn so you can redraw.
I'm using the HTML5 canvas to load a single instance of an image which I then blit multiple times onto a single canvas. The image needs some slight pixel-based manipulation in order to customise it. My initial plan of attack had been to load the image, blit it to a backing canvas, draw my modifications on-top of it, and then grab the image data and cache it for future use.
Here's some code I've written to that effect:
context.drawImage(img, 0, 0);
context.fillStyle = '#ffffff';
context.fillRect(0, 0, 2, 2); // Draw a 2x2 rectangle of white pixels on the top left of the image
imageData = context.getImageData(0, 0, img.width, img.height);
cusomImage = imageData;
While this works, I've noticed that my image (which is a transparent PNG) does not maintain transparency. Instead, when using putImageData to place it onto my front-facing canvas, it is rendered with a black background. How do I maintain transparency?
Any suggestions are welcome!
putImageData() does not do what you might first expect:
http://dropshado.ws/post/1244700472/putimagedata-is-a-complete-jerk
putImageData() direct overrides the pixels of the canvas. So if you draw over something else on the same canvas it will not draw "over" it, it will instead replace the pixels of the canvas in the area with it's pixels.
I ran into this exact issue and finally found out why.
As for a solution, I haven't tried this yet but it seems promising:
Why is putImageData so slow?
[EDIT]: I tested this method and it works fine for me, my data is now displaying transparency correctly.
The canvas is black after being created. Make it transparent first with:
context.fillStyle = 'rgba(0,0,0,0)';
context.fillRect(0, 0, width, height);