Open joyjoe opened 7 years ago
;(function(global, factory){ "use strict"; if(typeof module === "object" && typeof module.exports === "object"){ // Node.js module.exports = global.document?factory(global, true):function(w){ if(!w.document){ throw new Error("require a window with a document"); } return factory(w); } }else{ factory(global); } })(typeof window !== "undefined"?window:this, function(window, noGlobal){ "use strict"; var config = { star_r: 3,//star半径 star_alpha: 10, //5,//star透明度 initPopulation: 150,//star总个数 moveDistance: 0.25,//star移动距离 dot_r: 5,//dot半径 dot_speeds: 0.5,//dot速度 dot_alpha: 0.5,//dot透明度 dot_aReduction: 0.01,//dot消失透明度条件 dotsMinDistance: 5,//dot之间最短距离 dotsMaxDistance: 50,//dot之间最长距离 linkCount: 5 };
var stars = [],
dots = [],
canvas = null,
ctx = null,
WIDTH = document.documentElement.clientWidth,
HEIGHT = document.documentElement.clientHeight,
mouseMoving = false,
mouseMoveChecker,
mouseX,
mouseY;
function StarGlitter(container, obj){
function init(){
var _node = null;
if(typeof(container) === "string"){
if(container[0]==="."){
_node = document.getElementsByClassName(container.substr(1))[0];
}else if(container[0]==="#"){
_node = document.getElementById(container.substr(1));
}
}else if(container instanceof HTMLElement){
_node = container;
}
canvas = _node;
canvas.setAttribute("width", WIDTH);
canvas.setAttribute("height", HEIGHT);
ctx = canvas.getContext("2d");
// config
if(obj instanceof Object){
for(var item in obj){
config[item] = obj[item];
}
}
ctx.strokeStyle = "white";
ctx.shadowColor = "white";
for(var i = 0; i < config.initPopulation; i++){
stars[i] = new Star(i, Math.floor(Math.random() * WIDTH), Math.floor(Math.random() * HEIGHT), true);
}
}
function animate(){
ctx.clearRect(0,0,WIDTH,HEIGHT);
for(var i in stars){
stars[i].move();
}
for(var i in dots){
dots[i].move();
}
renderDraw();
requestAnimationFrame(animate);
}
document.onmousemove = function(e){
mouseMoving = true;
mouseX = e.clientX;
mouseY = e.clientY;
clearInterval(mouseMoveChecker);
mouseMoveChecker = setInterval(function(){
mouseMoving = false;
}, 20);
}
init();
animate();
};
// 绘制star
function Star(id, x, y, useCache){
this.init(id, x, y, useCache);
}
Star.prototype = {
constructor: Star,
init: function(id, x, y, useCache){
this.id = id;
this.x = x;
this.y = y;
this.useCache = useCache;
this.cacheCanvas = document.createElement("canvas");
this.cacheCtx = this.cacheCanvas.getContext("2d");
this.r = Math.floor(Math.random() * config.star_r) + 1;
this.cacheCtx.width = this.r * 6;
this.cacheCtx.height = this.r * 6;
var alpha = (Math.floor(Math.random() * 10) + 1) / config.star_alpha;
this.color = "rgba(255,255,255,"+ alpha +")";
if(this.useCache){
this.cache();
}else{
this.draw();
}
},
_render: function(ctx, x, y, r, start, end, flag, color){
ctx.save();
ctx.fillStyle = color || this.color;
ctx.shadowColor = "white";
ctx.shadowBlur = r * 2;
ctx.beginPath();
ctx.arc(x, y, r, start, end, flag);
ctx.closePath();
ctx.fill();
ctx.restore();
},
draw: function(){
if(this.useCache){
ctx.drawImage(this.cacheCanvas, this.x - this.r, this.y - this.r);
}else{
this._render(ctx, this.x, this.y, this.r, 0, Math.PI * 2, false);
}
},
cache: function(){
this._render(this.cacheCtx, this.r * 3, this.r * 3, this.r, 0, Math.PI * 2, false);
},
move: function(){
this.y -= config.moveDistance;
if(this.y <= -10){
this.y += (HEIGHT + 10);
}
this.draw();
},
die: function(){
stars[this.id] = null;
delete stars[this.id];
}
}
function Dot(id, x, y, useCache){
this.init(id, x, y, useCache);
}
Dot.prototype = {
constructor: Dot,
init: function(id, x, y, useCache){
this.id = id;
this.x = x;
this.y = y;
this.r = Math.floor(Math.random() * config.dot_r) + 1;
this.speed = config.dot_speeds;
this.a = config.dot_alpha;
this.aReduction = config.dot_aReduction;
this.useCache = useCache;
this.dotCanvas = document.createElement("canvas");
this.dotCtx = this.dotCanvas.getContext("2d");
this.dotCtx.width = this.r * 6;
this.dotCtx.height = this.r * 6;
this.color = "rgba(255,255,255,"+ this.a +")";
this.dir = Math.floor(Math.random() * 140) + 200;
this.linkCount = config.linkCount;
if(useCache){
this.cache();
}else{
this.draw();
}
},
_render: function(ctx, x, y, r, start, end, flag, color){
ctx.save();
ctx.fillStyle = color || this.color;
ctx.shadowColor = "white";
ctx.shadowBlur = r * 2;
ctx.beginPath();
ctx.arc(x, y, r, start, end, flag);
ctx.closePath();
ctx.fill();
ctx.restore();
},
draw: function(){
if(!this.useCache){
this._render(ctx, this.x, this.y, this.r, 0, Math.PI *2 , false);
}else{
ctx.drawImage(this.dotCanvas, this.x - this.r * 3, this.y - this.r * 3);
}
},
cache: function(){
this._render(this.dotCtx, this.r * 3, this.r * 3, this.r, 0, Math.PI *2 , false);
},
link: function(){
if(this.id == 0){
return;
}
// 可以考虑其他连线策略
ctx.beginPath();
ctx.strokeStyle = this.linkColor;
for(var i = 0; i <= this.linkCount; i++){
var previousDot = getPreviousDot(this.id, i + 1);
if(previousDot){
if(i == 0){
ctx.moveTo(previousDot.x, previousDot.y);
ctx.lineTo(this.x, this.y);
}else{
ctx.lineTo(previousDot.x, previousDot.y);
}
}else{
break;
}
}
ctx.stroke();
ctx.closePath();
},
move: function(){
this.a -=this.aReduction;
if(this.a <= 0){
this.die();
return;
}
this.color = "rgba(255,255,255,"+ this.a +")";
this.linkColor = "rgba(255,255,255,"+ this.a/4 +")";
this.x = this.x + Math.cos(Math.PI/180*this.dir) * this.speed;
this.y = this.y + Math.cos(Math.PI/180*this.dir) * this.speed;
this.draw();
this.link();
},
die: function(){
dots[this.id] = null;
delete dots[this.id];
}
}
function renderDraw(){
if(dots.length == 0){
dots[0] = new Dot(0, mouseX, mouseY, true);
dots[0].draw();
return;
}
var previousDot = getPreviousDot(dots.length, 1);
var prevX = previousDot.x;
var prevY = previousDot.y;
var diffX = Math.abs(prevX - mouseX);
var diffY = Math.abs(prevY - mouseY);
if(diffX < config.dotsMinDistance || diffY < config.dotsMinDistance){
return;
}
// 下一个点的位置可以考虑加入鼠标移动方向的因素
var xVariation = Math.random() > 0.5?-1:1;
xVariation = xVariation * Math.floor(Math.random() * config.dotsMaxDistance) + 1;
var yVariation = Math.random() > 0.5?-1:1;
yVariation = yVariation * Math.floor(Math.random() * config.dotsMaxDistance) + 1;
dots[dots.length] = new Dot(dots.length, mouseX+xVariation, mouseY+yVariation, true);
dots[dots.length - 1].draw();
dots[dots.length - 1].link();
}
function getPreviousDot(id, stepback){
if(id == 0 || id - stepback < 0){
return false;
}
if(typeof dots[id - stepback] !== "undefined"){
return dots[id - stepback];
}else{
return false;
}
}
if(!noGlobal){
window.StarGlitter = StarGlitter;
}
return StarGlitter;
});
先膜拜一下妹子
提几点建议
下面把我个人优化后的代码贴出来,有错误欢迎指正。