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>

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