酷炫一款动态背景+鼠标点击效果(HTML +js canvas)

简介: 前言之前用于装饰个人的Hexo博客背景和点击事件,于是动手弄弄顺便学习学习,现在分享出来给有需要的人。废话不多说 ,分享一款酷炫的页面动态背景 效果见( https://fivecc.cn )

前言

之前用于装饰个人的Hexo博客背景和点击事件,于是动手弄弄顺便学习学习,现在分享出来给有需要的人。

废话不多说 ,分享一款酷炫的页面动态背景 效果见(https://fivecc.cn)

动态背景

1. 效果图:

网络异常,图片无法展示
|

实例效果:

网络异常,图片无法展示
|

2. 源码:

<!--背景css--><style>* {
margin: 0;
padding: 0;
}
#canvasBg {
position: fixed;
background: #ccc;
overflow: auto;
z-index: -1;
}
</style><!--背景html--><canvasid="canvasBg"></canvas><!--背景js--><script>window.requestAnimationFrame= (function () {
return (
window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function (callback) {
window.setTimeout(callback, 1000/2);
    }
  );
})();
varmyCanvas=document.getElementById("canvasBg");
varctx=myCanvas.getContext("2d"); //getContext 设置画笔varnum;
varw, h;
varduixiang= [];
varmove= {};
functionwidthheight() {
w=myCanvas.width=window.innerWidth;
h=myCanvas.height=window.innerHeight;
num=Math.floor(w*h*0.00028); //点的数量。根据屏幕大小确定for (vari=0; i<num; i++) {
duixiang[i] = {
x: Math.random() *w,
y: Math.random() *h,
cX: Math.random() *0.6-0.3,
cY: Math.random() *0.6-0.3,
R: Math.floor(Math.random() *5) +2,
//CC:Math.floor(Math.random()*3)+2,r: Math.floor(Math.random() *254),
g: Math.floor(Math.random() *254),
b: Math.floor(Math.random() *254),
    };
// console.log(duixiang[i])Cricle(
duixiang[i].x,
duixiang[i].y,
duixiang[i].R,
duixiang[i].r,
duixiang[i].g,
duixiang[i].b    );
//Cricle(duixiang[i].x,duixiang[i].y,duixiang[i].R,duixiang[i].CC);  }
}
widthheight(); //获取浏览器的等宽度等高functionCricle(x, y, R, r, g, b) {
ctx.save(); //保存路径if (Math.random() >0.991) {
ctx.globalAlpha=0.9;
  } //ctx.fillStyle = "#CCC";}//填充的背景颜色else {
ctx.globalAlpha=0.47;
  }
ctx.fillStyle="rgb("+r+","+g+","+b+")";
ctx.beginPath(); //开始绘画ctx.arc(x, y, R, Math.PI*2, 0); //绘画圆 x y 半径(大小) 角度  一个PI 是180 * 2 = 360    真假 0/1 true/falsectx.closePath(); //结束绘画ctx.fill(); //填充背景颜色ctx.restore(); //回复路径}
Cricle();
!(functiondraw() {
ctx.clearRect(0, 0, w, h); //先清除画布上的点for (vari=0; i<num; i++) {
duixiang[i].x+=duixiang[i].cX;
duixiang[i].y+=duixiang[i].cY;
if (duixiang[i].x>w||duixiang[i].x<0) {
duixiang[i].cX=-duixiang[i].cX;
    }
if (duixiang[i].y>h||duixiang[i].y<0) {
duixiang[i].cY=-duixiang[i].cY;
    }
Cricle(
duixiang[i].x,
duixiang[i].y,
duixiang[i].R,
duixiang[i].r,
duixiang[i].g,
duixiang[i].b    );
//勾股定理判断两点是否连线for (varj=i+1; j<num; j++) {
if (
        (duixiang[i].x-duixiang[j].x) * (duixiang[i].x-duixiang[j].x) +          (duixiang[i].y-duixiang[j].y) * (duixiang[i].y-duixiang[j].y) <=55*55      ) {
line(
duixiang[i].x,
duixiang[i].y,
duixiang[j].x,
duixiang[j].y,
0,
i,
j        );
      }
if (move.x) {
if (
          (duixiang[i].x-move.x) * (duixiang[i].x-move.x) +            (duixiang[i].y-move.y) * (duixiang[i].y-move.y) <=100*100        ) {
line(duixiang[i].x, duixiang[i].y, move.x, move.y, 1, i, 1);
        }
      }
    }
  }
window.requestAnimationFrame(draw);
})();
//绘制线条functionline(x1, y1, x2, y2, flag, i, j) {
if (flag) {
varcolor=ctx.createLinearGradient(x1, y1, x2, y2);
ctx.globalAlpha=0.5;
color.addColorStop(
0,
"rgb("+duixiang[i].r+","+duixiang[i].g+","+duixiang[i].b+")"    );
color.addColorStop(0.8, "#019ee5");
  } else {
varcolor=ctx.createLinearGradient(x1, y1, x2, y2);
ctx.globalAlpha=0.9;
color.addColorStop(
0,
"rgb("+duixiang[i].r+","+duixiang[i].g+","+duixiang[i].b+")"    );
color.addColorStop(
1,
"rgb("+duixiang[j].r+","+duixiang[j].g+","+duixiang[j].b+")"    );
  }
ctx.save();
ctx.strokeStyle=color;
ctx.lineWidth=0.5;
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
//ctx.restore();}
//document.onmousemove = function(e){//   move.x = e.clientX;//  move.y = e.clientY;//}//console.log(move)//去掉注释 ,可以与背景互动window.onresize=function () {
location.reload();
};
</script>

鼠标点击特效

1.鼠标点击效果

网络异常,图片无法展示
|

2.鼠标点击效果

<!--鼠标点击css--><style>#canvasEvent {
position: fixed;
pointer-events: none;
width: 100%;
height: 100%;
overflow: auto;
z-index: 999;
}
</style><!--鼠标点击html--><canvasid="canvasEvent"style="whdth: 100%;height: 100%"></canvas><!--鼠标点击html--><script>var_createClass= (function () {
functiondefineProperties(target, props) {
for (vari=0; i<props.length; i++) {
vardescriptor=props[i];
descriptor.enumerable=descriptor.enumerable||false;
descriptor.configurable=true;
if ("value"indescriptor) descriptor.writable=true;
Object.defineProperty(target, descriptor.key, descriptor);
    }
  }
returnfunction (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
returnConstructor;
  };
})();
function_classCallCheck(instance, Constructor) {
if (!(instanceinstanceofConstructor)) {
thrownewTypeError("Cannot call a class as a function");
  }
}
vargetRandom=functiongetRandom(min, max) {
returnMath.random() * (max-min) +min;
};
vargetRandomInt=functiongetRandomInt(min, max) {
returnMath.floor(Math.random() * (max-min)) +min;
};
vargetRandomColor=functiongetRandomColor() {
varcolors= [
"rgba(231, 76, 60, 1)", // 红"rgba(241, 196, 15, 1)", // 黄"rgba(46, 204, 113, 1)", // 绿"rgba(52, 152, 219, 1)", // 蓝"rgba(155, 89, 182, 1)", // 紫色  ];
returncolors[getRandomInt(0, colors.length)];
};
// Particle//粒子模块varParticle= (function () {
functionParticle(system, x, y) {
_classCallCheck(this, Particle);
this.system=system;
this.universe=this.system.world.universe;
this.x=x;
this.y=y;
this.color=getRandomColor();
this.life=1;
this.aging=getRandom(0.99, 0.999); // 0.99, 0.999 || 0.999, 0.9999this.r=getRandomInt(12, 16); //初始粒子半径范围this.speed=getRandom(18, 18.5); //粒子爆炸速度范围this.velocity= [
getRandom(-this.speed, this.speed),
getRandom(-this.speed, this.speed),
    ];
  }
_createClass(Particle, [
    {
key: "update",
value: functionupdate(dt) {
this.life*=this.aging;
if (
this.r<0.1||this.life===0||this.x+this.r<0||this.x-this.r>this.universe.width||this.y+this.r<0||this.y-this.r>this.universe.height        ) {
this.system.removeObject(this);
        }
this.r*=this.life;
this.x+=this.velocity[0];
this.y+=this.velocity[1];
      },
    },
    {
key: "render",
value: functionrender(ctx) {
// Main circle //亮圈模块ctx.fillStyle=this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r*1.2, 0, 2*Math.PI, false);
ctx.fill();
ctx.closePath();
varr=this.color.match(/([0-9]+)/g)[0];
varg=this.color.match(/([0-9]+)/g)[1];
varb=this.color.match(/([0-9]+)/g)[2];
// Gradient//梯度变化曲线varspread=1.5;
vargradient=ctx.createRadialGradient(
this.x,
this.y,
this.r,
this.x,
this.y,
this.r*spread        );
gradient.addColorStop(0, "rgba("+r+", "+g+", "+b+", 0.5)");
gradient.addColorStop(1, "rgba("+r+", "+g+", "+b+", 0)");
ctx.globalCompositeOperation="lighter";
ctx.fillStyle=gradient;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r*spread, 0, 2*Math.PI, false);
ctx.fill();
ctx.closePath();
ctx.globalCompositeOperation="source-over";
// Aberration//偏差varoffset=this.r*0.5;
varcolor="rgba("+g+", "+b+", "+r+", 0.5)";
ctx.globalCompositeOperation="lighter";
ctx.fillStyle=color;
ctx.beginPath();
ctx.arc(
this.x+offset,
this.y+offset,
this.r,
0,
2*Math.PI,
false        );
ctx.fill();
ctx.closePath();
ctx.globalCompositeOperation="source-over";
      },
    },
  ]);
returnParticle;
})();
// Crown //水波纹圈模块varCrown= (function () {
functionCrown(system, x, y) {
_classCallCheck(this, Crown);
this.system=system;
this.x=x;
this.y=y;
this.r=getRandomInt(5, 15); // 5, 20  水波纹圈半径范围this.mod=1.1;
this.life=0.5; //水波纹线this.aging=getRandom(0.83, 0.899);
this.speed=getRandom(8, 9);
this.color= {
r: getRandomInt(236, 242),
g: getRandomInt(70, 80),
b: getRandomInt(50, 70),
    };
this.angle1=Math.PI*getRandom(0, 2);
this.angle2=this.angle1+Math.PI*getRandom(0.3, 0.4); //水波纹圈完整度  }
_createClass(Crown, [
    {
key: "update",
value: functionupdate(dt) {
this.life*=this.aging;
if (this.life<=0.0001) this.system.removeObject(this);
this.r+=Math.abs(1-this.life) *this.speed;
this.x1=this.x+this.r*Math.cos(this.angle1);
this.y1=this.y+this.r*Math.sin(this.angle1);
this.angle3=this.angle1+ (this.angle2-this.angle1) /2;
this.x2=this.x+this.r*this.mod*Math.cos(this.angle3);
this.y2=this.y+this.r*this.mod*Math.sin(this.angle3);
      },
    },
    {
key: "render",
value: functionrender(ctx) {
vargradient=ctx.createRadialGradient(
this.x,
this.y,
this.r*0.9,
this.x,
this.y,
this.r        );
gradient.addColorStop(
0,
"rgba("+this.color.r+", "+this.color.g+", "+this.color.b+", "+this.life+")"        );
gradient.addColorStop(
1,
"rgba("+this.color.r+", "+this.color.g+", "+this.color.b+", "+this.life*0.5+")"        );
ctx.fillStyle=gradient;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, this.angle1, this.angle2, false);
ctx.quadraticCurveTo(this.x2, this.y2, this.x1, this.y1);
ctx.fill();
ctx.closePath();
      },
    },
  ]);
returnCrown;
})();
// Explosion //爆炸模块varExplosion= (function () {
functionExplosion(world, x, y) {
_classCallCheck(this, Explosion);
this.world=world;
this.x=x;
this.y=y;
this.objects= [];
varparticles=getRandomInt(10, 30); // 10, 30 //爆炸 粒子数量varcrowns=particles*getRandom(0.4, 0.5);
while (crowns-->0) {
this.addCrown();
    }
while (particles-->0) {
this.addParticle();
    }
  }
_createClass(Explosion, [
    {
key: "update",
value: functionupdate(dt) {
this.objects.forEach(function (obj) {
if (obj) obj.update(dt);
        });
if (this.objects.length<=0) {
this.world.clearExplosion(this);
        }
      },
    },
    {
key: "render",
value: functionrender(ctx) {
this.objects.forEach(function (obj) {
if (obj) obj.render(ctx);
        });
      },
    },
    {
key: "addCrown",
value: functionaddCrown() {
this.objects.push(newCrown(this, this.x, this.y));
      },
    },
    {
key: "addParticle",
value: functionaddParticle() {
this.objects.push(newParticle(this, this.x, this.y));
      },
    },
    {
key: "removeObject",
value: functionremoveObject(obj) {
varindex=this.objects.indexOf(obj);
if (index!==-1) {
this.objects.splice(index, 1);
        }
      },
    },
  ]);
returnExplosion;
})();
// WorldvarConfettiWorld= (function () {
functionConfettiWorld() {
_classCallCheck(this, ConfettiWorld);
  }
_createClass(ConfettiWorld, [
    {
key: "init",
value: functioninit() {
this.objects= [];
window.addEventListener("click", this.explode.bind(this));
// Initial explosion //初始爆炸varcounter=0;
while (counter-->0) {
this.explode({
clientX: window.event.clientX, //getRandomInt(10, this.universe.width) ,          //this.universe.width / 2,clientY: window.event.clientY, //getRandomInt(10, 50) //this.universe.height / 2          });
        }
      },
    },
    {
key: "update",
value: functionupdate(dt) {
this.objects.forEach(function (obj) {
if (obj) obj.update(dt);
        });
varamount=this.objects.reduce(function (sum, explosion) {
return (sum+=explosion.objects.length);
        }, 0);
      },
    },
    {
key: "render",
value: functionrender(ctx) {
this.objects.forEach(function (obj) {
if (obj) obj.render(ctx);
        });
      },
    },
    {
key: "explode",
value: functionexplode(event) {
varx=event.clientX;
vary=event.clientY;
this.objects.push(newExplosion(this, x, y));
      },
    },
    {
key: "clearExplosion",
value: functionclearExplosion(explosion) {
varindex=this.objects.indexOf(explosion);
if (index!==-1) {
this.objects.splice(index, 1);
        }
      },
    },
  ]);
returnConfettiWorld;
})();
// TimevarTime= (function () {
functionTime() {
_classCallCheck(this, Time);
this.now=0; // 当前粒子时间this.prev=0; // 上一粒子时间this.elapsed=0; //最后粒子时间this.delta=0; // 从上次更新开始的时间this.fps=60; // 期望fpsthis.step=1/60; // 步长  }
_createClass(Time, [
    {
key: "update",
value: functionupdate(time) {
this.now=time;
this.elapsed= (this.now-this.prev) /1000;
this.prev=this.now;
this.delta+=this.elapsed;
      },
    },
    {
key: "raf",
value: functionraf(func) {
window.requestAnimationFrame(func);
      },
    },
    {
key: "hasFrames",
value: functionhasFrames() {
returnthis.delta>=this.step;
      },
    },
    {
key: "processFrame",
value: functionprocessFrame() {
this.delta-=this.step;
      },
    },
  ]);
returnTime;
})();
// CanvasvarUniverse= (function () {
functionUniverse(element) {
_classCallCheck(this, Universe);
this.el=element;
this.ctx=this.el.getContext("2d");
this.pixelRatio=window.devicePixelRatio;
this.time=newTime();
this.worlds= {};
this.world=null; // current statethis.updateSize();
window.addEventListener("resize", this.updateSize.bind(this));
this.addWorld("confetti", ConfettiWorld);
this.setWorld("confetti");
this.start();
  }
_createClass(Universe, [
    {
key: "start",
value: functionstart() {
this.time.raf(this.tick.bind(this));
      },
    },
    {
key: "tick",
value: functiontick(time) {
this.time.update(time);
if (this.time.hasFrames()) {
this.update();
this.time.processFrame();
        }
this.render();
this.time.raf(this.tick.bind(this));
      },
    },
    {
key: "update",
value: functionupdate() {
this.world.update(this.time.step);
      },
    },
    {
key: "render",
value: functionrender() {
vargradient=this.ctx.createLinearGradient(
0,
0,
this.width,
this.height        );
this.ctx.clearRect(0, 0, this.width, this.height);
this.world.render(this.ctx);
      },
// Helpers 库    },
    {
key: "updateSize",
value: functionupdateSize() {
this.width=window.innerWidth;
this.height=window.innerHeight;
this.el.width=this.width*this.pixelRatio;
this.el.height=this.height*this.pixelRatio;
this.el.style.width=window.innerWidth+"px";
this.el.style.height=window.innerHeight+"px";
this.ctx.scale(this.pixelRatio, this.pixelRatio);
      },
    },
    {
key: "addWorld",
value: functionaddWorld(worldName, World) {
this.worlds[worldName] =newWorld();
this.worlds[worldName].universe=this;
this.worlds[worldName].init();
      },
    },
    {
key: "setWorld",
value: functionsetWorld(worldName) {
this.world=this.worlds[worldName];
      },
    },
  ]);
returnUniverse;
})();
// Mainconsole.clear();
varelement=document.querySelector("#canvasEvent");
window.Canvas=newUniverse(element);
</script>

喜欢就给我点一个大大的赞是👍 外加一个关注

目录
相关文章
|
14天前
|
移动开发 前端开发 JavaScript
【专栏:HTML与CSS实战项目篇】使用HTML5与CSS3制作一个动态表单验证页面
【4月更文挑战第30天】本文介绍了使用HTML5和CSS3创建动态表单验证页面的方法。首先,简述HTML5用于构建网页内容,CSS3用于描述样式。接着,分四步展示实现过程:1) 设计包含输入框和提示信息的表单结构;2) 使用CSS3创建样式,增强视觉效果;3) 使用JavaScript监听输入事件,动态验证表单并显示错误信息;4) 测试和调试确保跨平台兼容性。通过学习,开发者能掌握创建带验证功能的表单,提升用户体验。
|
14天前
|
编解码 前端开发 JavaScript
【专栏:HTML与CSS实战项目篇】打造一个动态新闻网站
【4月更文挑战第30天】构建动态新闻网站,运用HTML和CSS提升编程技能和网页设计理解。项目包括首页、新闻列表页和详情页,设计简洁易用,包含顶部导航、轮播图和新闻列表。页面布局注重吸引力和易用性,色彩搭配选用冷色调为主,辅以亮色点缀。字体选择清晰易读,布局保持整洁。交互效果如轮播图、导航栏高亮和响应式设计增强用户体验。本文提供基础新闻网站构建指南,为进一步功能扩展和优化打下基础。
|
15天前
|
JavaScript 前端开发
实现一个JavaScript动态日期功能
实现一个JavaScript动态日期功能
|
15天前
|
JavaScript 前端开发
JavaScript DOM 文档对象模型(获取、改变html元素)
JavaScript DOM 文档对象模型(获取、改变html元素)
|
15天前
|
JavaScript 前端开发
【专栏】`Function.prototype.apply` 在JavaScript中用于动态设定函数上下文(`this`)和参数列表
【4月更文挑战第29天】`Function.prototype.apply` 在JavaScript中用于动态设定函数上下文(`this`)和参数列表。它接受两个参数:上下文对象和参数数组。理解`apply`有助于深入JS运行机制。文章分三部分探讨其原理:基本概念和用法、工作原理详解、实际应用与注意事项。在应用中要注意性能、参数类型和兼容性问题。`apply`可用于动态改变上下文、传递参数数组,甚至模拟其他语言的调用方式。通过深入理解`apply`,能提升代码质量和效率。
|
15天前
|
前端开发 JavaScript
使用html+css+javaScript 完成计算器
使用html+css+javaScript 完成计算器
|
17天前
科技感十足的动态HTML源码
科技感十足的动态HTML源码,源码由HTML+CSS+JS组成,记事本打开源码文件可以进行内容文字之类的修改,双击html文件可以本地运行效果,也可以上传到服务器里面
20 0
科技感十足的动态HTML源码
|
19天前
|
JavaScript 前端开发 BI
原生html—摆脱ps、excel 在线绘制财务表格加水印(html绘制表格js加水印)
原生html—摆脱ps、excel 在线绘制财务表格加水印(html绘制表格js加水印)
20 1
|
22天前
|
移动开发 JavaScript HTML5
input | pattern | oninvalid | setCustomValidity | html5原生js表单校验
input | pattern | oninvalid | setCustomValidity | html5原生js表单校验
16 0
|
25天前
|
JavaScript
js的鼠标移入移出事件
js的鼠标移入移出事件