JavaScript
主页 > 网络编程 > JavaScript >

花瓣漫天飞舞js特效,简单浪漫

2023-01-03 | 佚名 | 点击:

《黛玉葬花》是文学名著《红楼梦》中的经典片段。林黛玉最怜惜花,觉得花落以后埋在土里(文中指出的是“花冢”)最干净,说明她对美有独特的见解。她写了《葬花吟》,以花比喻自己,在《红楼梦》中是最美丽的诗歌之一。

现代社会结婚、走红毯等很多时候会撒花瓣,满天花瓣和赏烟花一样,人们都觉得那一瞬间好美丽好浪漫。就像昙花一现,美好的事物总是很短暂,提醒人们去珍惜。这篇文章主要介绍了花瓣漫天飞舞js特效,简单浪漫,程序猿们可以跟女朋友一起欣赏

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 PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<HTML>

<HEAD>

    <TITLE>花瓣漫天飞舞入流水</TITLE>

    <META NAME="Generator" CONTENT="EditPlus">

    <META NAME="Author" CONTENT="">

    <META NAME="Keywords" CONTENT="">

    <META NAME="Description" CONTENT="">

    <style>

        html, body{

            width: 100%;

            height: 100%;

            margin: 0;

            padding: 0;

            overflow: hidden;

        }

        .container{

            width: 100%;

            height: 100%;

            margin: 0;

            padding: 0;

            background-color: #000000;

        }

    </style>

    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

</HEAD>

  

<BODY>

  

<div id="jsi-cherry-container" class="container"></div>

<script>

    var RENDERER = {

        INIT_CHERRY_BLOSSOM_COUNT : 30,

        MAX_ADDING_INTERVAL : 10,

  

        init : function(){

            this.setParameters();

            this.reconstructMethods();

            this.createCherries();

            this.render();

        },

        setParameters : function(){

            this.$container = $('#jsi-cherry-container');

            this.width = this.$container.width();

            this.height = this.$container.height();

            this.context = $('<canvas />').attr({width : this.width, height : this.height}).appendTo(this.$container).get(0).getContext('2d');

            this.cherries = [];

            this.maxAddingInterval = Math.round(this.MAX_ADDING_INTERVAL * 1000 / this.width);

            this.addingInterval = this.maxAddingInterval;

        },

        reconstructMethods : function(){

            this.render = this.render.bind(this);

        },

        createCherries : function(){

            for(var i = 0, length = Math.round(this.INIT_CHERRY_BLOSSOM_COUNT * this.width / 1000); i < length; i++){

                this.cherries.push(new CHERRY_BLOSSOM(this, true));

            }

        },

        render : function(){

            requestAnimationFrame(this.render);

            this.context.clearRect(0, 0, this.width, this.height);

  

            this.cherries.sort(function(cherry1, cherry2){

                return cherry1.z - cherry2.z;

            });

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

                if(!this.cherries[i].render(this.context)){

                    this.cherries.splice(i, 1);

                }

            }

            if(--this.addingInterval == 0){

                this.addingInterval = this.maxAddingInterval;

                this.cherries.push(new CHERRY_BLOSSOM(this, false));

            }

        }

    };

    var CHERRY_BLOSSOM = function(renderer, isRandom){

        this.renderer = renderer;

        this.init(isRandom);

    };

    CHERRY_BLOSSOM.prototype = {

        FOCUS_POSITION : 300,

        FAR_LIMIT : 600,

        MAX_RIPPLE_COUNT : 100,

        RIPPLE_RADIUS : 100,

        SURFACE_RATE : 0.5,

        SINK_OFFSET : 20,

  

        init : function(isRandom){

            this.x = this.getRandomValue(-this.renderer.width, this.renderer.width);

            this.y = isRandom ? this.getRandomValue(0, this.renderer.height) : this.renderer.height * 1.5;

            this.z = this.getRandomValue(0, this.FAR_LIMIT);

            this.vx = this.getRandomValue(-2, 2);

            this.vy = -2;

            this.theta = this.getRandomValue(0, Math.PI * 2);

            this.phi = this.getRandomValue(0, Math.PI * 2);

            this.psi = 0;

            this.dpsi = this.getRandomValue(Math.PI / 600, Math.PI / 300);

            this.opacity = 0;

            this.endTheta = false;

            this.endPhi = false;

            this.rippleCount = 0;

  

            var axis = this.getAxis(),

                theta = this.theta + Math.ceil(-(this.y + this.renderer.height * this.SURFACE_RATE) / this.vy) * Math.PI / 500;

            theta %= Math.PI * 2;

  

            this.offsetY = 40 * ((theta <= Math.PI / 2 || theta >= Math.PI * 3 / 2) ? -1 : 1);

            this.thresholdY = this.renderer.height / 2 + this.renderer.height * this.SURFACE_RATE * axis.rate;

            this.entityColor = this.renderer.context.createRadialGradient(0, 40, 0, 0, 40, 80);

            this.entityColor.addColorStop(0, 'hsl(330, 70%, ' + 50 * (0.3 + axis.rate) + '%)');

            this.entityColor.addColorStop(0.05, 'hsl(330, 40%,' + 55 * (0.3 + axis.rate) + '%)');

            this.entityColor.addColorStop(1, 'hsl(330, 20%, ' + 70 * (0.3 + axis.rate) + '%)');

            this.shadowColor = this.renderer.context.createRadialGradient(0, 40, 0, 0, 40, 80);

            this.shadowColor.addColorStop(0, 'hsl(330, 40%, ' + 30 * (0.3 + axis.rate) + '%)');

            this.shadowColor.addColorStop(0.05, 'hsl(330, 40%,' + 30 * (0.3 + axis.rate) + '%)');

            this.shadowColor.addColorStop(1, 'hsl(330, 20%, ' + 40 * (0.3 + axis.rate) + '%)');

        },

        getRandomValue : function(min, max){

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

        },

        getAxis : function(){

            var rate = this.FOCUS_POSITION / (this.z + this.FOCUS_POSITION),

                x = this.renderer.width / 2 + this.x * rate,

                y = this.renderer.height / 2 - this.y * rate;

            return {rate : rate, x : x, y : y};

        },

        renderCherry : function(context, axis){

            context.beginPath();

            context.moveTo(0, 40);

            context.bezierCurveTo(-60, 20, -10, -60, 0, -20);

            context.bezierCurveTo(10, -60, 60, 20, 0, 40);

            context.fill();

  

            for(var i = -4; i < 4; i++){

                context.beginPath();

                context.moveTo(0, 40);

                context.quadraticCurveTo(i * 12, 10, i * 4, -24 + Math.abs(i) * 2);

                context.stroke();

            }

        },

        render : function(context){

            var axis = this.getAxis();

  

            if(axis.y == this.thresholdY && this.rippleCount < this.MAX_RIPPLE_COUNT){

                context.save();

                context.lineWidth = 2;

                context.strokeStyle = 'hsla(0, 0%, 100%, ' + (this.MAX_RIPPLE_COUNT - this.rippleCount) / this.MAX_RIPPLE_COUNT + ')';

                context.translate(axis.x + this.offsetY * axis.rate * (this.theta <= Math.PI ? -1 : 1), axis.y);

                context.scale(1, 0.3);

                context.beginPath();

                context.arc(0, 0, this.rippleCount / this.MAX_RIPPLE_COUNT * this.RIPPLE_RADIUS * axis.rate, 0, Math.PI * 2, false);

                context.stroke();

                context.restore();

                this.rippleCount++;

            }

            if(axis.y < this.thresholdY || (!this.endTheta || !this.endPhi)){

                if(this.y <= 0){

                    this.opacity = Math.min(this.opacity + 0.01, 1);

                }

                context.save();

                context.globalAlpha = this.opacity;

                context.fillStyle = this.shadowColor;

                context.strokeStyle = 'hsl(330, 30%,' + 40 * (0.3 + axis.rate) + '%)';

                context.translate(axis.x, Math.max(axis.y, this.thresholdY + this.thresholdY - axis.y));

                context.rotate(Math.PI - this.theta);

                context.scale(axis.rate * -Math.sin(this.phi), axis.rate);

                context.translate(0, this.offsetY);

                this.renderCherry(context, axis);

                context.restore();

            }

            context.save();

            context.fillStyle = this.entityColor;

            context.strokeStyle = 'hsl(330, 40%,' + 70 * (0.3 + axis.rate) + '%)';

            context.translate(axis.x, axis.y + Math.abs(this.SINK_OFFSET * Math.sin(this.psi) * axis.rate));

            context.rotate(this.theta);

            context.scale(axis.rate * Math.sin(this.phi), axis.rate);

            context.translate(0, this.offsetY);

            this.renderCherry(context, axis);

            context.restore();

  

            if(this.y <= -this.renderer.height / 4){

                if(!this.endTheta){

                    for(var theta = Math.PI / 2, end = Math.PI * 3 / 2; theta <= end; theta += Math.PI){

                        if(this.theta < theta && this.theta + Math.PI / 200 > theta){

                            this.theta = theta;

                            this.endTheta = true;

                            break;

                        }

                    }

                }

                if(!this.endPhi){

                    for(var phi = Math.PI / 8, end = Math.PI * 7 / 8; phi <= end; phi += Math.PI * 3 / 4){

                        if(this.phi < phi && this.phi + Math.PI / 200 > phi){

                            this.phi = Math.PI / 8;

                            this.endPhi = true;

                            break;

                        }

                    }

                }

            }

            if(!this.endTheta){

                if(axis.y == this.thresholdY){

                    this.theta += Math.PI / 200 * ((this.theta < Math.PI / 2 || (this.theta >= Math.PI && this.theta < Math.PI * 3 / 2)) ? 1 : -1);

                }else{

                    this.theta += Math.PI / 500;

                }

                this.theta %= Math.PI * 2;

            }

            if(this.endPhi){

                if(this.rippleCount == this.MAX_RIPPLE_COUNT){

                    this.psi += this.dpsi;

                    this.psi %= Math.PI * 2;

                }

            }else{

                this.phi += Math.PI / ((axis.y == this.thresholdY) ? 200 : 500);

                this.phi %= Math.PI;

            }

            if(this.y <= -this.renderer.height * this.SURFACE_RATE){

                this.x += 2;

                this.y = -this.renderer.height * this.SURFACE_RATE;

            }else{

                this.x += this.vx;

                this.y += this.vy;

            }

            return this.z > -this.FOCUS_POSITION && this.z < this.FAR_LIMIT && this.x < this.renderer.width * 1.5;

        }

    };

    $(function(){

        RENDERER.init();

    });

</script>

</BODY>

</HTML>

原文链接:
相关文章
最新更新