ACM忙完啦,最近想给自己的xienaoban.github.io做个博客网页,刚好没学过html之类的东西,就从零开始一边学一边做。之前一直对html5做的各种特效很感兴趣,就从网页背景开始写起吧。
曾经看到过别人的博客的背景有种特效,就是背景随机散布若干点不停移动,当两个点足够近的时候就会产生一条线连接两点,就像星座的连线一样;当点离鼠标很近的时候还会被吸引。于是自己也来实现个。
感觉js真的是个很神奇的语言,没有类,就把函数“假装”为类,并作为类似构造函数而存在,然后用prototype添加成员函数。看上去还真像那么回事,哈哈。
//==========================================
// File: background.js
// Title: 几何星空背景
// Auther: XieNaoban
// Version: v0.9
//==========================================
//创建背景画布
var cvs = document.createElement("canvas");
cvs.width = window.innerWidth;
cvs.height = window.innerHeight;
cvs.style.cssText="\
position:fixed;\
top:0px;\
left:0px;\
z-index:-1;\
opacity:1.0;\
";
document.body.appendChild(cvs);
var ctx = cvs.getContext("2d");
var startTime = new Date().getTime();
//随机数函数
function randomInt(min,max) {
return Math.floor((max-min+1)*Math.random()+min);
}
function randomFloat(min,max) {
return (max-min)*Math.random()+min;
}
//构造点类
function Point() {
this.x = randomFloat(0,cvs.width);
this.y = randomFloat(0,cvs.height);
var maxD = 0.08, minD = 0.01;
this.speed = randomFloat(minD,maxD);
this.angle = randomFloat(0,2*Math.PI);
this.r = 1;
var grey = (this.r*30+200);
this.color = "rgba("+grey+","+grey+","+grey+",1)";
}
Point.prototype.move = function(dif) {
var dx = Math.sin(this.angle)*this.speed;
var dy = Math.cos(this.angle)*this.speed;
this.x += dx*dif;
if (this.x<0) {
this.x=0;
this.angle=2*Math.PI-this.angle;
}
else if (this.x>cvs.width){
this.x=cvs.width;
this.angle=2*Math.PI-this.angle;
}
this.y += dy*dif;
if (this.y<0) {
this.y=0;
this.angle=Math.PI-this.angle;
}
else if (this.y>cvs.height){
this.y=cvs.height;
this.angle=Math.PI-this.angle;
}
}
Point.prototype.draw = function() {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x,this.y,this.r,0,Math.PI*2);
ctx.closePath();
ctx.fill();
}
//绘制每一帧
var points = [];
function initPoints(num) {
for (var i = 0; i<num; ++i) {
points.push(new Point());
}
}
var p0 = new Point();
var degree=5.0;
document.onmousemove = function(ev) {
p0.x = ev.clientX;
p0.y = ev.clientY;
}
document.onmousedown = function(ev) {
degree = 10.0;
p0.x = ev.clientX;
p0.y = ev.clientY;
}
document.onmouseup = function(ev) {
degree = 5.0;
p0.x = ev.clientX;
p0.y = ev.clientY;
}
function drawLine(p1,p2,d) {
var dis = (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);
var t = 100/dis;
t = Math.min(t,0.4);
if(t<0.01) return false;
t = Math.min(1,t*d);
ctx.strokeStyle = "rgba(255,250,250,"+ t +")";
ctx.beginPath();
ctx.lineWidth=1;
ctx.moveTo(p1.x,p1.y);
ctx.lineTo(p2.x,p2.y);
ctx.closePath();
ctx.stroke();
return true;
}
function drawFrame() {
cvs.width = window.innerWidth;
cvs.height = window.innerHeight;
ctx.fillStyle = "rgba(0,43,54,1)";
ctx.fillRect(0,0,cvs.width,cvs.height);
var endTime = new Date().getTime();
var dif = endTime-startTime;
startTime = endTime;
for(var i = 0; i<points.length; ++i) {
for(var j = i+1; j<points.length; ++j) {
var p1 = points[i], p2 = points[j];
drawLine(p1,p2,3.0);
}
}
for(var i = 0; i<points.length; ++i) {
var p = points[i];
drawLine(p0,p,degree);
p.draw();
p.move(dif);
}
window.requestAnimationFrame(drawFrame);
}
initPoints(70);
drawFrame();
没有去实现那个鼠标跟随,因为感觉我以后应该会自己想一个原创的更好玩的特效,这个就练练手好了。不过实现效果还是蛮炫酷的很满意啊,就是当最大化窗口就会显得稀疏,窗口小了看着太密。
还有个问题就是cpu占用太高了。。。每一帧要渲染70个点、判断 70 ∗ 70 = 490 70*70=490 70∗70=490条线(以及70个sin、cos可以优化为dx、dy)。。。果然以后必须得换个背景。。。(或者减少点并放大整个图形倒也不错)。
还有个八(te)哥(xing),就是切换到别的页面后不是本页面会停止渲染嘛,过半分钟再切回来会发现所有点挤在四个角落。原因是我是按照时间差来定下一帧每个点的位置的,当下一帧与当前帧的时间差太大的时候,每个点的移动距离都跑到屏幕外面了,于是被强制拉回屏幕的边缘。(感觉我这个实现方法会导致动画在低配电脑上看着很卡)。