├── LICENSE
├── README.MD
├── example-1-1:tic-tac-toe
└── index.html
├── example-1-2:tic-tac-toe - Path2D version
└── index.html
├── example-2:brick
└── index.html
├── example-3:picture-frame
├── index.html
├── picture-frame.jpg
└── tfboys.jpg
├── example-4-1:loading bar
└── index.html
├── example-4-2:loading ring
└── index.html
├── example-5-1:balls
├── ball.class.js
├── baseball.png
├── basketball.png
├── football.png
├── index.html
└── volleyball.png
├── example-5-2:control balls
├── ball.class.js
├── baseball.png
├── basketball.png
├── football.png
├── index.html
└── volleyball.png
├── example-6:photo-edit
├── background.jpg
├── editor.js
├── index.html
├── main.js
├── photo.jpg
├── reset.png
├── style.css
└── watermark.png
├── index.html
├── libs
├── flexbox.css
└── utils.js
├── thirds
├── alloy_finger.js
├── bluebird.core.min.js
├── keymaster.js
├── normalize.css
└── requestAnimationFrame.polyfill.js
└── 思维导图 - canvas常用api.png
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Array Huang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 | # canvas-learning:分享一些本人学习canvas时用来练习的案例
2 |
3 | ## 案例1: 井字游戏
4 |
5 | ### [案例1-1][1]
6 | - 简单应用了canvas的一些基础API,如绘制基本图形以及路径。
7 |
8 | ### [案例1-2][2]
9 | - 练习使用`Path2D`配合`translate`来复用路径。
10 |
11 | ## [案例2:铺砖][3]
12 | - 练一下批量有规律地输出图形,灵感来自前公司楼下的地砖。
13 |
14 | ## [案例3:相框][4]
15 | - 主要是练习canvas图片相关的API。
16 |
17 | ## 案例4:进度条
18 | - 练习canvas文字相关的API。
19 | - 练习canvas动画。
20 |
21 | ### [案例4-1:长条进度条][5]
22 |
23 | ### [案例4-2:圆形进度条][6]
24 |
25 | ## 案例5:做自由落体运动的球
26 |
27 | ### [案例5-1][7]
28 | - 练习**自由落体运动**的动画。
29 | - 练习在动画里同时处理多个图形。
30 |
31 | ### [案例5-2:用户交互加强版][8]
32 | - 用户可以通过拖动球来改变其位置,若新位置不在画布底部,则开始做自由落体运动。
33 | - 练习canvas用户交互。
34 |
35 | ## [案例6:“过年就是这个味儿”活动页][9]
36 | - 此案例来自于我过往的一个项目,当时是用css3来做的,现在改成用canvas来实现。
37 | - 练习触控手势:pressmove / pinch / rotate。
38 | - 练习canvas的变形相关API:translate / scale / rotate。
39 |
40 | ## 附 **思维导图 - canvas常用api**
41 | ![思维导图 - canvas常用api][10]
42 |
43 |
44 | [1]: https://array-huang.github.io/canvas-learning/example-1-1%EF%BC%9Atic-tac-toe
45 | [2]: https://array-huang.github.io/canvas-learning/example-1-2%EF%BC%9Atic-tac-toe%20-%20Path2D%20version
46 | [3]: https://array-huang.github.io/canvas-learning/example-2%EF%BC%9Abrick
47 | [4]: https://array-huang.github.io/canvas-learning/example-3%EF%BC%9Apicture-frame
48 | [5]: https://array-huang.github.io/canvas-learning/example-4-1%EF%BC%9Aloading%20bar
49 | [6]: https://array-huang.github.io/canvas-learning/example-4-2%EF%BC%9Aloading%20ring
50 | [7]: https://array-huang.github.io/canvas-learning/example-5-1%EF%BC%9Aballs
51 | [8]: https://array-huang.github.io/canvas-learning/example-5-2%EF%BC%9Acontrol%20balls
52 | [9]: https://array-huang.github.io/canvas-learning/example-6%EF%BC%9Aphoto-edit
53 | [10]: https://array-huang.github.io/canvas-learning/%E6%80%9D%E7%BB%B4%E5%AF%BC%E5%9B%BE%20-%20canvas%E5%B8%B8%E7%94%A8api.png
--------------------------------------------------------------------------------
/example-1-1:tic-tac-toe/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 案例1: 井字游戏
6 |
7 |
8 |
9 |
61 |
62 |
--------------------------------------------------------------------------------
/example-1-2:tic-tac-toe - Path2D version/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 案例1: 井字游戏
6 |
7 |
8 |
9 |
100 |
101 |
--------------------------------------------------------------------------------
/example-2:brick/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 案例2:铺砖
6 |
7 |
8 |
9 |
129 |
130 |
--------------------------------------------------------------------------------
/example-3:picture-frame/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 案例3:相框
6 |
7 |
8 |
9 |
10 |
61 |
62 |
--------------------------------------------------------------------------------
/example-3:picture-frame/picture-frame.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Array-Huang/canvas-learning/e65a372d23c044c41b836a062dfec3910c6d1971/example-3:picture-frame/picture-frame.jpg
--------------------------------------------------------------------------------
/example-3:picture-frame/tfboys.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Array-Huang/canvas-learning/e65a372d23c044c41b836a062dfec3910c6d1971/example-3:picture-frame/tfboys.jpg
--------------------------------------------------------------------------------
/example-4-1:loading bar/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 案例4-1:长条进度条
6 |
7 |
8 |
9 |
10 |
80 |
81 |
--------------------------------------------------------------------------------
/example-4-2:loading ring/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 案例4-2:圆形进度条
6 |
7 |
8 |
9 |
10 |
85 |
86 |
--------------------------------------------------------------------------------
/example-5-1:balls/ball.class.js:
--------------------------------------------------------------------------------
1 | var HIT_LOST_SPEED = 100;
2 | var g = 600
3 |
4 | var pf = {
5 | calculateCoor: function(ball, t1) {
6 | /* 计算离上次位移经过的时间 */
7 | var deltaT = t1 - ball.t0;
8 | ball.t0 = t1;
9 |
10 | /* 计算速度 */
11 | var newV = ball.v0 + g * deltaT;
12 |
13 | /* 计算位移 */
14 | var s = ball.v0 * deltaT + g * Math.pow(deltaT, 2) / 2;
15 | var newY = ball.y - s; // 球离地面的距离
16 | if (newY < 0) { // 距离小于0表示球已触底
17 | ball.y = 0; // 方便起见,把距离重置为0
18 | /*
19 | 触底反弹,速度方向相反,而且会有一定的衰减,衰减由参数HIT_LOST_SPEED来决定
20 | 如果现时速度小于衰减的量,则直接重置速度为0,表明球已彻底停下
21 | */
22 | ball.v0 = newV > HIT_LOST_SPEED ? -1 * (newV - HIT_LOST_SPEED) : 0;
23 | } else {
24 | ball.y = newY; // 记录好球的新位置
25 | ball.v0 = newV; // 记录好球的新速度
26 | }
27 | },
28 | };
29 |
30 | window.ball = function(params) {
31 | Object.assign(this, params);
32 | }
33 |
34 | window.ball.prototype = {
35 | /* 实例化ball类时需要传入的参数,这些参数是各个球独有的 */
36 | // x: 0, // 绘制图片的基点,即图片的左下角
37 | // y: 300, // 绘制图片的基点,即图片的左下角
38 | // v0: 0, // 球当前的速度,为正数则表示方向向下,为负数则表示方向向上
39 | // t0: null, // 上次计算位移时记录的时间戳
40 |
41 | /* 设置球的坐标 */
42 | setCoor: function(x, y) {
43 | this.x = x;
44 | this.y = y;
45 | },
46 |
47 | /* 计算最新的坐标 */
48 | getStatus: function(t1) {
49 | pf.calculateCoor(this, t1);
50 | return {
51 | x: this.x,
52 | y: this.y,
53 | v0: this.v0,
54 | };
55 | },
56 | };
57 |
--------------------------------------------------------------------------------
/example-5-1:balls/baseball.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Array-Huang/canvas-learning/e65a372d23c044c41b836a062dfec3910c6d1971/example-5-1:balls/baseball.png
--------------------------------------------------------------------------------
/example-5-1:balls/basketball.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Array-Huang/canvas-learning/e65a372d23c044c41b836a062dfec3910c6d1971/example-5-1:balls/basketball.png
--------------------------------------------------------------------------------
/example-5-1:balls/football.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Array-Huang/canvas-learning/e65a372d23c044c41b836a062dfec3910c6d1971/example-5-1:balls/football.png
--------------------------------------------------------------------------------
/example-5-1:balls/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 案例5:做自由落体运动的球
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
122 |
123 |
--------------------------------------------------------------------------------
/example-5-1:balls/volleyball.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Array-Huang/canvas-learning/e65a372d23c044c41b836a062dfec3910c6d1971/example-5-1:balls/volleyball.png
--------------------------------------------------------------------------------
/example-5-2:control balls/ball.class.js:
--------------------------------------------------------------------------------
1 | var HIT_LOST_SPEED = 50;
2 | var g = 600
3 |
4 | var pf = {
5 | calculateCoor: function(ball, t1) {
6 | /*
7 | 以下情况,只记录当前时间戳而不需要计算球坐标(即球静止不动)
8 | - 第一次运行
9 | - 球触底
10 | */
11 | if (!ball.t0 || (ball.y === 0 && ball.v0 === 0)) {
12 | ball.t0 = t1;
13 | return;
14 | }
15 |
16 | /* 计算离上次位移经过的时间 */
17 | var deltaT = t1 - ball.t0;
18 | ball.t0 = t1;
19 |
20 | if (ball.isControlled) { // 如果球被控制住了,则不改变它
21 | return;
22 | }
23 |
24 | /* 计算速度 */
25 | var newV = ball.v0 + g * deltaT;
26 |
27 | /* 计算位移 */
28 | var s = ball.v0 * deltaT + g * Math.pow(deltaT, 2) / 2;
29 | var newY = ball.y - s; // 球离地面的距离
30 | if (newY < 0) { // 距离小于0表示球已触底
31 | ball.y = 0; // 方便起见,把距离重置为0
32 | /*
33 | 触底反弹,速度方向相反,而且会有一定的衰减,衰减由参数HIT_LOST_SPEED来决定
34 | 如果现时速度小于衰减的量,则直接重置速度为0,表明球已彻底停下
35 | */
36 | ball.v0 = newV > HIT_LOST_SPEED ? -1 * (newV - HIT_LOST_SPEED) : 0;
37 | } else {
38 | ball.y = newY; // 记录好球的新位置
39 | ball.v0 = newV; // 记录好球的新速度
40 | }
41 | },
42 |
43 | moveBall: function(mouse, ball, canvas, BALL_SIZE) {
44 | // 需要注意的是,对于球来说,始终是以画布左下角作为坐标原点的
45 | return function() {
46 | /* 使球的中心与鼠标保持一致,以此来计算绘制球的基点(即左下角) */
47 | ball.x = mouse.x - BALL_SIZE / 2;
48 | ball.x = ball.x < 0 ? 0 : ball.x;
49 | ball.y = (canvas.height - mouse.y) - BALL_SIZE / 2; // 由于鼠标的坐标是以左上角为坐标原点的,因此需要转换坐标
50 | ball.y = ball.y < 0 ? 0 : ball.y;
51 | };
52 | },
53 | };
54 |
55 | window.ball = function(params) {
56 | Object.assign(this, params);
57 | }
58 |
59 | window.ball.prototype = {
60 | /* 实例化ball类时需要传入的参数,这些参数是各个球独有的 */
61 | // x: 0, // 绘制图片的基点,即图片的左下角
62 | // y: 300, // 绘制图片的基点,即图片的左下角
63 | // v0: 0, // 球当前的速度,为正数则表示方向向下,为负数则表示方向向上
64 | // t0: null, // 上次计算位移时记录的时间戳
65 | // isControlled: false, // 是否被控制住了
66 |
67 | /* 设置球的坐标 */
68 | setCoor: function(x, y) {
69 | this.x = x;
70 | this.y = y;
71 | },
72 |
73 | /* 计算最新的坐标 */
74 | getStatus: function(t1) {
75 | pf.calculateCoor(this, t1);
76 | return {
77 | x: this.x,
78 | y: this.y,
79 | v0: this.v0,
80 | };
81 | },
82 |
83 | /* 控制住球 */
84 | control: function(element, mouse, BALL_SIZE) {
85 | var nowBall = this;
86 | this.isControlled = true;
87 | this.v0 = 0; // 因为被控制住了,速度归零
88 | this.t0 = null; // “上次计算坐标”的时间戳重置
89 | var mouseMoveCb = pf.moveBall(mouse, this, element, BALL_SIZE);
90 | element.addEventListener('mousemove', mouseMoveCb); // 鼠标移动时触发,用于保持球跟随鼠标移动
91 | var mouseUpCb = function() { // 解绑事件,解除控制状态
92 | element.removeEventListener('mousemove', mouseMoveCb);
93 | element.removeEventListener('mouseup', mouseUpCb);
94 | nowBall.isControlled = false;
95 | };
96 | element.addEventListener('mouseup', mouseUpCb); // 鼠标按键弹起时触发,相当于结束控制
97 | },
98 | };
99 |
--------------------------------------------------------------------------------
/example-5-2:control balls/baseball.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Array-Huang/canvas-learning/e65a372d23c044c41b836a062dfec3910c6d1971/example-5-2:control balls/baseball.png
--------------------------------------------------------------------------------
/example-5-2:control balls/basketball.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Array-Huang/canvas-learning/e65a372d23c044c41b836a062dfec3910c6d1971/example-5-2:control balls/basketball.png
--------------------------------------------------------------------------------
/example-5-2:control balls/football.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Array-Huang/canvas-learning/e65a372d23c044c41b836a062dfec3910c6d1971/example-5-2:control balls/football.png
--------------------------------------------------------------------------------
/example-5-2:control balls/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 案例5-2:用户交互加强版
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 说明:各球可拖拽,松开鼠标自由落体
14 |
143 |
144 |
--------------------------------------------------------------------------------
/example-5-2:control balls/volleyball.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Array-Huang/canvas-learning/e65a372d23c044c41b836a062dfec3910c6d1971/example-5-2:control balls/volleyball.png
--------------------------------------------------------------------------------
/example-6:photo-edit/background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Array-Huang/canvas-learning/e65a372d23c044c41b836a062dfec3910c6d1971/example-6:photo-edit/background.jpg
--------------------------------------------------------------------------------
/example-6:photo-edit/editor.js:
--------------------------------------------------------------------------------
1 | /* 照片编辑器的单例 */
2 | window.editorObject = {
3 | canvas: null, // 存放canvas的element对象
4 | context: null, // 存放canvas的context
5 | canvasSize: { //