I have a simple task - I need to draw one rectangle, rotate and copy it and clone its rotated version. I try to do it like so:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
//1. rotate canvas
ctx.rotate(-30 * Math.PI / 180);
ctx.rect(10, 60, 80, 40);
ctx.stroke();
//2. copy rotated rectangle
var img = ctx.getImageData(0, 0, 140, 140);
//3. rotate back
ctx.rotate(30 * Math.PI / 180);
//4. draw rotated version of the rectangle
ctx.putImageData(img, 80, 100);
The idea is very simple. At first step I draw a rectangle, at the second step I rotate my canvas and do what I think is a snapshot (or create a copy of my rotated rectangle), at the third step I rotate my canvas back (so my rotated rectangle must not be rotated any longer) and at the final step I add a new object to the canvas - the copy of the rotated rectangle. But this is what I get:
Whereas I expected to get this picture:
What am I doing wrong and how can I get the desired result?
"putImageData is not affected by the transformation matrix"
See here: putImageData() on rotated canvas work incorrect
Instead, if you want a complex image to be copied into memory, and then repeatedly drawn on the screen at different angles, you might consider using a temporary canvas. This post gives a good example:
How to rotate the existing content of HTML5 canvas?
If you need to create multiple image sprites, and creating multiple canvases won't do, consider drawing your sprite to an appropriately sized temporary canvas, and then convert the contents of the temporary canvas to an image using canvas.toDataUrl
The post gives a nice example:
https://davidwalsh.name/convert-canvas-image
Related
What I would like to do is draw a circle on a canvas and then when a function is called delete the previous circle and draw a new one. Is this possible without having to redraw the whole canvas?
Take the code below for example
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(95, 50, 40, 0, 2 * Math.PI);
ctx.stroke();
A canvas is a collection of pixels (it's exactly like an image, however it's computed from code instead of being just loaded from file).
The only way to remove the old circle and draw the new one (if you want pixel perfect result) is repainting everything with the circle in the new position.
A possible solution could be using three distinct canvas elements layered one on top of the other:
whatever is behind the changing parts
the changing parts
whatever is covering the changing parts
1 and 3 can be kept fixed, you need to redraw only the second canvas.
Say I have drawn a circle on a canvas that has something else drawn on it that stops me from clearing the canvas - due to the other element being randomly generated
var circleX = 50;
var circleY = 10;
var moveCircX = 2;
var moveCircY = 3;
function createCirc(){
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(circleX, circleY, 10, 0, Math.PI*2, true);
ctx.fill();
}
function circMove(){
circleY = (circleY + circMoveY)
//then validation to stop it from being drawn of the canvas
So what I'm trying to do is move the circle but clear the previous drawn circle from the canvas. So is there a solution to clearing the circle or would it be easier to create a sprite that replicates the circle?
Since your background isn't changing, the simplest strategy is to copy the background before you first draw your circle, then draw your circle. When you're moving, redraw that part of the background from the copy you kept, then draw your circle in the new place.
An efficient way to do that is to use getImageData and putImageData.
So, (my javascript is rusty, so this may not be perfect. Feel free to correct any mistakes), before the first time you createCirc, simply do:
imageData = ctx.getImageData(0,0, ctx.canvas.width, ctx.canvas.height)
And, in your circMove function, before you move and redraw the circle, you want:
ctx.putImageData(imageData, circleX, circleY, circleX, circleY, 2*circle_radius, 2*circle_radius)
(You don't define circle_radius, but I'm sure you must have a similar value. I'm using 2x the radius to presumably be the size of the image that is drawn.)
In my web app I am allowing users to choose images. If the height of the image is greater than the width then I rotate the image by 270 degrees.
I am confuse about what should be the ideal size for the rotated image as I would be saving that rotated image later on.
For example if a user upload a image with low resolution what should be the size there and what if the user uploads an image with a high revolution what would be the size than?
I don't want the pixels to be distorted. Any good library to rotate image on the client side? Or any algorithm which can help me?
You could try the naive canvas approach like this:
Basically you'll be drawing the image on a canvas, rotated, then saving the canvas to a dataUrl
var context = canvas.getContext('2d');
//save the context
//pushes a Matrix on the transformation stack
context.save();
context.translate(x, y); //where to put image (in the canvas)
context.rotate(angle); //angle in degrees (i think...)
context.scale(scale); //optional scale
//rotate around center of image
context.drawImage(bitmap, -image.width / 2, -image.height / 2);
//or rotate around top left corner of image
context.drawImage(image, 0, 0);
//restore the canvas
//pop a matrix off the transformation stack
context.restore();
//now save the canvas to a data url for download or to display in an image object / tag
var data = canvas.toDataUrl();
References:
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Transformations
https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement
http://html5.litten.com/understanding-save-and-restore-for-the-canvas-context/
you can use Blob object approach. Convert the image to blob objects and you can play with it. I cant help with code coz am not much aware of blobs. Please do more research on blobs and you can achieve what you want to do using Blobs.
Is it possible to give a glow effect to an image automatically, say using canvas?
jsfiddle
The canvas tag would have to omit the transparent
and make it have an outter glow?
<canvas id="canvas" width=960 height=960></canvas>
Make a canvas path glow by applying a series of overlapping shadows with increasing blur
A Demo: http://jsfiddle.net/m1erickson/Z3Lx2/
You can change the styling of the glow by varying the number of overlays and the blur size.
Example code for a glow effect:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// glow
var glowColor="blue";
ctx.save();
ctx.strokeStyle = glowColor;
ctx.shadowColor = glowColor;
ctx.shadowOffsetX=300;
for (var i = 0; i < 10; i++) {
ctx.shadowBlur = i * 2;
ctx.strokeRect(-270, 30, 75, 150);
}
ctx.restore();
To get the outline path of your phone image, you can use the "marching ants" algorithm.
This algorithm will create a path that outlines an image.
In your case you would define the image as all pixels that are not transparent.
Here's a very good implementation of "marching ants" that is used in the excellent d3 library:
https://github.com/d3/d3-plugins/blob/master/geom/contour/contour.js
It's used like this:
DrawImage your phone on the canvas.
// draw the image
// (this time to grab the image's pixel data
ctx.drawImage(img,0,0);
Get the pixel color array from the canvas using ctx.getImageData
// grab the image's pixel data
imgData=ctx.getImageData(0,0,canvas.width,canvas.height);
data=imgData.data;
Define a function that checks the pixel array for non-transparent pixels at any x,y on the canvas.
// This is used by the marching ants algorithm
// to determine the outline of the non-transparent
// pixels on the image
var defineNonTransparent=function(x,y){
var a=data[(y*cw+x)*4+3];
return(a>20);
}
Call the contour function:
// call the marching ants algorithm
// to get the outline path of the image
// (outline=outside path of transparent pixels
var points=geom.contour(defineNonTransparent);
Here's an example result:
the glow is automatically generated using overlapping shadows
the outline path of the phone is calculated using the marching ants algorithm
I have a roulette wheel created with HTML5 canvas and currently each slice is a plain color generated by using the fillStyle(), beginPath(), stroke(), then fill() methods.
I would like to use images that that crop appropriately in the shape of the slice, but I'm not sure how to implement this using drawImage().
Here's the jsfiddle
http://jsfiddle.net/pyD2q/2/
Any help or resources is appreciated.
Instead of filling the color in you can use it as a clipping mask instead. For each arc, set clip, draw the image and repeat.
Something like this (untested):
for (i = 0; i < s.members.length; i++) {
angle = s.startAngle + i * s.arc;
ctx.beginPath();
ctx.arc(s.width / 2, s.height / 2, s.outsideRadius, angle, angle + s.arc, false);
ctx.arc(s.width / 2, s.height / 2, s.insideRadius, angle + s.arc, angle, true);
ctx.save(); /// store current clip-state
ctx.clip(); /// set current arc as clipping mask
ctx.drawImage(someImageArray[i], x, y, width, height);
ctx.restore(); /// restore clip-state
ctx.stroke(); /// stroke arc
}
You will of course also need to place the images correctly relative to the section and if you want to rotate the image you would need to rotate it at this point.
In that regard I would recommend creating this wheel on an off-screen canvas. This way you only need to draw the off-screen canvas into the main canvas rotated and what have you (saves you the trouble of calculating each angle as well and the performance will be better).