272 rivejä
11 KiB
JavaScript
272 rivejä
11 KiB
JavaScript
/*
|
|
* 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。
|
|
*
|
|
* 指定登记&发行网站: https://www.zhiqim.com/ 欢迎加盟知启蒙,[编程有你,知启蒙一路随行]。
|
|
*
|
|
* 本文采用《知启蒙登记发行许可证》,除非符合许可证,否则不可使用该文件!
|
|
* 1、您可以免费使用、修改、合并、出版发行和分发,再授权软件、软件副本及衍生软件;
|
|
* 2、您用于商业用途时,必须在原作者指定的登记网站,按原作者要求进行登记;
|
|
* 3、您在使用、修改、合并、出版发行和分发时,必须包含版权声明、许可声明,及保留原作者的著作权、商标和专利等知识产权;
|
|
* 4、您在互联网、移动互联网等大众网络下发行和分发再授权软件、软件副本及衍生软件时,必须在原作者指定的发行网站进行发行和分发;
|
|
* 5、您可以在以下链接获取一个完整的许可证副本。
|
|
*
|
|
* 许可证链接:http://zhiqim.org/licenses/zhiqim_register_publish_license.htm
|
|
*
|
|
* 除非法律需要或书面同意,软件由原始码方式提供,无任何明示或暗示的保证和条件。详见完整许可证的权限和限制。
|
|
*/
|
|
|
|
+(function(Z)
|
|
{
|
|
//BEGIN
|
|
|
|
/**
|
|
* WebGL+three.js 3D动画,当前有波浪和光线球两种
|
|
*/
|
|
Z.WebGLThree = Z.Class.newInstance();
|
|
Z.WebGLThree.prototype =
|
|
{
|
|
defaults:
|
|
{
|
|
//常量
|
|
SEPARATION: 125,
|
|
AMOUNTX: 35,
|
|
AMOUNTY: 35,
|
|
|
|
//传入参数
|
|
threePath: null,
|
|
target: null,
|
|
|
|
//内部对象
|
|
camera: null,
|
|
scene: null,
|
|
renderer: null,
|
|
particles_ware: [],
|
|
particles_globe: [],
|
|
|
|
//运行时
|
|
count: 0,
|
|
mouseX: 0,
|
|
mouseY: 0,
|
|
windowHalfX: window.innerWidth / 2,
|
|
windowHalfY: window.innerHeight / 2,
|
|
rotation_speed: .002,
|
|
timeout: null
|
|
},
|
|
|
|
execute: function()
|
|
{
|
|
if (Z.B.mobile || Z.B.msieVer <= 9)
|
|
{//移动端和IE9以下不支持
|
|
return;
|
|
}
|
|
|
|
if (this.threePath == null || this.target == null)
|
|
{//两个参数必须
|
|
return;
|
|
}
|
|
|
|
if (Z.Types.isString(this.target))
|
|
this.target = Z("#"+this.target);
|
|
else if (Z.Types.isElement(this.target))
|
|
this.target = Z(this.target);
|
|
else
|
|
return;
|
|
|
|
//先加载three.js,再初始化init
|
|
Z.loads(this.threePath, Z.bind(this.initWebGL, this));
|
|
},
|
|
|
|
initWebGL: function()
|
|
{
|
|
var animationType = Math.floor(2 * Math.random());
|
|
if (animationType == 0)
|
|
{//波浪
|
|
this.initWave();
|
|
this.animateWave();
|
|
}
|
|
else
|
|
{//光球
|
|
this.initGlobe();
|
|
this.animateGlobe();
|
|
}
|
|
|
|
//增加事件处理
|
|
Z(document).mousemove(this.onDocumentMouseMove, this)
|
|
.on("touchstart", this.onDocumentTouchStart, this)
|
|
.on("touchmove", this.onDocumentTouchMove, this);
|
|
Z(window).resize(this.onWindowResize, this);
|
|
},
|
|
|
|
/******************************************************************************************/
|
|
//光球
|
|
/******************************************************************************************/
|
|
initGlobe: function initGlobe()
|
|
{
|
|
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1e4),
|
|
this.camera.position.z = 500,
|
|
this.scene = new THREE.Scene;
|
|
|
|
for (var t = 2 * Math.PI, i = function (e) {e.beginPath(), e.arc(0, 0, 25, 0, t, true), e.fill()}, t = 2 * Math.PI, n = 0; 500 > n; n++)
|
|
{
|
|
var o = new THREE.SpriteCanvasMaterial({color: 16777215,
|
|
transparent: true,
|
|
program: function (e) {e.beginPath(), e.arc(0, 0, .5, 0, t, true), e.fill()}});
|
|
var particle = new THREE.Sprite(o);
|
|
particle.position.x = 2 * Math.random() - 1;
|
|
particle.position.y = 2 * Math.random() - 1;
|
|
particle.position.z = 2 * Math.random() - 1;
|
|
particle.position.normalize();
|
|
particle.position.multiplyScalar(10 * Math.random() + 450);
|
|
particle.scale.multiplyScalar(4 + 2 * Math.random());
|
|
particle.material.opacity = .1;
|
|
this.scene.add(particle);
|
|
this.particles_globe.push(particle);
|
|
}
|
|
for (var n = 0; 500 > n; n++)
|
|
{
|
|
var s = new THREE.Geometry;
|
|
var r = new THREE.Vector3(2 * Math.random() - 1, 2 * Math.random() - 1, 2 * Math.random() - 1);
|
|
r.normalize();
|
|
r.multiplyScalar(450);
|
|
s.vertices.push(r);
|
|
|
|
var a = r.clone();
|
|
a.multiplyScalar(.3 * Math.random() + 1), s.vertices.push(a);
|
|
var l = new THREE.Line(s, new THREE.LineBasicMaterial({color: 16777215, opacity: .3}));
|
|
this.scene.add(l)
|
|
}
|
|
this.renderer = new THREE.CanvasRenderer({alpha: true});
|
|
this.renderer.setClearColor(0, 0);
|
|
this.renderer.setSize(window.innerWidth, window.innerHeight);
|
|
this.target.append(this.renderer.domElement)
|
|
},
|
|
|
|
animateGlobe: function()
|
|
{
|
|
requestAnimationFrame(Z.bind(this.animateGlobe, this));
|
|
this.renderGlobe();
|
|
},
|
|
|
|
renderGlobe: function()
|
|
{
|
|
var e = Z("body:hover"), t = this.camera.position.x, i = this.camera.position.y, n = this.camera.position.z;
|
|
if (e.length != 0 && this.timeout != null)
|
|
{
|
|
this.camera.position.x += .05 * (this.mouseX - this.camera.position.x);
|
|
}
|
|
else
|
|
{
|
|
this.camera.position.x = t * Math.cos(this.rotation_speed) - n * Math.sin(this.rotation_speed);
|
|
this.camera.position.z = n * Math.cos(this.rotation_speed) + t * Math.sin(this.rotation_speed);
|
|
}
|
|
|
|
this.camera.position.y += .05 * (-this.mouseY + 200 - this.camera.position.y);
|
|
this.camera.lookAt(this.scene.position);
|
|
|
|
Z(document).mousemove(function () {
|
|
this.timeout !== null && clearTimeout(this.timeout), this.timeout = setTimeout(function () {this.timeout = null}, 600)
|
|
});
|
|
|
|
for (var o = 0; o < this.particles_globe.length; o++)
|
|
{
|
|
var particle = this.particles_globe[o++];
|
|
temp = 50 * Math.sin(.3 * (o + this.count)) + .5 * Math.sin(.5 * (o + this.count));
|
|
opacity = Math.abs(temp) / 50 + .1;
|
|
opacity > 1 && (opacity = 1);
|
|
particle.material.opacity = opacity;
|
|
}
|
|
|
|
this.renderer.render(this.scene, this.camera);
|
|
this.count += .1;
|
|
},
|
|
|
|
/******************************************************************************************/
|
|
//波浪
|
|
/******************************************************************************************/
|
|
initWave: function()
|
|
{
|
|
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1e4);
|
|
this.camera.position.z = 1e3;
|
|
this.camera.position.y = 100;
|
|
this.camera.position.y = 1e3;
|
|
|
|
this.scene = new THREE.Scene;
|
|
for (var t = 2 * Math.PI, i = 0, n = 0; this.AMOUNTX > n; n++)for (var o = 0; this.AMOUNTY > o; o++)
|
|
{
|
|
var s = new THREE.SpriteCanvasMaterial({color: 16777215,
|
|
transparent: true,
|
|
program: function (e) {e.beginPath(), e.arc(0, 0, .5, 0, t, true), e.fill()}});
|
|
|
|
var particle = this.particles_ware[i++] = new THREE.Sprite(s);
|
|
particle.position.x = n * this.SEPARATION - this.AMOUNTX * this.SEPARATION / 2;
|
|
particle.position.z = o * this.SEPARATION - this.AMOUNTY * this.SEPARATION / 2;
|
|
this.scene.add(particle), particle.material.opacity = .4;
|
|
}
|
|
|
|
this.renderer = new THREE.CanvasRenderer({alpha: true});
|
|
this.renderer.setClearColor(0, 0);
|
|
this.renderer.setSize(window.innerWidth, window.innerHeight);
|
|
this.target.append(this.renderer.domElement);
|
|
},
|
|
|
|
animateWave: function()
|
|
{
|
|
requestAnimationFrame(Z.bind(this.animateWave, this));
|
|
this.renderWave();
|
|
},
|
|
|
|
renderWave: function()
|
|
{
|
|
this.camera.position.x += .01 * (this.mouseX - this.camera.position.x),
|
|
this.camera.position.y += .005 * (this.mouseY - this.camera.position.y),
|
|
this.camera.lookAt(this.scene.position);
|
|
|
|
for (var e = 0, t = 0; this.AMOUNTX > t; t++)
|
|
{
|
|
for (var i = 0; this.AMOUNTY > i; i++)
|
|
{
|
|
var particle = this.particles_ware[e++];
|
|
particle.position.y = 50 * Math.sin(.3 * (t + this.count)) + 50 * Math.sin(.5 * (i + this.count));
|
|
particle.scale.x = particle.scale.y = 4 * (Math.sin(.3 * (t + this.count)) + 1) + 4 * (Math.sin(.5 * (i + this.count)) + 1);
|
|
opacity = Math.abs(particle.position.y) / 100;
|
|
opacity < .5 && (opacity = .5);
|
|
opacity > 1 && (opacity = 1);
|
|
particle.material.opacity = opacity;
|
|
}
|
|
}
|
|
|
|
this.renderer.render(this.scene, this.camera);
|
|
this.count += .03
|
|
},
|
|
|
|
/******************************************************************************************/
|
|
//事件处理
|
|
/******************************************************************************************/
|
|
|
|
onWindowResize: function()
|
|
{//缩放
|
|
this.windowHalfX = window.innerWidth / 2,
|
|
this.windowHalfY = window.innerHeight / 2,
|
|
this.camera.aspect = window.innerWidth / window.innerHeight,
|
|
this.camera.updateProjectionMatrix(),
|
|
this.renderer.setSize(window.innerWidth, window.innerHeight);
|
|
},
|
|
|
|
onDocumentMouseMove: function(e)
|
|
{//鼠标移动
|
|
this.mouseX = e.clientX - this.windowHalfX, this.mouseY = e.clientY + 150;
|
|
},
|
|
|
|
onDocumentTouchStart: function(e)
|
|
{//iOS触摸开始
|
|
1 === e.touches.length && (e.preventDefault(), this.mouseX = e.touches[0].pageX - this.windowHalfX, this.mouseY = -e.touches[0].pageY);
|
|
},
|
|
|
|
onDocumentTouchMove: function(e)
|
|
{//iOS触摸移动
|
|
1 === e.touches.length && (e.preventDefault(), this.mouseX = e.touches[0].pageX - this.windowHalfX, this.mouseY = -e.touches[0].pageY);
|
|
}
|
|
};
|
|
|
|
//END
|
|
})(zhiqim); |