欢快畅游的小鱼特效

news2024/12/28 18:43:47

Jquery 欢快畅游的小鱼特效
在这里插入图片描述

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>欢快畅游的小鱼特效</title>
	<head>

		<!--背景渐变效果样式代码开始(可忽略)-->
		<style type="text/css">
			html,body{width:100%;height:100%;margin:0;padding:0;}
			body{
			background: -webkit-linear-gradient(left,rgba(89,114,192,0.8),rgba(89,114,192,0.2));
			background: -o-linear-gradient(right,rgba(89,114,192,0.8),rgba(89,114,192,0.2));
			background: -moz-linear-gradient(right,rgba(89,114,192,0.8),rgba(89,114,192,0.2));
			background: linear-gradient(to right, rgba(89,114,192,0.8), rgba(89,114,192,0.2));
			background-size: 400% 400%;
			animation: gradientBG 5s ease infinite;}
			@keyframes gradientBG {
			0% {
			background-position: 0% 50%;
			}
			50% {
			background-position: 100% 50%;
			}
			100% {
			background-position: 0% 50%;
			}
			}
		</style>
		<!--背景渐变效果样式代码结束(可忽略)-->

		<!--定义底部承载游动小鱼特效的div样式开始-->
		<style type="text/css">
			.container{
			margin:0;
			padding:0;
			background-color:transparent;
			width:100%;
			height:200px;
			z-index:-1;
			position:fixed;
			bottom:0;
			left:0;}
		</style>
		<!--定义底部承载游动小鱼特效的div样式结束-->

	</head>
	<body>

		<!--引入jquery-->
		<script src="https://www.jq22.com/jquery/jquery-1.7.1.js"></script>

		<!--承载游动小鱼特效的div容器-->
		<div id="jsi-flying-fish-container" class="container"></div>

		<!--核心特效定义js-->
		<script src='fish.js'></script>

	</body>
</html>

fish.js

var RENDERER = {
	POINT_INTERVAL : 5,
	FISH_COUNT : 3,
	MAX_INTERVAL_COUNT : 50,
	INIT_HEIGHT_RATE : 0.5,
	THRESHOLD : 50,
	
	init : function(){
		this.setParameters();
		this.reconstructMethods();
		this.setup();
		this.bindEvent();
		this.render();
	},
	setParameters : function(){
		this.$window = $(window);
		this.$container = $('#jsi-flying-fish-container');
		this.$canvas = $('<canvas />');
		this.context = this.$canvas.appendTo(this.$container).get(0).getContext('2d');
		this.points = [];
		this.fishes = [];
		this.watchIds = [];
	},
	createSurfacePoints : function(){
		var count = Math.round(this.width / this.POINT_INTERVAL);
		this.pointInterval = this.width / (count - 1);
		this.points.push(new SURFACE_POINT(this, 0));
		
		for(var i = 1; i < count; i++){
			var point = new SURFACE_POINT(this, i * this.pointInterval),
				previous = this.points[i - 1];
				
			point.setPreviousPoint(previous);
			previous.setNextPoint(point);
			this.points.push(point);
		}
	},
	reconstructMethods : function(){
		this.watchWindowSize = this.watchWindowSize.bind(this);
		this.jdugeToStopResize = this.jdugeToStopResize.bind(this);
		this.startEpicenter = this.startEpicenter.bind(this);
		this.moveEpicenter = this.moveEpicenter.bind(this);
		this.reverseVertical = this.reverseVertical.bind(this);
		this.render = this.render.bind(this);
	},
	setup : function(){
		this.points.length = 0;
		this.fishes.length = 0;
		this.watchIds.length = 0;
		this.intervalCount = this.MAX_INTERVAL_COUNT;
		this.width = this.$container.width();
		this.height = this.$container.height();
		this.fishCount = this.FISH_COUNT * this.width / 500 * this.height / 500;
		this.$canvas.attr({width : this.width, height : this.height});
		this.reverse = false;
		
		this.fishes.push(new FISH(this));
		this.createSurfacePoints();
	},
	watchWindowSize : function(){
		this.clearTimer();
		this.tmpWidth = this.$window.width();
		this.tmpHeight = this.$window.height();
		this.watchIds.push(setTimeout(this.jdugeToStopResize, this.WATCH_INTERVAL));
	},
	clearTimer : function(){
		while(this.watchIds.length > 0){
			clearTimeout(this.watchIds.pop());
		}
	},
	jdugeToStopResize : function(){
		var width = this.$window.width(),
			height = this.$window.height(),
			stopped = (width == this.tmpWidth && height == this.tmpHeight);
			
		this.tmpWidth = width;
		this.tmpHeight = height;
		
		if(stopped){
			this.setup();
		}
	},
	bindEvent : function(){
		this.$window.on('resize', this.watchWindowSize);
		this.$container.on('mouseenter', this.startEpicenter);
		this.$container.on('mousemove', this.moveEpicenter);
		this.$container.on('click', this.reverseVertical);
	},
	getAxis : function(event){
		var offset = this.$container.offset();
		
		return {
			x : event.clientX - offset.left + this.$window.scrollLeft(),
			y : event.clientY - offset.top + this.$window.scrollTop()
		};
	},
	startEpicenter : function(event){
		this.axis = this.getAxis(event);
	},
	moveEpicenter : function(event){
		var axis = this.getAxis(event);
		
		if(!this.axis){
			this.axis = axis;
		}
		this.generateEpicenter(axis.x, axis.y, axis.y - this.axis.y);
		this.axis = axis;
	},
	generateEpicenter : function(x, y, velocity){
		if(y < this.height / 2 - this.THRESHOLD || y > this.height / 2 + this.THRESHOLD){
			return;
		}
		var index = Math.round(x / this.pointInterval);
		
		if(index < 0 || index >= this.points.length){
			return;
		}
		this.points[index].interfere(y, velocity);
	},
	reverseVertical : function(){
		this.reverse = !this.reverse;
		
		for(var i = 0, count = this.fishes.length; i < count; i++){
			this.fishes[i].reverseVertical();
		}
	},
	controlStatus : function(){
		for(var i = 0, count = this.points.length; i < count; i++){
			this.points[i].updateSelf();
		}
		for(var i = 0, count = this.points.length; i < count; i++){
			this.points[i].updateNeighbors();
		}
		if(this.fishes.length < this.fishCount){
			if(--this.intervalCount == 0){
				this.intervalCount = this.MAX_INTERVAL_COUNT;
				this.fishes.push(new FISH(this));
			}
		}
	},
	render : function(){
		requestAnimationFrame(this.render);
		this.controlStatus();
		this.context.clearRect(0, 0, this.width, this.height);
		this.context.fillStyle = 'hsl(0, 0%, 95%)';
		
		for(var i = 0, count = this.fishes.length; i < count; i++){
			this.fishes[i].render(this.context);
		}
		this.context.save();
		this.context.globalCompositeOperation = 'xor';
		this.context.beginPath();
		this.context.moveTo(0, this.reverse ? 0 : this.height);
		
		for(var i = 0, count = this.points.length; i < count; i++){
			this.points[i].render(this.context);
		}
		this.context.lineTo(this.width, this.reverse ? 0 : this.height);
		this.context.closePath();
		this.context.fill();
		this.context.restore();
	}
};
var SURFACE_POINT = function(renderer, x){
	this.renderer = renderer;
	this.x = x;
	this.init();
};
SURFACE_POINT.prototype = {
	SPRING_CONSTANT : 0.03,
	SPRING_FRICTION : 0.9,
	WAVE_SPREAD : 0.3,
	ACCELARATION_RATE : 0.01,
	
	init : function(){
		this.initHeight = this.renderer.height * this.renderer.INIT_HEIGHT_RATE;
		this.height = this.initHeight;
		this.fy = 0;
		this.force = {previous : 0, next : 0};
	},
	setPreviousPoint : function(previous){
		this.previous = previous;
	},
	setNextPoint : function(next){
		this.next = next;
	},
	interfere : function(y, velocity){
		this.fy = this.renderer.height * this.ACCELARATION_RATE * ((this.renderer.height - this.height - y) >= 0 ? -1 : 1) * Math.abs(velocity);
	},
	updateSelf : function(){
		this.fy += this.SPRING_CONSTANT * (this.initHeight - this.height);
		this.fy *= this.SPRING_FRICTION;
		this.height += this.fy;
	},
	updateNeighbors : function(){
		if(this.previous){
			this.force.previous = this.WAVE_SPREAD * (this.height - this.previous.height);
		}
		if(this.next){
			this.force.next = this.WAVE_SPREAD * (this.height - this.next.height);
		}
	},
	render : function(context){
		if(this.previous){
			this.previous.height += this.force.previous;
			this.previous.fy += this.force.previous;
		}
		if(this.next){
			this.next.height += this.force.next;
			this.next.fy += this.force.next;
		}
		context.lineTo(this.x, this.renderer.height - this.height);
	}
};
var FISH = function(renderer){
	this.renderer = renderer;
	this.init();
};
FISH.prototype = {
	GRAVITY : 0.4,
	
	init : function(){
		this.direction = Math.random() < 0.5;
		this.x = this.direction ? (this.renderer.width + this.renderer.THRESHOLD) : -this.renderer.THRESHOLD;
		this.previousY = this.y;
		this.vx = this.getRandomValue(4, 10) * (this.direction ? -1 : 1);
		
		if(this.renderer.reverse){
			this.y = this.getRandomValue(this.renderer.height * 1 / 10, this.renderer.height * 4 / 10);
			this.vy = this.getRandomValue(2, 5);
			this.ay = this.getRandomValue(0.05, 0.2);
		}else{
			this.y = this.getRandomValue(this.renderer.height * 6 / 10, this.renderer.height * 9 / 10);
			this.vy = this.getRandomValue(-5, -2);
			this.ay = this.getRandomValue(-0.2, -0.05);
		}
		this.isOut = false;
		this.theta = 0;
		this.phi = 0;
	},
	getRandomValue : function(min, max){
		return min + (max - min) * Math.random();
	},
	reverseVertical : function(){
		this.isOut = !this.isOut;
		this.ay *= -1;
	},
	controlStatus : function(context){
		this.previousY = this.y;
		this.x += this.vx;
		this.y += this.vy;
		this.vy += this.ay;
		
		if(this.renderer.reverse){
			if(this.y > this.renderer.height * this.renderer.INIT_HEIGHT_RATE){
				this.vy -= this.GRAVITY;
				this.isOut = true;
			}else{
				if(this.isOut){
					this.ay = this.getRandomValue(0.05, 0.2);
				}
				this.isOut = false;
			}
		}else{
			if(this.y < this.renderer.height * this.renderer.INIT_HEIGHT_RATE){
				this.vy += this.GRAVITY;
				this.isOut = true;
			}else{
				if(this.isOut){
					this.ay = this.getRandomValue(-0.2, -0.05);
				}
				this.isOut = false;
			}
		}
		if(!this.isOut){
			this.theta += Math.PI / 20;
			this.theta %= Math.PI * 2;
			this.phi += Math.PI / 30;
			this.phi %= Math.PI * 2;
		}
		this.renderer.generateEpicenter(this.x + (this.direction ? -1 : 1) * this.renderer.THRESHOLD, this.y, this.y - this.previousY);
		
		if(this.vx > 0 && this.x > this.renderer.width + this.renderer.THRESHOLD || this.vx < 0 && this.x < -this.renderer.THRESHOLD){
			this.init();
		}
	},
	render : function(context){
		context.save();
		context.translate(this.x, this.y);
		context.rotate(Math.PI + Math.atan2(this.vy, this.vx));
		context.scale(1, this.direction ? 1 : -1);
		context.beginPath();
		context.moveTo(-30, 0);
		context.bezierCurveTo(-20, 15, 15, 10, 40, 0);
		context.bezierCurveTo(15, -10, -20, -15, -30, 0);
		context.fill();
		
		context.save();
		context.translate(40, 0);
		context.scale(0.9 + 0.2 * Math.sin(this.theta), 1);
		context.beginPath();
		context.moveTo(0, 0);
		context.quadraticCurveTo(5, 10, 20, 8);
		context.quadraticCurveTo(12, 5, 10, 0);
		context.quadraticCurveTo(12, -5, 20, -8);
		context.quadraticCurveTo(5, -10, 0, 0);
		context.fill();
		context.restore();
		
		context.save();
		context.translate(-3, 0);
		context.rotate((Math.PI / 3 + Math.PI / 10 * Math.sin(this.phi)) * (this.renderer.reverse ? -1 : 1));
		
		context.beginPath();
		
		if(this.renderer.reverse){
			context.moveTo(5, 0);
			context.bezierCurveTo(10, 10, 10, 30, 0, 40);
			context.bezierCurveTo(-12, 25, -8, 10, 0, 0);
		}else{
			context.moveTo(-5, 0);
			context.bezierCurveTo(-10, -10, -10, -30, 0, -40);
			context.bezierCurveTo(12, -25, 8, -10, 0, 0);
		}
		context.closePath();
		context.fill();
		context.restore();
		context.restore();
		this.controlStatus(context);
	}
};
$(function(){
	RENDERER.init();
});

jquery.min.js 1.7.1下载
也可引入在线jquery
下班~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/62247.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

年产2万吨山楂酒工厂的设计-包装工段及车间的设计(lunwen+任务书+cad图纸)

目录 1 前 言 1 2 工艺概述 2 2.1 工艺简述 2 2.2 山楂酒酿造工艺流程 2 2.2.1原料挑选 2 2.2.2清洗分选 2 2.2.3破碎去核 2 2.2.4成分调整 3 2.2.5活化酵母 3 2.2.6接种发酵&#xff08;前发酵&#xff09; 3 2.2.7发酵原酒&#xff08;后发酵&#xff09; 3 2.2.8陈酿 3 2.2.…

在vue项目中使用less全局变量

1、安装less和less-loader npm i less less-loader -D 2、此时全局变量并未生效&#xff0c;需要安装开发依赖&#xff1a; npm i style-resources-loader vue-cli-plugin-style-resources-loader -D并在vue.config.js文件中配置&#xff0c;指定全局变量文件&#xff1a; 3…

[附源码]计算机毕业设计万佳商城管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

自行车无级变速器设计

目录 1绪论 1 1.1 机械无级变速器的特征和应用 1 1.2 机械无级变速器的分类 1 1.3 机械无级变速器的发展概况 2 1.4 无级变速自行车研究现状 3 1.5 自行车无级变速器运用实例 5 1.6 研究的目的和意义 7 1.7 毕业论文设计内容和要求 8 2 自行车无级变速器总体方案的选择 8 2.1 钢…

多目标优化算法:基于非支配排序的蜣螂优化算法(Non-Dominated Sorting Dung beetle optimizer,NSDBO)

蜣螂优化算法&#xff08;Dung beetle optimizer&#xff0c;DBO&#xff09;由Jiankai Xue和Bo Shen于2022年提出&#xff0c;该算法主要受蜣螂的滚球、跳舞、觅食、偷窃和繁殖行为的启发所得。 一、蜣螂优化算法 1.1蜣螂滚球 &#xff08;1&#xff09;当蜣螂前行无障碍时…

第7节:CSS概述,选择器,标签分类,CSS三大特性

1、什么是 CSS&#xff1f;CSS 全称为 Cascading Style Sheets&#xff0c;中文翻译为“层叠样式表”&#xff0c;简称 CSS。在网页制作时采用 CSS 技术&#xff0c;可以有效地对页面的布局、字体、颜色、背景和其它效果实现更加精确的控制。只要对相应的代码做一些简单的修改&…

Word处理控件Aspose.Words功能演示:在 Python 中将 PDF 转换为 JPG

PDF文件以文档、发票、收据、文章等形式随处可见。它是打印和共享文档最方便的格式之一。在某些情况下&#xff0c;您必须将 PDF 文件转换为JPG图像以生成缩略图或嵌入到您的前端应用程序中。为此&#xff0c;本文介绍了如何在 Python 中以编程方式将 PDF 中的页面转换为 JPG 图…

有来实验室|第一篇:Seata1.5.2版本部署和开源全栈商城订单支付业务实战

在线体验&#xff1a;Seata实验室 一. 前言 相信 youlai-mall 的实验室大家有曾在项目中见到过&#xff0c;但应该都还处于陌生的阶段&#xff0c;毕竟在此之前实验室多是以概念般的形式存在&#xff0c;所以我想借着此次的机会&#xff0c;对其进行一个详细的说明。 实验室模…

[附源码]JAVA毕业设计课程在线反馈系统(系统+LW)

[附源码]JAVA毕业设计课程在线反馈系统&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术…

OPNET Modeler 软件的简单介绍与使用

文章目录前言一、OPNET 中的重要概念二、OPNET 编辑器简介三、用 OPNET 建立网络拓扑结构四、收集统计量五、仿真及结果1、运行仿真2、查看仿真结果①查看服务器 Ethernet load 结果②查看服务器 Ethernet Delay 结果六、复制场景并扩展网络1、复制场景2、运行仿真及结果总结前…

[附源码]计算机毕业设计基于SpringBoot的实验填报管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

宏鑫科技在创业板过会:前三季度收入约7亿元,王文志为实控人

近日&#xff0c;深圳证券交易所创业板披露的信息显示&#xff0c;浙江宏鑫科技股份有限公司&#xff08;下称“宏鑫科技”&#xff09;获得创业板上市委会议通过。本次冲刺上市&#xff0c;宏鑫科技计划募资7.48亿元&#xff0c;用于年产100万件高端锻造汽车铝合金车轮智造工厂…

Spring Boot 热部署与日志

Spring Boot 热部署与日志 1.springboot中devtools热部署 1.1 引言 为了进一步提高开发效率,springboot为我们提供了全局项目热部署,日后在开发过程中修改了部分代码以及相关配置文件后,不需要每次重启使修 改生效,在项目中开启了springboot全局热部署之后只需要在修改之后等待…

项目管理工具dhtmlxGantt入门教程(二):如何初始化dhtmlxGantt(上)

dhtmlxGantt 是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表&#xff0c;可满足项目管理控件应用程序的所有需求&#xff0c;有很完善的甘特图图表库。当您使用 dhtmlxGantt 开发应用程序时&#xff0c;您需要做的第一件事就是初始化&#xff0c;或者简单地说&#xff0…

浅谈 volatile

1.简介 volatile 在Java日常开发中,尤其是并发编程中,是一个高频使用的关键字,它提供了一种轻量级的同步机制(常用于和synchronized比较),用来修饰成员变量。volatile 具有如下两大特性: 1. 保证内存可见性2. 禁止指令重排序 volatile 无法保证原子性。 2.内存可见性 我们先…

HTTP 长连接和 TCP 长连接有什么区别

目录 一、HTTP 的 Keep-Alive 二、TCP 的 Keepalive 三、总结 事实上&#xff0c;这两个完全是两样不同东西&#xff0c;实现的层面也不同&#xff1a; HTTP 的 Keep-Alive&#xff0c;是由应用层&#xff08;用户态&#xff09; 实现的&#xff0c;称为 HTTP 长连接&#x…

简约的博客网页制作 大学生个人博客网页设计模板 学生个人网页成品 DIV简单个人网站作品下载 静态HTML CSS个人网页作业源代码

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

【翻译】Domain Enhanced Arbitrary Image Style Transfer via Contrastive Learning

文章目录ABSTRACT1 INTRODUCTION2 RELATED WORK3 METHOD3.1 Multi-layer Style Projector3.2 Contrastive Style Learning3.3 Domain Enhancement3.4 Network Training4 EXPERIMENTS4.1 Qualitative Evaluation4.2 Quantitative Evaluation4.3 Ablation Study5 CONCLUSION AND …

装饰模式Decorator

1.意图&#xff1a;动态地给一个对象添加一些额外的职责。就增加功能而言&#xff0c;Decorator模式比生成子类更加灵活。 2.结构 Component定义一个对象接口&#xff0c;可以给这些对象动态地添加职责&#xff1b; ConcreteComponent定义一个对象&#xff0c;可以给这个对象…

[附源码]JAVA毕业设计六如文学网站(系统+LW)

[附源码]JAVA毕业设计六如文学网站&#xff08;系统LW&#xff09; 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a;…