原生JS+canvas实现炫酷背景
原生JS+canvas实现炫酷背景 可以在需要的背景页使用
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>HTML5 Canvas矩阵粒子波浪背景动画特效</title>
<style>
html,body {
height:100%;
}
body {
margin:0;
background:#000;
}
canvas {
display:block;
}
.waves {
position:absolute;
left:0;
top:0;
right:0;
bottom:0;
}
</style>
</head>
<body>
<div class="waves"></div>
<script>
class ShaderProgram {
constructor( holder, options = {} ) {
options = Object.assign( {
antialias: false,
depthTest: false,
mousemove: false,
autosize: true,
side: 'front',
vertex: `
precision highp float;
attribute vec4 a_position;
attribute vec4 a_color;
uniform float u_time;
uniform vec2 u_resolution;
uniform vec2 u_mousemove;
uniform mat4 u_projection;
varying vec4 v_color;
void main() {
gl_Position = u_projection * a_position;
gl_PointSize = (10.0 / gl_Position.w) * 100.0;
v_color = a_color;
}`,
fragment: `
precision highp float;
uniform sampler2D u_texture;
uniform int u_hasTexture;
varying vec4 v_color;
void main() {
if ( u_hasTexture == 1 ) {
gl_FragColor = v_color * texture2D(u_texture, gl_PointCoord);
} else {
gl_FragColor = v_color;
}
}`,
uniforms: {},
buffers: {},
camera: {},
texture: null,
onUpdate: ( () => {} ),
onResize: ( () => {} ),
}, options )
const uniforms = Object.assign( {
time: { type: 'float', value: 0 },
hasTexture: { type: 'int', value: 0 },
resolution: { type: 'vec2', value: [ 0, 0 ] },
mousemove: { type: 'vec2', value: [ 0, 0 ] },
projection: { type: 'mat4', value: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] },
}, options.uniforms )
const buffers = Object.assign( {
position: { size: 3, data: [] },
color: { size: 4, data: [] },
}, options.buffers )
const camera = Object.assign( {
fov: 60,
near: 1,
far: 10000,
aspect: 1,
z: 100,
perspective: true,
}, options.camera )
const canvas = document.createElement( 'canvas' )
const gl = canvas.getContext( 'webgl', { antialias: options.antialias } )
if ( ! gl ) return false
this.count = 0
this.gl = gl
this.canvas = canvas
this.camera = camera
this.holder = holder
this.onUpdate = options.onUpdate
this.onResize = options.onResize
this.data = {}
holder.appendChild( canvas )
this.createProgram( options.vertex, options.fragment )
this.createBuffers( buffers )
this.createUniforms( uniforms )
this.updateBuffers()
this.updateUniforms()
this.createTexture( options.texture )
gl.enable( gl.BLEND )
gl.enable( gl.CULL_FACE )
gl.blendFunc( gl.SRC_ALPHA, gl.ONE )
gl[ options.depthTest ? 'enable' : 'disable' ]( gl.DEPTH_TEST )
if ( options.autosize )
window.addEventListener( 'resize', e => this.resize( e ), false )
if ( options.mousemove )
window.addEventListener( 'mousemove', e => this.mousemove( e ), false )
this.resize()
this.update = this.update.bind( this )
this.time = { start: performance.now(), old: performance.now() }
this.update()
}
mousemove( e ) {
let x = e.pageX / this.width * 2 - 1
let y = e.pageY / this.height * 2 - 1
this.uniforms.mousemove = [ x, y ]
}
resize( e ) {
const holder = this.holder
const canvas = this.canvas
const gl = this.gl
const width = this.width = holder.offsetWidth
const height = this.height = holder.offsetHeight
const aspect = this.aspect = width / height
const dpi = this.dpi = devicePixelRatio
canvas.width = width * dpi
canvas.height = height * dpi
canvas.style.width = width + 'px'
canvas.style.height = height + 'px'
gl.viewport( 0, 0, width * dpi, height * dpi )
gl.clearColor( 0, 0, 0, 0 )
this.uniforms.resolution = [ width, height ]
this.uniforms.projection = this.setProjection( aspect )
this.onResize( width, height, dpi )
}
setProjection( aspect ) {
const camera = this.camera
if ( camera.perspective ) {
camera.aspect = aspect
const fovRad = camera.fov * ( Math.PI / 180 )
const f = Math.tan( Math.PI * 0.5 - 0.5 * fovRad )
const rangeInv = 1.0 / ( camera.near - camera.far )
const matrix = [
f / camera.aspect, 0, 0, 0,
0, f, 0, 0,
0, 0, (camera.near + camera.far) * rangeInv, -1,
0, 0, camera.near * camera.far * rangeInv * 2, 0
]
matrix[ 14 ] += camera.z
matrix[ 15 ] += camera.z
return matrix
} else {
return [
2 / this.width, 0, 0, 0,
0, -2 / this.height, 0, 0,
0, 0, 1, 0,
-1, 1, 0, 1,
]
}
}
createShader( type, source ) {
const gl = this.gl
const shader = gl.createShader( type )
gl.shaderSource( shader, source )
gl.compileShader( shader )
if ( gl.getShaderParameter (shader, gl.COMPILE_STATUS ) ) {
return shader
} else {
console.log( gl.getShaderInfoLog( shader ) )
gl.deleteShader( shader )
}
}
createProgram( vertex, fragment ) {
const gl = this.gl
const vertexShader = this.createShader( gl.VERTEX_SHADER, vertex )
const fragmentShader = this.createShader( gl.FRAGMENT_SHADER, fragment )
const program = gl.createProgram()
gl.attachShader( program, vertexShader )
gl.attachShader( program, fragmentShader )
gl.linkProgram( program )
if ( gl.getProgramParameter( program, gl.LINK_STATUS ) ) {
gl.useProgram( program )
this.program = program
} else {
console.log( gl.getProgramInfoLog( program ) )
gl.deleteProgram( program )
}
}
createUniforms( data ) {
const gl = this.gl
const uniforms = this.data.uniforms = data
const values = this.uniforms = {}
Object.keys( uniforms ).forEach( name => {
const uniform = uniforms[ name ]
uniform.location = gl.getUniformLocation( this.program, 'u_' + name )
Object.defineProperty( values, name, {
set: value => {
uniforms[ name ].value = value
this.setUniform( name, value )
},
get: () => uniforms[ name ].value
} )
} )
}
setUniform( name, value ) {
const gl = this.gl
const uniform = this.data.uniforms[ name ]
uniform.value = value
switch ( uniform.type ) {
case 'int': {
gl.uniform1i( uniform.location, value )
break
}
case 'float': {
gl.uniform1f( uniform.location, value )
break
}
case 'vec2': {
gl.uniform2f( uniform.location, ...value )
break
}
case 'vec3': {
gl.uniform3f( uniform.location, ...value )
break
}
case 'vec4': {
gl.uniform4f( uniform.location, ...value )
break
}
case 'mat2': {
gl.uniformMatrix2fv( uniform.location, false, value )
break
}
case 'mat3': {
gl.uniformMatrix3fv( uniform.location, false, value )
break
}
case 'mat4': {
gl.uniformMatrix4fv( uniform.location, false, value )
break
}
}
// ivec2 : uniform2i,
// ivec3 : uniform3i,
// ivec4 : uniform4i,
// sampler2D : uniform1i,
// samplerCube : uniform1i,
// bool : uniform1i,
// bvec2 : uniform2i,
// bvec3 : uniform3i,
// bvec4 : uniform4i,
}
updateUniforms() {
const gl = this.gl
const uniforms = this.data.uniforms
Object.keys( uniforms ).forEach( name => {
const uniform = uniforms[ name ]
this.uniforms[ name ] = uniform.value
} )
}
createBuffers( data ) {
const gl = this.gl
const buffers = this.data.buffers = data
const values = this.buffers = {}
Object.keys( buffers ).forEach( name => {
const buffer = buffers[ name ]
buffer.buffer = this.createBuffer( 'a_' + name, buffer.size )
Object.defineProperty( values, name, {
set: data => {
buffers[ name ].data = data
this.setBuffer( name, data )
if ( name == 'position' )
this.count = buffers.position.data.length / 3
},
get: () => buffers[ name ].data
} )
} )
}
createBuffer( name, size ) {
const gl = this.gl
const program = this.program
const index = gl.getAttribLocation( program, name )
const buffer = gl.createBuffer()
gl.bindBuffer( gl.ARRAY_BUFFER, buffer )
gl.enableVertexAttribArray( index )
gl.vertexAttribPointer( index, size, gl.FLOAT, false, 0, 0 )
return buffer
}
setBuffer( name, data ) {
const gl = this.gl
const buffers = this.data.buffers
if ( name == null && ! gl.bindBuffer( gl.ARRAY_BUFFER, null ) ) return
gl.bindBuffer( gl.ARRAY_BUFFER, buffers[ name ].buffer )
gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( data ), gl.STATIC_DRAW )
}
updateBuffers() {
const gl = this.gl
const buffers = this.buffers
Object.keys( buffers ).forEach( name =>
buffers[ name ] = buffer.data
)
this.setBuffer( null )
}
createTexture( src ) {
const gl = this.gl
const texture = gl.createTexture()
gl.bindTexture( gl.TEXTURE_2D, texture )
gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array( [ 0, 0, 0, 0 ] ) )
this.texture = texture
if ( src ) {
this.uniforms.hasTexture = 1
this.loadTexture( src )
}
}
loadTexture( src ) {
const gl = this.gl
const texture = this.texture
const textureImage = new Image()
textureImage.onload = () => {
gl.bindTexture( gl.TEXTURE_2D, texture )
gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureImage )
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR )
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR )
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
// gl.generateMipmap( gl.TEXTURE_2D )
}
textureImage.src = src
}
update() {
const gl = this.gl
const now = performance.now()
const elapsed = ( now - this.time.start ) / 5000
const delta = now - this.time.old
this.time.old = now
this.uniforms.time = elapsed
if ( this.count > 0 ) {
gl.clear( gl.COLORBUFFERBIT )
gl.drawArrays( gl.POINTS, 0, this.count )
}
this.onUpdate( delta )
requestAnimationFrame( this.update )
}
}
const pointSize = 3
const waves = new ShaderProgram( document.querySelector( '.waves' ), {
texture: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAb1BMVEUAAAD///8v0wLRAAAAJHRSTlMAC/goGvDhmwcExrVjWzrm29TRqqSKenRXVklANSIUE8mRkGpv+HOfAAABCElEQVQ4y4VT13LDMAwLrUHteO+R9f/fWMfO6dLaPeKVEECRxOULWsEGpS9nULDwia2Y+ALqUNbAWeg775zv+sA4/FFRMxt8U2FZFCVWjR/YrH4/H9sarclSKdPMWKzb8VsEeHB3m0shkhVCyNzeXeAQ9Xl4opEieX2QCGnwGbj6GMyjw9t1K0fK9YZunPXeAGsfJtYjwzxaBnozGGorYz0ypK2HzQSYx1y8DgSRo2ewOiyh2QWOEk1Y9OrQV0a8TiBM1a8eMHWYnRMy7CZ4t1CmyRkhSUvP3gRXyHOCLBxNoC3IJv//ZrJ/kxxUHPUB+6jJZZHrpg6GOjnqaOmzp4NDR48OLxn/H27SRQ08S0ZJAAAAAElFTkSuQmCC',
uniforms: {
size: { type: 'float', value: pointSize },
field: { type: 'vec3', value: [ 0, 0, 0 ] },
speed: { type: 'float', value: 5 },
},
vertex: `
#define M_PI 3.1415926535897932384626433832795
precision highp float;
attribute vec4 a_position;
attribute vec4 a_color;
uniform float u_time;
uniform float u_size;
uniform float u_speed;
uniform vec3 u_field;
uniform mat4 u_projection;
varying vec4 v_color;
void main() {
vec3 pos = a_position.xyz;
pos.y += (
cos(pos.x / u_field.x * M_PI * 8.0 + u_time * u_speed) +
sin(pos.z / u_field.z * M_PI * 8.0 + u_time * u_speed)
) * u_field.y;
gl_Position = u_projection * vec4( pos.xyz, a_position.w );
gl_PointSize = ( u_size / gl_Position.w ) * 100.0;
v_color = a_color;
}`,
fragment: `
precision highp float;
uniform sampler2D u_texture;
varying vec4 v_color;
void main() {
gl_FragColor = v_color * texture2D(u_texture, gl_PointCoord);
}`,
onResize( w, h, dpi ) {
const position = [], color = []
const width = 400 * ( w / h )
const depth = 400
const height = 3
const distance = 5
for ( let x = 0; x < width; x += distance ) {
for ( let z = 0; z < depth; z+= distance ) {
position.push( - width / 2 + x, -30, -depth / 2 + z )
color.push( 0, 1 - ( x / width ) * 1, 0.5 + x / width * 0.5, z / depth )
}
}
this.uniforms.field = [ width, height, depth ]
this.buffers.position = position
this.buffers.color = color
this.uniforms.size = ( h / 400) * pointSize * dpi
},
} )
</script>
</body>
</html>
相关文章:

原生JS+canvas实现炫酷背景
原生JScanvas实现炫酷背景 可以在需要的背景页使用 <!doctype html> <html> <head> <meta charset"utf-8"> <title>HTML5 Canvas矩阵粒子波浪背景动画特效</title> <style> html,body { height:100%; } body { …...

Linux学习之NAS服务器搭建
NAS是Network Attached Storage的缩写,也就是网络附属存储。可以使用自己已经不怎么使用的笔记本搭建一台NAS服务器。 fdisk -l可以看一下各个磁盘的状态。 可以看到有sda、sdb、sdc和sdd等四块硬盘。 lvs、vgs和pvs结合起来看,sdb和sdc没有被使用。 …...

分享码云上8个宝藏又有价值的开源图片编辑器
如果你需要高效地处理图片,那么这8款实用工具是可以尝试的! 它们能够进行一键抠图、放大、拼接、转矢量图、图标自动生成以及等操作,让你的工作效率飞升! 在Gitee这个最有价值的开源项目计划是Gitee综合评定出的优秀开源项目的展示…...

TCP Header都有啥?
分析&回答 源端口号(Source Port) :16位,标识主机上发起传送的应用程序; 目的端口(Destonation Port) :16位,标识主机上传送要到达的应用程序。 源端,目…...

无涯教程-Android - AutoCompleteTextView函数
AutoCompleteTextView是一个类似于EditText的视图,只是它在用户键入时自动显示补充数据。 AutoCompleteTextView - 属性 以下是与AutoCompleteTextView控件相关的重要属性。您可以查看Android官方文档以获取属性的完整列表以及可以在运行时更改这些属性的相关方法。…...
【Docker】 07-安装ElasticSearch、Kibana
安装ElasticSearch 1、拉取镜像 docker pull elasticsearch:6.4.2 2、运行 docker run -p 9200:9200 -p 9300:9300 --name es -d elasticsearch:6.4.2 启动会报错,按照下面流程修改 3、在宿主机中,修改配置sysctl.conf vim /etc/sysctl.conf 加入如下配…...

【数据结构篇】线性表1 --- 顺序表、链表 (万字详解!!)
前言:这篇博客我们重点讲 线性表中的顺序表、链表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列... 线性表在逻辑上是…...

C语言每日一练--Day(17)
本专栏为c语言练习专栏,适合刚刚学完c语言的初学者。本专栏每天会不定时更新,通过每天练习,进一步对c语言的重难点知识进行更深入的学习。 今日练习题关键字:数对 截取字符串 💓博主csdn个人主页:小小unico…...

8月琐碎但值得的事情
8月份结束了,最近心态比较好,慢点就慢点,没有那么着急了,可能是因为着急也没啥办法, 8月是比较开心的一个月,可能是做的事情更有盼头了,可能是看了喜欢的书,可能是我变瘦了ÿ…...

苹果Mac系统如何优化流畅的运行?提高运行速度
Mac系统的稳定性和流畅性一直备受大家称赞,这也是大多数人选择Mac的原因,尽管如此,我们仍不时地对Mac进行优化、调整,以使其比以前更快、更流畅地运行。以下是小编分享给各位的Mac优化方法,记得保存哦~ 一、释放被过度…...

Python 类和对象
类的创建 Python语言中,使用class关键字来创建类,其创建方式如下: class ClassName(bases):# class documentation string 类文档字符串,对类进行解释说明class_suiteclass是关键字,bases是要继承的父类,…...

VC++使用Microsoft Speech SDK进行文字TTS朗读
Microsoft Speech SDK下载地址 https://www.microsoft.com/en-us/download/details.aspx?id10121 需要msttss22L.exe、SpeechSDK51.exe、SpeechSDK51LangPack.exe三个,下载后全部安装 使用VS2005建立一个win32控制台项目 朗读"hello word"、中文“你好”…...

FFmpeg4.3.1+h264在windows下编译与VS2017项目集成
前言 在Android音视频开发中,网上知识点过于零碎,自学起来难度非常大,不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》,结合我自己的工作学习经历,我准备写一个音视频系列blog。本文是音视频系…...

mapboxGL3新特性介绍
概述 8月7日,mapboxGL发布了3版本的更新,本文带大家一起来看看mapboxGL3有哪些新的特性。 新特新 如上图所示,是mapboxGL官网关于新版的介绍,大致翻译如下: 增强了web渲染的质量、便捷程度以及开发人员体验ÿ…...

类ChatGPT大模型LLaMA及其微调模型
1.LLaMA LLaMA的模型架构:RMSNorm/SwiGLU/RoPE/Transfor mer/1-1.4T tokens 1.1对transformer子层的输入归一化 对每个transformer子层的输入使用RMSNorm进行归一化,计算如下: 1.2使用SwiGLU替换ReLU 【Relu激活函数】Relu(x) max(0,x) 。 【GLU激…...
50个简洁的提示提高代码可读性和效率(0-10)
这篇文章整理了50个简洁的提示,可以提高您的代码可读性和效率。这些提示来自个人项目、彻底的代码审查和与资深开发人员的启发性讨论。 无论您是新手还是经验丰富的开发人员,这篇文章都应该能够帮助您学到一些东西。 这个列表包括常见的Python模式、核…...

Linux —— 进程信号
一,信号概念 信号是进程之间事件异步通知的一种方式,属于软中断; 系统定义的信号 每个信号都有一个编号和一个宏定义名称(可在signal.h查看);编号34以上的为实时信号; [wz192 Desktop]$ kill -…...
Android笔记 自定义控件时drawText字符串宽度的3种计算方式
String str "hello"; canvas.drawText(str, x, y, mPaint);//1. 粗略计算文字宽度: float width mPaint.measureText(str);//2. 计算文字的矩形,可以得到宽高: Rect rect new Rect(); mPaint.getTextBounds(str, 0, str.length(…...

ChatRWKV 学习笔记和使用指南
0x0. 前言 Receptance Weighted Key Value(RWKV)是pengbo提出的一个新的语言模型架构,它使用了线性的注意力机制,把Transformer的高效并行训练与RNN的高效推理相结合,使得模型在训练期间可以并行,并在推理…...

Particle Life粒子生命演化的MATLAB模拟
Particle Life粒子生命演化的MATLAB模拟 0 前言1 基本原理1.1 力影响-吸引排斥行为1.2 距离rmax影响 2 多种粒子相互作用2.1 双种粒子作用2.1 多种粒子作用 3 代码 惯例声明:本人没有相关的工程应用经验,只是纯粹对相关算法感兴趣才写此博客。所以如果有…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...