Canvas动画(PC端 移动端)

一,介绍与需求

1.1,介绍

canvas是HTML5中新增一个HTML5标签与操作canvas的javascript API,它可以实现在网页中完成动态的2D与3D图像技术。 标记和 SVG以及 VML 之间的一个重要的不同是, 有一个基于 JavaScript 的绘图 API,而 SVG 和 VML 使用一个 XML 文档来描述绘图。SVG 绘图很容易编辑与生成,但功能明显要弱一些。canvas可以完成动画、游戏、图表、图像处理等原来需要Flash完成的一些功能

1.2,需求

实现特殊的动画效果

二,动画实现

以跟随鼠标/手指移动的火为例

第一步:创建Canvas标签

1

第二步:获取Canvas标签

复制代码

1  let canvas = document.getElementById('fire');

2 if (canvas.getContext){

3    var ctx = canvas.getContext('2d');

4    // drawing code here

5  } else {

6    alert("不支持Canvas")

7  }

复制代码

第三步:绘制火花

复制代码

1 var Spark = function (mouse) {

2

3            this.cx = mouse.x;

4            this.cy = mouse.y;

5            this.x = rand(this.cx - 40, this.cx + 40);

6            this.y = rand(this.cy, this.cy + 5);

7            this.lx = this.x;

8            this.ly = this.y;

9            this.vy = rand(1, 3);

10            this.vx = rand(-4, 4);

11            this.r = rand(0, 1);

12            this.life = rand(4, 5);

13            this.alive = true;

14            this.c = {

15

16                h: Math.floor(rand(2, 40)),

17                s: 100,

18                l: rand(40, 100),

19                a: rand(0.8, 0.9)

20

21            }

22

23        }

24        Spark.prototype.update = function () {

25

26            this.lx = this.x;

27            this.ly = this.y;

28

29            this.y -= this.vy;

30            this.x += this.vx;

31

32            if (this.x < this.cx)

33                this.vx += 0.2;

34            else

35                this.vx -= 0.2;

36

37            this.vy += 0.08;

38            this.life -= 0.1;

39

40            if (this.life <= 0) {

41

42                this.c.a -= 0.05;

43

44                if (this.c.a <= 0)

45                    this.alive = false;

46

47            }

48

49        }

50        Spark.prototype.draw = function (ctx) {

51

52            ctx.beginPath();

53            ctx.moveTo(this.lx, this.ly);

54            ctx.lineTo(this.x, this.y);

55            ctx.strokeStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + (this.c.a / 2) + ")";

56            ctx.lineWidth = this.r * 2;

57            ctx.lineCap = 'round';

58            ctx.stroke();

59            ctx.closePath();

60

61            ctx.beginPath();

62            ctx.moveTo(this.lx, this.ly);

63            ctx.lineTo(this.x, this.y);

64            ctx.strokeStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + this.c.a + ")";

65            ctx.lineWidth = this.r;

66            ctx.stroke();

67            ctx.closePath();

68

69        }

复制代码

第四步:绘制火焰

复制代码

1    var Flame = function (mouse) {

2

3            this.cx = mouse.x;

4            this.cy = mouse.y;

5            this.x = rand(this.cx - 25, this.cx + 25);

6            this.y = rand(this.cy - 5, this.cy + 5);

7            this.vy = rand(1, 3);

8            this.vx = rand(-1, 1);

9            this.r = rand(20, 30);

10            this.life = rand(3, 6);

11            this.alive = true;

12            this.c = {

13

14                h: Math.floor(rand(2, 40)),

15                s: 100,

16                l: rand(80, 100),

17                a: 0,

18                ta: rand(0.8, 0.9)

19

20            }

21

22

23        }

24        Flame.prototype.update = function () {

25

26            this.y -= this.vy;

27            this.vy += 0.05;

28

29

30            this.x += this.vx;

31

32            if (this.x < this.cx)

33                this.vx += 0.1;

34            else

35                this.vx -= 0.1;

36

37

38

39

40            if (this.r > 0)

41                this.r -= 0.1;

42

43            if (this.r <= 0)

44                this.r = 0;

45

46

47

48            this.life -= 0.15;

49

50            if (this.life <= 0) {

51

52                this.c.a -= 0.05;

53

54                if (this.c.a <= 0)

55                    this.alive = false;

56

57            } else if (this.life > 0 && this.c.a < this.c.ta) {

58

59                this.c.a += .08;

60

61            }

62

63        }

64        Flame.prototype.draw = function (ctx) {

65

66            ctx.beginPath();

67            ctx.arc(this.x, this.y, this.r * 3, 0, 2 * Math.PI);

68            ctx.fillStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + (this.c.a / 20) + ")";

69            ctx.fill();

70

71            ctx.beginPath();

72            ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);

73            ctx.fillStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + this.c.a + ")";

74            ctx.fill();

75

76        }

复制代码

第五步:绘制火

复制代码

  1    var Fire = function () {

  2

  3            this.canvas = document.getElementById('fire');

  4            this.ctx = this.canvas.getContext('2d');

  5            this.canvas.height = window.innerHeight;// window.innerHeight

  6            this.canvas.width = window.innerWidth;//window.innerWidth

  7

  8            this.aFires = [];

  9            this.aSpark = [];

10            this.aSpark2 = [];

11

12

13

14            this.mouse = {

15                x: this.canvas.width * .5,

16                y: this.canvas.height * .75,

17            }

18

19

20

21            this.init();

22

23        }

24        Fire.prototype.init = function () {

25            //跳转语句

26            if (system.win || system.mac || system.xll) {

27                this.canvas.addEventListener('mousemove', this.updateMouse.bind(this), false);//PC端

28            } else {

29                this.canvas.addEventListener('touchmove', this.updateMouse.bind(this), false);//移动端

30            }

31

32

33        }

34        Fire.prototype.run = function () {

35

36            this.update();

37            this.draw();

38

39            if (this.bRuning)

40                requestAnimationFrame(this.run.bind(this));

41

42        }

43        Fire.prototype.start = function () {

44

45            this.bRuning = true;

46            this.run();

47

48        }

49        Fire.prototype.stop = function () {

50

51            this.bRuning = false;

52

53        }

54        Fire.prototype.update = function () {

55

56            this.aFires.push(new Flame(this.mouse));

57            this.aSpark.push(new Spark(this.mouse));

58            this.aSpark2.push(new Spark(this.mouse));

59

60

61

62            for (var i = this.aFires.length - 1; i >= 0; i--) {

63

64                if (this.aFires[i].alive)

65                    this.aFires[i].update();

66                else

67                    this.aFires.splice(i, 1);

68

69            }

70

71            for (var i = this.aSpark.length - 1; i >= 0; i--) {

72

73                if (this.aSpark[i].alive)

74                    this.aSpark[i].update();

75                else

76                    this.aSpark.splice(i, 1);

77

78            }

79

80

81            for (var i = this.aSpark2.length - 1; i >= 0; i--) {

82

83                if (this.aSpark2[i].alive)

84                    this.aSpark2[i].update();

85                else

86                    this.aSpark2.splice(i, 1);

87

88            }

89

90        }

91

92        Fire.prototype.draw = function () {

93

94            this.ctx.globalCompositeOperation = "source-over";

95            this.ctx.fillStyle = "rgba( 15, 5, 2, 1 )";

96            this.ctx.fillRect(0, 0, window.innerWidth, window.innerHeight);

97

98            this.grd = this.ctx.createRadialGradient(this.mouse.x, this.mouse.y - 200, 200, this.mouse.x, this.mouse.y - 100, 0);

99            this.grd.addColorStop(0, "rgb( 15, 5, 2 )");

100            this.grd.addColorStop(1, "rgb( 30, 10, 2 )");

101            this.ctx.beginPath();

102            this.ctx.arc(this.mouse.x, this.mouse.y - 100, 200, 0, 2 * Math.PI);

103            this.ctx.fillStyle = this.grd;

104            this.ctx.fill();

105

106

107            this.ctx.font = "15em Amatic SC";

108            this.ctx.textAlign = "center";

109            this.ctx.strokeStyle = "rgb(50, 20, 0)";

110            this.ctx.fillStyle = "rgb(120, 10, 0)";

111            this.ctx.lineWidth = 2;

112            this.ctx.strokeText("", this.canvas.width / 2, this.canvas.height * .72);

113            this.ctx.fillText("", this.canvas.width / 2, this.canvas.height * .72);

114

115

116

117            this.ctx.globalCompositeOperation = "overlay";//or lighter or soft-light

118

119            for (var i = this.aFires.length - 1; i >= 0; i--) {

120

121                this.aFires[i].draw(this.ctx);

122

123            }

124

125            this.ctx.globalCompositeOperation = "soft-light";//"soft-light";//"color-dodge";

126

127            for (var i = this.aSpark.length - 1; i >= 0; i--) {

128

129                if ((i % 2) === 0)

130                    this.aSpark[i].draw(this.ctx);

131

132            }

133

134

135            this.ctx.globalCompositeOperation = "color-dodge";//"soft-light";//"color-dodge";

136

137            for (var i = this.aSpark2.length - 1; i >= 0; i--) {

138

139                this.aSpark2[i].draw(this.ctx);

140

141            }

142

143

144        }

145

146        Fire.prototype.updateMouse = function (e) {

147            //跳转语句

148            if (system.win || system.mac || system.xll) {//PC端

149                this.mouse.x = e.clientX;

150                this.mouse.y = e.clientY;

151            } else {//移动端

152                e.preventDefault();//阻止默认行为

153                this.mouse.x = e.changedTouches[0].clientX;

154                this.mouse.y = e.changedTouches[0].clientY;

155            }

156

157

158        }

复制代码

第六步:调用

复制代码

1 var oCanvas;

2        init = function () {

3

4            oCanvas = new Fire();

5            oCanvas.start();

6

7

8        }

9        window.onload = init;

复制代码

随机数函数

1  rand = function (min, max) { return Math.random() * (max - min) + min; };

效果如下:

三,PC端与移动端处理

3.1,判断是PC端还是移动端

复制代码

1    //平台、设备和操作系统

2        var system = {

3            win: false,

4            mac: false,

5            xll: false

6        };

7        //检测平台

8        var p = navigator.platform;

9        system.win = p.indexOf("Win") == 0;

10        system.mac = p.indexOf("Mac") == 0;

11        system.x11 = (p == "X11") || (p.indexOf("Linux") == 0);

12

13 //跳转语句

14            if (system.win || system.mac || system.xll) {

15                this.canvas.addEventListener('mousemove', this.updateMouse.bind(this), false);//PC端 鼠标移动

16            } else {

17                this.canvas.addEventListener('touchmove', this.updateMouse.bind(this), false);//移动端 手指滑动

18            }

复制代码

3.2,PC端还是移动端的事件处理

复制代码

1 //跳转语句

2            if (system.win || system.mac || system.xll) {//PC端

3                this.mouse.x = e.clientX;

4                this.mouse.y = e.clientY;

5            } else {//移动端

6                e.preventDefault();//阻止默认行为

7                this.mouse.x = e.changedTouches[0].clientX;

8                this.mouse.y = e.changedTouches[0].clientY;

9            }

复制代码

移动端需禁止缩放

1   

东莞网站建设www.zg886.cn

你可能感兴趣的:(Canvas动画(PC端 移动端))