1 /**
2 * class 的继承等相关知识
3 */
4
5 // extends、 static、 super
6
7 const canvas = document.querySelector('#canvas');
8 const ctx = canvas.getContext('2d');
9
10 const w = canvas.width = 600;
11 const h = canvas.height = 400;
12
13 class Ball {
14 constructor(x, y, r){
15 this.x = x;
16 this.y = y;
17 this.r = r;
18 this.color = `rgb(${~~Ball.rpFn([55, 255])}, ${~~Ball.rpFn([55, 255])}, ${~~Ball.rpFn([55, 255])})`;
19 return this;
20 }
21 render(ctx){
22 ctx.save();
23 ctx.translate(this.x, this.y);
24 ctx.fillStyle = this.color;
25 ctx.beginPath();
26 ctx.arc(0, 0, this.r, 0, 2*Math.PI);
27 ctx.fill();
28 ctx.restore();
29 return this;
30 }
31 static rpFn(arr){ // Ball.rpFn([1, 10])
32 let max = Math.max(...arr),
33 min = Math.min(...arr);
34 return Math.random() * (max - min) + min;
35 }
36 }
37
38 // const ball1 = new Ball(100, 100, 30).render(ctx);
39
40 class SuperBall extends Ball {
41 constructor(x, y, r){
42 // Ball.call(this, x, y, r);
43 // this.color = 'red';
44 super(x, y, r);
45 this.vy = SuperBall.rpFn([2, 4]);
46 this.g = SuperBall.rpFn([0.2, 0.4]);
47 this.a = 0;
48 return this;
49 }
50 move(ctx){
51 // super(); // 报错
52
53 this.y += this.vy;
54 this.vy += this.g;
55
56 let current = this.vy * -0.75;
57
58 if(this.y + this.r >= ctx.canvas.height){
59 this.y = ctx.canvas.height - this.r;
60
61 if(Math.abs(current - this.a) < 0.01) return false;
62
63 this.a = this.vy *= -0.75;
64 }
65
66 ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
67 super.render(ctx);
68
69 return true;
70 }
71 };
72
73 // const ball1 = new SuperBall(100, 100, 30).render(ctx);
74
75 let ball, timer;
76
77 canvas.onclick = function (e){
78 let x = e.offsetX, y = e.offsetY;
79
80 let r = ~~Ball.rpFn([25, 55]);
81
82 ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
83 ball = new SuperBall(x, y, r).render(ctx);
84
85 ballMove();
86 }
87
88 function ballMove(){
89 timer = window.requestAnimationFrame(ballMove);
90
91 if(!ball.move(ctx)){
92 window.cancelAnimationFrame(timer);
93 }
94 }