Skip to content

Commit 338dae6

Browse files
committed
Integrate copyediting for chapter 17
1 parent 18867fe commit 338dae6

File tree

1 file changed

+27
-29
lines changed

1 file changed

+27
-29
lines changed

17_canvas.md

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ quote}}
1414

1515
{{index CSS, "transform (CSS)", [DOM, graphics]}}
1616

17-
Browsers give us several ways to display ((graphics)). The simplest way is to use styles to position and color regular DOM elements. This can get you quite far, as the game in the [previous chapter](game) showed. By adding partially transparent background ((image))s to the nodes, we can make them look exactly the way we want. It is even possible to rotate or skew nodes with the `transform` style.
17+
Browsers give us several ways to display ((graphics)). The simplest way is to use styles to position and color regular DOM elements. This can get us quite far, as the game in the [previous chapter](game) showed. By adding partially transparent background ((image))s to the nodes, we can make them look exactly the way we want. It is even possible to rotate or skew nodes with the `transform` style.
1818

1919
But we'd be using the DOM for something that it wasn't originally designed for. Some tasks, such as drawing a ((line)) between arbitrary points, are extremely awkward to do with regular HTML elements.
2020

@@ -28,7 +28,7 @@ The second alternative is called a _((canvas))_. A canvas is a single DOM elemen
2828

2929
## SVG
3030

31-
This book will not go into ((SVG)) in detail, but I will briefly explain how it works. At the [end of the chapter](canvas#graphics_tradeoffs), I'll come back to the trade-offs that you must consider when deciding which ((drawing)) mechanism is appropriate for a given application.
31+
This book won't go into ((SVG)) in detail, but I'll briefly explain how it works. At the [end of the chapter](canvas#graphics_tradeoffs), I'll come back to the trade-offs that you must consider when deciding which ((drawing)) mechanism is appropriate for a given application.
3232

3333
This is an HTML document with a simple SVG ((picture)) in it:
3434

@@ -104,19 +104,19 @@ if}}
104104

105105
{{index SVG, coordinates}}
106106

107-
Just like in HTML (and SVG), the coordinate system that the canvas uses puts (0,0) at the top-left corner, and the positive y-((axis)) goes down from there. So (10,10) is 10 pixels below and to the right of the top-left corner.
107+
Just like in HTML (and SVG), the coordinate system that the canvas uses puts (0,0) at the top-left corner, and the positive y-((axis)) goes down from there. This means (10,10) is 10 pixels below and to the right of the top-left corner.
108108

109109
{{id fill_stroke}}
110110

111111
## Lines and surfaces
112112

113113
{{index filling, stroking, drawing, SVG}}
114114

115-
In the ((canvas)) interface, a shape can be _filled_, meaning its area is given a certain color or pattern, or it can be _stroked_, which means a ((line)) is drawn along its edge. The same terminology is used by SVG.
115+
In the ((canvas)) interface, a shape can be _filled_, meaning its area is given a certain color or pattern, or it can be _stroked_, which means a ((line)) is drawn along its edge. SVG uses the same terminology.
116116

117117
{{index "fillRect method", "strokeRect method"}}
118118

119-
The `fillRect` method fills a ((rectangle)). It takes first the x- and y-((coordinates)) of the rectangle's top-left corner, then its width, and then its height. A similar method called `strokeRect` draws the ((outline)) of a rectangle.
119+
The `fillRect` method fills a ((rectangle)). It takes first the x- and y-((coordinates)) of the rectangle's top-left corner, then its width, then its height. A similar method called `strokeRect` draws the ((outline)) of a rectangle.
120120

121121
{{index [state, "of canvas"]}}
122122

@@ -200,7 +200,7 @@ When filling a path (using the `fill` method), each ((shape)) is filled separate
200200
</script>
201201
```
202202

203-
This example draws a filled triangle. Note that only two of the triangle's sides are explicitly drawn. The third, from the bottom-right corner back to the top, is implied and wouldn't be there when you stroke the path.
203+
This example draws a filled triangle. Note that only two of the triangle's sides are explicitly drawn. The third, from the bottom-right corner back to the top, is implied and wouldn't be there if you stroked the path.
204204

205205
{{if book
206206

@@ -250,7 +250,7 @@ We draw a ((quadratic curve)) from the left to the right, with (60,10) as contro
250250

251251
{{index canvas, "bezierCurveTo method"}}
252252

253-
The `bezierCurveTo` method draws a similar kind of curve. Instead of a single ((control point)), this one has two—one for each of the ((line))'s endpoints. Here is a similar sketch to illustrate the behavior of such a curve:
253+
The `bezierCurveTo` method draws a similar kind of curve. Instead of a single ((control point)), this method has two—one for each of the ((line))'s endpoints. Here is a similar sketch to illustrate the behavior of such a curve:
254254

255255
```{lang: html}
256256
<canvas></canvas>
@@ -302,21 +302,23 @@ Those last two parameters make it possible to draw only part of the circle. The
302302

303303
{{index "moveTo method", "arc method", [path, " canvas"]}}
304304

305-
The resulting picture contains a ((line)) from the right of the full circle (first call to `arc`) to the right of the quarter-((circle)) (second call). Like other path-drawing methods, a line drawn with `arc` is connected to the previous path segment. You can call `moveTo` or start a new path to avoid this.
305+
The resulting picture contains a ((line)) from the right of the full circle (first call to `arc`) to the right of the quarter-((circle)) (second call).
306306

307307
{{if book
308308

309309
{{figure {url: "img/canvas_circle.png", alt: "Screenshot of a circle", width: "4.9cm"}}}
310310

311311
if}}
312312

313+
Like other path-drawing methods, a line drawn with `arc` is connected to the previous path segment.You can call `moveTo` or start a new path to avoid this.
314+
313315
{{id pie_chart}}
314316

315317
## Drawing a pie chart
316318

317319
{{index "pie chart example"}}
318320

319-
Imagine you've just taken a ((job)) at EconomiCorp, Inc., and your first assignment is to draw a pie chart of its customer satisfaction ((survey)) results.
321+
Imagine we've just taken a ((job)) at EconomiCorp, Inc. Your first assignment is to draw a pie chart of its customer satisfaction ((survey)) results.
320322

321323
The `results` binding contains an array of objects that represent the survey responses.
322324

@@ -400,7 +402,7 @@ In computer ((graphics)), a distinction is often made between _vector_ graphics
400402

401403
{{index "load event", "event handling", "img (HTML tag)", "drawImage method"}}
402404

403-
The `drawImage` method allows us to draw ((pixel)) data onto a ((canvas)). This pixel data can originate from an `<img>` element or from another canvas. The following example creates a detached `<img>` element and loads an image file into it. But it cannot immediately start drawing from this picture because the browser may not have loaded it yet. To deal with this, we register a `"load"` event handler and do the drawing after the image has loaded.
405+
The `drawImage` method allows us to draw ((pixel)) data onto a ((canvas)). This pixel data can originate from an `<img>` element or from another canvas. The following example creates a detached `<img>` element and loads an image file into it. But the method cannot immediately start drawing from this picture because the browser may not have loaded it yet. To deal with this, we register a `"load"` event handler and do the drawing after the image has loaded.
404406

405407
```{lang: html}
406408
<canvas></canvas>
@@ -418,13 +420,13 @@ The `drawImage` method allows us to draw ((pixel)) data onto a ((canvas)). This
418420

419421
{{index "drawImage method", scaling}}
420422

421-
By default, `drawImage` will draw the image at its original size. You can also give it two additional arguments to set a different width and height.
423+
By default, `drawImage` will draw the image at its original size. You can also give it two additional arguments to specify the width and height of the drawn image, when those aren't the same as origin image.
422424

423425
When `drawImage` is given _nine_ arguments, it can be used to draw only a fragment of an image. The second through fifth arguments indicate the rectangle (x, y, width, and height) in the source image that should be copied, and the sixth to ninth arguments give the rectangle (on the canvas) into which it should be copied.
424426

425427
{{index "player", "pixel art"}}
426428

427-
This can be used to pack multiple _((sprite))s_ (image elements) into a single image file and then draw only the part you need. For example, we have this picture containing a game character in multiple ((pose))s:
429+
This can be used to pack multiple _((sprite))s_ (image elements) into a single image file and then draw only the part you need. For example, this picture contains a game character in multiple ((pose))s:
428430

429431
{{figure {url: "img/player_big.png", alt: "Pixel art showing a computer game character in 10 different poses. The first 8 form its running animation cycle, the 9th has the character standing still, and the 10th shows him jumping.", width: "6cm"}}}
430432

@@ -472,7 +474,7 @@ The `cycle` binding tracks our position in the animation. For each ((frame)), it
472474

473475
{{indexsee flipping, mirroring}}
474476

475-
But what if we want our character to walk to the left instead of to the right? We could draw another set of sprites, of course. But we can also instruct the ((canvas)) to draw the picture the other way round.
477+
What if we want our character to walk to the left instead of to the right? We could draw another set of sprites, of course. But we could also instruct the ((canvas)) to draw the picture the other way round.
476478

477479
{{index "scale method", scaling}}
478480

@@ -504,15 +506,15 @@ Scaling will cause everything about the drawn image, including the ((line width)
504506

505507
{{index "drawImage method"}}
506508

507-
So to turn a picture around, we can't simply add `cx.scale(-1, 1)` before the call to `drawImage` because that would move our picture outside of the ((canvas)), where it won't be visible. You could adjust the ((coordinates)) given to `drawImage` to compensate for this by drawing the image at x position -50 instead of 0. Another solution, which doesn't require the code that does the drawing to know about the scale change, is to adjust the ((axis)) around which the scaling happens.
509+
To turn a picture around, we can't simply add `cx.scale(-1, 1)` before the call to `drawImage`. That would move our picture outside of the ((canvas)), where it won't be visible. We could adjust the ((coordinates)) given to `drawImage` to compensate for this by drawing the image at x position -50 instead of 0. Another solution, which doesn't require the code doing the drawing to know about the scale change, is to adjust the ((axis)) around which the scaling happens.
508510

509511
{{index "rotate method", "translate method", transformation}}
510512

511513
There are several other methods besides `scale` that influence the coordinate system for a ((canvas)). You can rotate subsequently drawn shapes with the `rotate` method and move them with the `translate` method. The interesting—and confusing—thing is that these transformations _stack_, meaning that each one happens relative to the previous transformations.
512514

513515
{{index "rotate method", "translate method"}}
514516

515-
So if we translate by 10 horizontal pixels twice, everything will be drawn 20 pixels to the right. If we first move the center of the coordinate system to (50,50) and then rotate by 20 ((degree))s (about 0.1π ((radian))s), that rotation will happen _around_ point (50,50).
517+
If we translate by 10 horizontal pixels twice, everything will be drawn 20 pixels to the right. If we first move the center of the coordinate system to (50,50) and then rotate by 20 ((degree))s (about 0.1π ((radian))s), that rotation will happen _around_ point (50,50).
516518

517519
{{figure {url: "img/transform.svg", alt: "Diagram showing the result of stacking transformations. The first diagram translates and then rotates, causing the translation to happen normally and rotation to happen around the target of the translation. The second diagram first rotates, and then translates, causing the rotation to happen around the origin and the translation direction to be tilted by that rotation.", width: "9cm"}}}
518520

@@ -623,7 +625,7 @@ We define another display object type called `CanvasDisplay`, supporting the sam
623625

624626
{{index [state, "in objects"]}}
625627

626-
This object keeps a little more information than `DOMDisplay`. Rather than using the scroll position of its DOM element, it tracks its own ((viewport)), which tells us what part of the level we are currently looking at. Finally, it keeps a `flipPlayer` property so that even when the player is standing still, it keeps facing the direction it last moved in.
628+
This object keeps a little more information than `DOMDisplay`. Rather than using the scroll position of its DOM element, it tracks its own ((viewport)), which tells us which part of the level we are currently looking at. Finally, it keeps a `flipPlayer` property so that even when the player is standing still, it keeps facing the direction in which it last moved.
627629

628630
```{sandbox: "game", includeCode: true}
629631
class CanvasDisplay {
@@ -748,11 +750,11 @@ Tiles that are not empty are drawn with `drawImage`. The `otherSprites` image co
748750

749751
{{index scaling}}
750752

751-
Background tiles are 20 by 20 pixels since we will use the same scale that we used in `DOMDisplay`. Thus, the offset for lava tiles is 20 (the value of the `scale` binding), and the offset for walls is 0.
753+
Background tiles are 20 by 20 pixels, since we'll use the same scale as in `DOMDisplay`. Thus, the offset for lava tiles is 20 (the value of the `scale` binding), and the offset for walls is 0.
752754

753755
{{index drawing, "load event", "drawImage method"}}
754756

755-
We don't bother waiting for the sprite image to load. Calling `drawImage` with an image that hasn't been loaded yet will simply do nothing. Thus, we might fail to draw the game properly for the first few ((frame))s, while the image is still loading, but that is not a serious problem. Since we keep updating the screen, the correct scene will appear as soon as the loading finishes.
757+
We don't bother waiting for the sprite image to load. Calling `drawImage` with an image that hasn't been loaded yet will simply do nothing. Thus, we might fail to draw the game properly for the first few ((frame))s while the image is still loading, but that isn't a serious problem. Since we keep updating the screen, the correct scene will appear as soon as the loading finishes.
756758

757759
{{index "player", [animation, "platform game"], drawing}}
758760

@@ -818,7 +820,7 @@ When ((drawing)) something that is not the ((player)), we look at its type to fi
818820

819821
{{index viewport}}
820822

821-
We have to subtract the viewport's position when computing the actor's position since (0,0) on our ((canvas)) corresponds to the top left of the viewport, not the top left of the level. We could also have used `translate` for this. Either way works.
823+
We have to subtract the viewport's position when computing the actor's position, since (0,0) on our ((canvas)) corresponds to the top left of the viewport, not the top left of the level. We could also have used `translate` for this. Either way works.
822824

823825
{{if interactive
824826

@@ -848,7 +850,7 @@ if}}
848850

849851
## Choosing a graphics interface
850852

851-
Thus, when you need to generate graphics in the browser, you can choose between plain HTML, ((SVG)), and ((canvas)). There is no single _best_ approach that works in all situations. Each option has strengths and weaknesses.
853+
When you need to generate graphics in the browser, you can choose between plain HTML, ((SVG)), and ((canvas)). There is no single _best_ approach that works in all situations. Each option has strengths and weaknesses.
852854

853855
{{index "text wrapping"}}
854856

@@ -862,19 +864,15 @@ SVG can be used to produce ((crisp)) ((graphics)) that look good at any zoom lev
862864

863865
Both SVG and HTML build up a data structure (the DOM) that represents your picture. This makes it possible to modify elements after they are drawn. If you need to repeatedly change a small part of a big ((picture)) in response to what the user is doing or as part of an ((animation)), doing it in a canvas can be needlessly expensive. The DOM also allows us to register mouse event handlers on every element in the picture (even on shapes drawn with SVG). You can't do that with canvas.
864866

865-
{{index performance, optimization}}
866-
867-
But ((canvas))'s ((pixel))-oriented approach can be an advantage when drawing a huge number of tiny elements. The fact that it does not build up a data structure but only repeatedly draws onto the same pixel surface gives canvas a lower cost per shape.
868-
869-
{{index "ray tracer"}}
867+
{{index performance, optimization, "ray tracer"}}
870868

871-
There are also effects, such as rendering a scene one ((pixel)) at a time (for example, using a ray tracer) or postprocessing an image with JavaScript (blurring or distorting it), that are only practical with a canvas element.
869+
But ((canvas))'s ((pixel))-oriented approach can be an advantage when drawing a huge number of tiny elements. The fact that it does not build up a data structure but only repeatedly draws onto the same pixel surface gives canvas a lower cost per shape. There are also effects that are only practical with a canvas element, such as rendering a scene one ((pixel)) at a time (for example, using a ray tracer) or postprocessing an image with JavaScript (blurring or distorting it).
872870

873871
In some cases, you may want to combine several of these techniques. For example, you might draw a ((graph)) with ((SVG)) or ((canvas)) but show ((text))ual information by positioning an HTML element on top of the picture.
874872

875873
{{index display}}
876874

877-
For nondemanding applications, it really doesn't matter much which interface you choose. The display we built for our game in this chapter could have been implemented using any of these three ((graphics)) technologies since it does not need to draw text, handle mouse interaction, or work with an extraordinarily large number of elements.
875+
For nondemanding applications, it really doesn't matter much which interface you choose. The display we built for our game in this chapter could have been implemented using any of these three ((graphics)) technologies, since it does not need to draw text, handle mouse interaction, or work with an extraordinarily large number of elements.
878876

879877
## Summary
880878

@@ -918,7 +916,7 @@ Write a program that draws the following ((shape))s on a ((canvas)):
918916

919917
{{figure {url: "img/exercise_shapes.png", alt: "Picture showing the shapes you are asked to draw", width: "8cm"}}}
920918

921-
When drawing the last two, you may want to refer to the explanation of `Math.cos` and `Math.sin` in [Chapter ?](dom#sin_cos), which describes how to get coordinates on a circle using these functions.
919+
When drawing the last two shapes, you may want to refer to the explanation of `Math.cos` and `Math.sin` in [Chapter ?](dom#sin_cos), which describes how to get coordinates on a circle using these functions.
922920

923921
{{index readability, "hard-coding"}}
924922

@@ -1077,7 +1075,7 @@ One unfortunate thing about ((transformation))s is that they slow down the drawi
10771075

10781076
In a game like ours, where we are drawing only a single transformed sprite, this is a nonissue. But imagine that we need to draw hundreds of characters or thousands of rotating particles from an explosion.
10791077

1080-
Think of a way to allow us to draw an inverted character without loading additional image files and without having to make transformed `drawImage` calls every frame.
1078+
Think of a way to draw an inverted character without loading additional image files and without having to make transformed `drawImage` calls every frame.
10811079

10821080
{{hint
10831081

0 commit comments

Comments
 (0)