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

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

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

<!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>

%s 个评论

要回复文章请先登录注册