3D霓虹灯效果:
image.png
<style>
body {
background-color: #080c11;
margin: 0;
padding: 0;
overflow: hidden;
}
canvas {
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}
</style>
<canvas id='canv'></canvas>
<script>
window.requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var $;
var rad = 0;
var num = 700;
var size = 15;
var len = 0;
var arr = [];
var midX;
var midY;
var msX = 0;
var msY = 0;
var w;
var h;
window.onload = function() {
var c = document.getElementById("canv");
w = c.width = window.innerWidth;
h = c.height = window.innerHeight;
$ = c.getContext("2d");
midX = c.width / 2;
midY = c.height / 2;
rad = c.height;
for (var i = 0; i < num; i++) {
arr[i] = new Part();
}
$.fillStyle = "hsla(217, 35%, 15%, 1)";
$.fillRect(0, 0, c.width, c.height);
len = h / 2;
// window.addEventListener("mousemove", msmv, false);
// window.addEventListener("touchmove", tcmv, false);
window.addEventListener('load', resize);
window.addEventListener('resize', resize, false);
window.requestAnimFrame(setInterval(go, 45));
};
function resize() {
c.width = w = window.innerWidth;
c.height = h = window.innerHeight;
c.style.position = 'absolute';
c.style.left = (window.innerWidth - w) *
.01 + 'px';
c.style.top = (window.innerHeight - h) *
.01 + 'px';
}
function msmv(e) {
var rect = e.target.getBoundingClientRect();
msX = e.clientX - rect.left;
msY = e.clientY - rect.top;
}
function tcmv(e) {
var rect = e.target.getBoundingClientRect();
msX = e.touches[0].pageX - rect.left;
msY = e.touches[0].pageY - rect.top;
}
function disp(p1, p2) {
return (p2.z - p1.z);
}
function go() {
$.globalCompositeOperation = 'source-over';
$.fillStyle = "hsla(217, 35%, 5%, .8)";
$.fillRect(0, 0, w, h);
$.globalCompositeOperation = 'lighter';
arr.sort(disp);
for (var i = 0; i < num; i++) {
arr[i].upd();
arr[i].draw();
}
}
var rndCol = function() {
var r = Math.floor(Math.random() * 180);
var g = Math.floor(Math.random() * 60);
var b = Math.floor(Math.random() * 100);
return "rgb(" + r + "," + g + "," + b + ")";
}
var Part = function() {
this.x = 0;
this.y = 0;
this.z = 0;
this.vx = 0;
this.vy = 0;
this.dx = Math.random() * Math.PI;
this.dy = 0;
this.phi = Math.random() * Math.PI * 2;
this.t = Math.random() * Math.PI;
if (Math.random() < 0.5) {
this.col = rndCol();
this.dir = 1;
} else {
this.col = rndCol();
this.dir = -1;
}
};
Part.prototype.draw = function() {
var s = this.scale();
var x = w / 2 + this.x * s;
var y = h / 2 + this.y * s;
$.fillStyle = this.col;
if (this.z > -rad / 2) {
$.beginPath();
$.arc(x, y, Math.ceil(size * s), 0, Math.PI * 2, false);
$.fill();
}
};
Part.prototype.scale = function() {
return (len / (len + this.z));
};
Part.prototype.upd = function() {
var m = (w / 2 - msX) / w / 10;
this.phi += (this.dy + m) * this.dir;
this.t = this.dx;
this.x = rad * Math.sin(this.t) * Math.cos(this.phi);
this.y = rad * Math.cos(this.t);
this.z = rad * Math.sin(this.t) * Math.sin(this.phi) +
rad / 2 * (h / 1.2 - msY) / h * 4;
}
</script>
小球在3D范围内运动:
image.png
<style>
canvas {
position: absolute;
top: 0;
left: 0;
}
</style>
<canvas id="c"></canvas>
<script>
/*Javascript代码片段*/
var w = c.width = window.innerWidth,
h = c.height = window.innerHeight,
ctx = c.getContext('2d'),
balls = [],
tick = 0,
fl = 260, // focal length
bd = 300, // boundaries
vp = { // vanis point
x: w / 2,
y: h / 2
},
pts = [ // bounding box wireframe
dimensionize(-bd,-bd,0),
dimensionize(-bd,bd,0),
dimensionize(bd,bd,0),
dimensionize(bd,-bd,0),
dimensionize(bd,-bd,bd*2),
dimensionize(bd,bd,bd*2),
dimensionize(-bd,bd,bd*2),
dimensionize(-bd,-bd,bd*2)
]
for (var i = 0; i < 50; ++i)
balls.push({
x: Math.random() * bd*2 - bd,
y: Math.random() * bd*2 - bd,
z: Math.random() * bd*2,
vx: 5 * ( Math.random() - .5 ),
vy: 5 * ( Math.random() - .5 ),
vz: 5 * ( Math.random() - .5 ),
s: Math.random() * 2 + 20
});
function anim(){
window.requestAnimationFrame( anim );
++tick;
ctx.fillStyle = 'black';
ctx.fillRect( 0, 0, w, h );
ctx.strokeStyle = 'white';
for( var i = 0; i < 5; i+=4 ){
ctx.beginPath();
ctx.moveTo( pts[i].x, pts[i].y );
ctx.lineTo( pts[i+1].x, pts[i+1].y );
ctx.lineTo( pts[i+2].x, pts[i+2].y );
ctx.lineTo( pts[i+3].x, pts[i+3].y );
ctx.closePath();
ctx.stroke();
}
for( var i = 0; i < 4; ++i ){
ctx.beginPath();
ctx.moveTo( pts[i].x, pts[i].y );
ctx.lineTo( pts[7-i].x, pts[7-i].y );
ctx.stroke();
}
balls.map( function( ball ){
ball.x += ball.vx;
ball.y += ball.vy; //+=.1; uncomment for gravity ;)
ball.z += ball.vz;
if( ball.x - ball.s < -bd ){
ball.vx *= -1;
ball.x = -bd + ball.s;
} else if( ball.x + ball.s > bd ){
ball.vx *= -1;
ball.x = bd - ball.s;
}
if( ball.y - ball.s < -bd ){
ball.vy *= -1;
ball.y = -bd + ball.s;
} else if( ball.y + ball.s > bd ){
ball.vy *= -1;
ball.y = bd - ball.s;
}
if( ball.z - ball.s < 0 ){
ball.vz *= -1;
ball.z = ball.s;
} else if( ball.z + ball.s > bd*2 ){
ball.vz *= -1;
ball.z = bd*2 - ball.s;
}
});
balls.sort( function( a, b ){ return b.z - a.z } );
balls.map( function( ball ){
var p = dimensionize( ball.x, ball.y, ball.z );
p.s *= ball.s;
ctx.fillStyle = 'hsl(hue,80%,50%)'.replace( 'hue', ( ball.x+ball.y+ball.z ) / 4 + tick );
ctx.beginPath();
ctx.arc( p.x, p.y, p.s, 0, Math.PI * 2 );
ctx.fill();
})
}
anim();
function dimensionize( x, y, z ){
var scale = fl / ( fl + z );
return {
x: vp.x + x * scale,
y: vp.y + y * scale,
s: scale
};
}
</script>