广告位联系
返回顶部
分享到

JavaScript实现瀑布动画的代码

JavaScript 来源:互联网 作者:酷站 发布时间:2022-06-19 14:31:47 人浏览
摘要

具体内容如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

具体内容如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

<!DOCTYPE html>

<html>

    <head>

        <meta charset="utf8">

        <meta http-equiv=“X-UA-Compatible” content="IE-edge, chrome=1">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <title>瀑布(waterful)</title>

        <style>

            body {

                background: #222;

            }

        </style>

    </head>

    <body>

        <script>

            //判断浏览器是否支持canvas

            function isSupportCanvas() {

                var canvas = document.createElement('canvas');

                return !!(canvas.getContext && canvas.getContext("2d"));

            }

 

            //requestAnimationFrame会自动使用最优的帧率进行渲染,在我的浏览器上是每秒60帧

            function setupRAF() {

                var lastTime = 0;

                var vendors = ['webkit', 'ms', 'moz', 'o'];

                for(var i=0; i<vendors.length && !window.requestAnimationFrame; i++) {

                    window.requestAnimationFrame = window[vendors[i] + "RequestAnimationFrame"];

                    window.cancelAnimationFrame = window[vendors[i] + "CancelAnimationFrame"] || window[vendors[i] + "CancelRequestAnimationFrame"]

                }

                if(!window.requestAnimationFrame) {

                    window.requestAnimationFrame = function(callback, element) {

                        var currentTime = new Date().getTime();

                        var timeToCall = Math.max(0, 16 - (currentTime - lastTime));

                        var futureTime = currentTime + timeToCall;

                        var id = window.setTimeout(function() {

                            callback(futureTime);

                        }, timeToCall);

                        lastTime = futureTime;

                        return id;

                    }

                }

                if(!window.cancelAnimationFrame) {

                    window.cancelAnimationFrame = function(id) {

                        clearTimeout(id);

                    }

                }

            }

 

            //在给定的范围内随机选取一个整数

            function randomInt(min, max) {

                /*

                由于位运算的操作数要求是整数,其结果也是整数,所以经过位运算的都会自动变成整数

                可用的取整方法:

                (1)~~n

                (2)n<<0

                (3)n>>0

                (4)n|0

                (5)Math.floor()

                (6)Math.ceil()

                (7)Math.round()

                值得注意的是,位运算只是去掉小数部分,并不会改变整数部分

                */

                return ~~(Math.random() * (max - min) + min);

            }

 

            //在对象所表示的范围中随机选取一个数

            function randomAtRange(obj) {

                return Math.random() * (obj.max - obj.min) + obj.min;

            }

 

            //在对象所表示的范围中随机选取一个整数

            function randomIntAtRange(obj) {

                return randomInt(obj.min, obj.max);

            }

 

            //瀑布

            var Waterful = function(width, height) {

                var doublePI = Math.PI * 2;

 

                var canvas;

                var ctx;

 

                //存放水粒子的数组

                var particles = [];

                //每帧生成或销毁粒子的数量

                var particleChangeRate = width / 25;

                //垂直方向上的加速度(即重力), 小数点前的0可以省略

                var gravity = .15;

 

                //水流粒子

                var WaterParticle = function() {

                    //水流粒子宽度范围

                    var waterWidthRange = {min: 1, max: 20};

                    //水流粒子高度范围

                    var waterHeightRange = {min: 1, max: 45};

                    //水流粒子落到地上溅起的水花半径范围

                    var waterBubbleRadiusRange = {min: 1, max: 8};

                    //水花溅起的高度范围

                    var waterBubbleSpringRange = {min: 20, max: 30};

 

                    //色相范围

                    var hueRange = {min: 200, max: 220};

                    //饱和度范围

                    var saturationRange = {min: 30, max: 60};

                    //亮度

                    var lightnessRange = {min: 30, max: 60};

 

                    //拼接成一个HSLA颜色值(注意:普通函数的this指代它自己)

                    this.joinHSLA = function(alpha) {

                        return "hsla(" + [this.hue, this.saturation + "%", this.lightness + "%", alpha].join(",") + ")";

                    }

 

                    this.init = function() {                        

                        //水流粒子的最大半径

                        var waterMaxRadius = waterWidthRange.max / 2;

                        //水流粒子初始X坐标的范围

                        var xRange = {min: waterMaxRadius, max: canvas.width - waterMaxRadius};

 

                        //水流粒子宽度

                        this.width = randomAtRange(waterWidthRange);

                        //水流粒子高度

                        this.height = randomAtRange(waterHeightRange);

                        //水流粒子初始X坐标

                        this.x = randomAtRange(xRange);

                        //水流粒子初始Y坐标

                        this.y = -this.height;

                        //水流粒子垂直方向上的初始速度

                        this.velocity = 0;

                        //水流半径等于水流粒子宽度的一半

                        this.waterRadius = this.width / 2;

                        //水花半径

                        this.waterBubbleRadius = randomAtRange(waterBubbleRadiusRange);

                        //水花溅起的高度

                        this.waterBubbleSpring = randomAtRange(waterBubbleSpringRange);

                        //水流颜色

                        this.hue = randomIntAtRange(hueRange);

                        this.saturation = randomIntAtRange(saturationRange);

                        this.lightness = randomIntAtRange(lightnessRange);

                        //地板高度

                        this.floorHeight = canvas.height - waterBubbleSpringRange.min - this.height; 

 

                        //水流粒子是否已经落地变成水花

                        this.isDead = false;

                    }

 

                    this.update = function() {

                        this.velocity += gravity;

                        this.y += this.velocity;

                        if(this.y > this.floorHeight) {

                            this.isDead = true;

                        }

                    }

 

                    this.render = function() {

                        if(this.isDead) {

                            //绘制水花

                            ctx.fillStyle = "hsla(" + this.hue + ", 40%, 40%, 1)";

                            ctx.fillStyle = this.joinHSLA(.3);

                            ctx.beginPath();

                            ctx.arc(this.x, canvas.height - this.waterBubbleSpring, this.waterBubbleRadius, 0, doublePI);

                            ctx.fill();

                        } else {

                            //绘制水流

                            ctx.strokeStyle = this.joinHSLA(.05);

                            ctx.lineCap = "round";

                            ctx.lineWidth = this.waterRadius;

                            ctx.beginPath();

                            ctx.moveTo(this.x, this.y);

                            ctx.lineTo(this.x, this.y + this.height);

                            ctx.stroke();

                        }

                    }

 

                    this.init();

                }

 

                this.init = function() {

                    canvas = document.createElement("canvas");

                    //如果html不支持canvas的话会显示该文本,否则不显示

                    var textNode = document.createTextNode("Your browser can not support canvas");

                    canvas.appendChild(textNode);

                    document.body.appendChild(canvas);

                    canvas.width = width;

                    canvas.height = height;

                    //如果不支持canvas就没必要继续下去了

                    if(!isSupportCanvas()) {

                        return;

                    }

                    ctx = canvas.getContext("2d");

                    setupRAF();

                    loop();

                }

 

                function loop() {

                    /*

                    先绘制一层朦胧的白非常重要,这样可以省去很多用来填充颜色的粒子

                    将下面3句换成clearRect就能发现其实绘制的粒子颜色本身是很淡的,如果直接换成深的颜色就会发现空隙衔接处很不均匀

                    增大粒子数目可以发现颜色会变深,但是粒子数越多画面越卡,所以先绘制上一层白色的蒙版是一种非常取巧的做法

                    */

                    ctx.globalCompositeOperation = 'destination-out';

                    ctx.fillStyle = 'rgba(255,255,255,.06)';

                    ctx.fillRect(0, 0, canvas.width, canvas.height);

                    //ctx.clearRect(0, 0, canvas.width, canvas.height);

                    ctx.globalCompositeOperation = "lighter";

 

                    //添加新粒子

                    for(var i=0; i<particleChangeRate; i++) {

                        particles.push(new WaterParticle());

                    }

                    //更新渲染粒子

                    for(var i=0; i<particles.length; i++) {

                        particles[i].update();

                        particles[i].render();

                    }

 

                    //绘制水花,并删除消亡的粒子

                    for(var i=particles.length-1; i>=0; i--) {

                        if(particles[i].isDead) {

                            particles.splice(i, 1);

                        }

                    }

                    requestAnimationFrame(loop);

                }

            }

 

            function init() {

                var waterful = new Waterful(300, 300);

                waterful.init();

            }

 

            init();

        </script>

    </body>

</html>

效果:


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/chy555chy/article/details/54730336
相关文章
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计