WEB DEVELOPMENT
jajajaja3Tesis17 de Mayo de 2015
2.752 Palabras (12 Páginas)207 Visitas
Header indie font bundle logo
Grab the Indie Font Bundle today and save over 97%! Check it out
tuts+
Free Tutorials
Courses
eBooks
Blog
Pricing
Sign In
Free Account
Code
Categories
Learning Guides Expert HelpNew!
WEB DEVELOPMENT
Canvas From Scratch: Transformations and Gradients
by Rob Hawkes20 Apr 201124 Comments
Share
1
Share
Share
This post is part of a series called Canvas From Scratch.
Canvas From Scratch: Advanced Drawing
Canvas from Scratch: Pixel Manipulation
In this article, I'm going to walk you through transformations in the canvas, as well as shadows and gradients. Transformations are an extremely valuable set of methods that allow you to start being creative with the way you draw objects on the canvas. Let's get started after the jump!
Setting Up
You're going to use the same HTML template from the previous articles, so open up your favourite editor and paste in the following code:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>
<head>
<title>Canvas from scratch</title>
<meta charset="utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
$(document).ready(function() {
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
});
</script>
</head>
<body>
<canvas id="myCanvas" width="500" height="500">
<!-- Insert fallback content here -->
</canvas>
</body>
</html>
Here we have nothing more than a basic HTML page with a canvas element and some JavaScript that runs after the DOM has loaded. Nothing crazy.
Translations in Action
Translate essentially shifts the entire coordinate system.
One of the simplest transformations in canvas is translate. This allows you to move the origin point of the 2d rendering context; the (0, 0) position on the canvas. Let me show you what this means.
First, place a square in canvas at the position (0, 0):
1
ctx.fillRect(0, 0, 100, 100);
It will draw itself at the top left hand edge of the canvas. Still - nothing out of the ordinary here.
A simple square
Now, try translating the 2d rendering context and drawing another square in the same position:
1
2
3
4
5
ctx.save();
ctx.translate(100, 100);
ctx.fillStyle = "rgb(0, 0, 255)";
ctx.fillRect(0, 0, 100, 100);
ctx.restore();
What do you think will happen? Have a gold star if you guessed that the new square will be drawn at the position (100, 100). No play time for those who guessed wrong. Sorry!
Translating a square
So what happened here then? As far as the code for drawing the second square is concerned, you drew it in the same place as the first square. The reason for this is that you basically shifted the entire coordinate system of the canvas so that its (0, 0) position is now at the place (100, 100).
How translation works
Does it make a little more sense now? I hope so. It can take a little while to get your head around, but it's a simple concept once you understand it.
You probably wouldn't use this transformation too much on its own, as you could simply draw the second square at (100, 100) to get the same effect. The beauty of translate, though, is that you can combine it with other transformations to do some pretty cool things.
Let's take a look at the next transformation on the list.
Scaling Your Visuals
As you've probably guessed, the scale transformation is used for resizing. More specifically, the scale transformation is used to scale the 2d rendering context.
Remove the code that you worked on with the translate example, and add the following code:
1
ctx.fillRect(100, 100, 100, 100);
This will draw a standard square at the position (100, 100), with a width and height of 100 pixels. So how do we scale this?
A simple square
Properties in scale are multipliers for the x and y dimensions.
The scale transformation is used in a similar way to translate, in that it's called before you draw the objects that you want it to be applied to. It's important to point out that the properties in scale are multipliers for the x and y dimensions. This means that a scale of (1, 1) would multiply the size of the 2d rendering context by one, leaving it the same size it was before. A scale of (5, 5) would multiply the size of the 2d rendering context by five, making it five times larger than it was previously. Simple.
In your case you want to double the size of the square, so you apply a scale of (2, 2):
1
2
3
4
ctx.save();
ctx.scale(2, 2);
ctx.fillRect(100, 100, 100, 100);
ctx.restore();
Which results in a square that is two times the size:
Scaling a square
However, notice how the square is now being drawn in a different position than it was being drawn before you applied scale. The reason for this is that scale multiplies the size of everything in the 2d rendering context, including coordinates. In your case, the position (100, 100) now becomes (200, 200); the coordinates are twice the size that they would be without being scaled.
To get around this, we can perform a translate that moves the origin of the 2d rendering context to the position that you want to draw the square. If you then apply scale and draw the square at position (0, 0), its position won't be shifted:
1
2
3
4
5
ctx.save();
ctx.translate(100, 100);
ctx.scale(2, 2);
ctx.fillRect(0, 0, 100, 100);
ctx.restore();
Which results in a square that is twice as large as the original, but that is drawn at the same position as the original:
Scaling and translating square
It's being aware of these little quirks in transformations that really helps when using them. Most of the common issues with transformations seems to be a result of not fully understanding how they work.
Rotating Elements
So far, all the transformations that you've dealt with have been pretty unexciting. Fortunately, the rotate transformation is here to save the day, and it's easily my favourite of the bunch.
I'm sure rotate needs no introduction, so let's jump right in and rotate a square 45 degrees (remember that degrees need to be in radians):
1
2
3
4
ctx.save();
ctx.rotate(Math.PI/4); // Rotate 45 degrees (in radians)
ctx.fillRect(100, 100, 100, 100);
ctx.restore();
Which positions a square at (100, 100) and rotates.. woah, hang on! This doesn't look right:
Rotating a square
See what happened? The square seems to be trying to escape the browser window, rather than rotating on the spot at the position (100, 100). This is because rotate, like all the transformations, affects the entire 2d rendering context, and not objects individually.
Here is an illustration of what happens to the coordinate system when you perform a 45 degree rotate:
How rotation works
Notice how the entire coordinate system has rotated 45 degrees from the point of origin (0, 0)? This is what caused the square to look like it was escaping the browser window, simply because the position (100, 100) had been rotated slap bang on the edge of the browser.
The simple way to get around this issue is to combine rotate with translate, like so:
1
2
3
4
5
ctx.save();
ctx.translate(150, 150); // Translate to centre of square
ctx.rotate(Math.PI/4); // Rotate 45 degrees
ctx.fillRect(-50, -50, 100, 100); // Centre at the rotation point
ctx.restore();
Performing the translate moves the origin point of the 2d rendering context (0, 0) to what should be the central point of the square (150, 150). This means that any rotation will now be based around the position (150, 150). If you then draw a square with a negative x and y position, equal to half of the square's width and height, you'll end up drawing a square that looks like it has been rotated around its central point:
Rotating and translating a square
The rotate transformation is likely the hardest of them all to understand fully. It's important to remember that transformations are performed on
...