Je kunt niet meer dan 25 onderwerpen selecteren
Onderwerpen moeten beginnen met een letter of nummer, kunnen streepjes bevatten ('-') en kunnen maximaal 35 tekens lang zijn.
339 regels
11 KiB
339 regels
11 KiB
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta name="renderer" content="webkit"/>
|
|
<meta name="force-rendering" content="webkit"/>
|
|
<meta charset="UTF-8">
|
|
<title>Title</title>
|
|
<style type="text/css">
|
|
html, body {
|
|
margin: 0;
|
|
height: 100%;
|
|
background-size: cover;
|
|
background-position: center center;
|
|
overflow: hidden;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body onload="draw();" style="background-image: url(https://jllsly.com/wallpapers/snow-night-wallpapers-high-quality-resolution-Is-Cool-Wallpapers-1.jpg);">
|
|
</body>
|
|
<script src="https://johnson2heng.github.io/three.js-demo/lib/three.js"></script>
|
|
<script src="https://johnson2heng.github.io/three.js-demo/lib/js/controls/OrbitControls.js"></script>
|
|
<script src="https://johnson2heng.github.io/three.js-demo/lib/js/libs/stats.min.js"></script>
|
|
<script src="https://johnson2heng.github.io/three.js-demo/lib/js/libs/dat.gui.min.js"></script>
|
|
<script src="https://cdn.bootcss.com/lodash.js/4.17.11/lodash.min.js"></script>
|
|
<script src="//cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
|
|
<script src="https://cdn.bootcss.com/gsap/latest/TweenMax.min.js"></script>
|
|
<script>
|
|
|
|
//https://www.overdriveonline.com/wp-content/uploads/sites/8/2013/01/Truck-at-night-in-snow.jpg
|
|
//https://ateachinglifedotcom.files.wordpress.com/2016/12/snow-at-night.jpg
|
|
//https://d2v9y0dukr6mq2.cloudfront.net/video/thumbnail/H0MA-uKSipsekm5s/magical-winter-night-in-the-snow-covered-pine-forest-realistic-3d-animation_bcgk90me1g_thumbnail-full01.png
|
|
//https://i.pinimg.com/originals/18/03/c9/1803c9683d2a6acb5f827114015a51c8.jpg
|
|
//https://travelingorion.files.wordpress.com/2017/02/img_6666.jpg
|
|
//https://jllsly.com/wallpapers/snow-night-wallpaper-desktop-Is-Cool-Wallpapers-1.jpg
|
|
//https://juegosrev.com/wp-content/uploads/2017/06/Winter-Night-Wallpapers-Gallery-88-Plus-PIC-WPW504471.jpg
|
|
//https://jllsly.com/wallpapers/snow-night-wallpapers-high-quality-resolution-Is-Cool-Wallpapers-1.jpg
|
|
setInterval(function(){
|
|
if (location.hash.length > 2) {
|
|
document.body.style.backgroundImage = "url("+ location.hash.substr(1) + ")";
|
|
}
|
|
}, 1000)
|
|
|
|
var renderer, camera;
|
|
var swidth,sheight, swidth_2;
|
|
|
|
var rotateRatio = 0.04;
|
|
|
|
var wind = {x:0, z:0, y:0, ratio:0.45};
|
|
|
|
let windChangeStep = function(key){
|
|
TweenMax.to(
|
|
wind,
|
|
_.random(1.6, 2.5, true),
|
|
{
|
|
[key]:_.random(-1, 1, true) * wind.ratio,
|
|
ease: Power2.easeInOut,
|
|
onComplete:function(){
|
|
windChangeStep(key)
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
windChangeStep("x");
|
|
windChangeStep("z");
|
|
windChangeStep("y");
|
|
var getVelocity = function(){
|
|
return {
|
|
y:_.random(-0.2, -0.05, true) * 1.4,
|
|
x:_.random(-0.1, 0.2, true) * 0.01,
|
|
z:_.random(-0.1, 0.2, true) * 0.01,
|
|
angle:_.random(-Math.PI/2, Math.PI/2, true)
|
|
}
|
|
}
|
|
|
|
|
|
function clacSize(){
|
|
swidth = window.innerWidth * 0.05;
|
|
sheight = window.innerHeight * 0.05;
|
|
swidth_2 = swidth * swidth;
|
|
}
|
|
|
|
|
|
$(window).on("resize", e=>{
|
|
_.throttle(e=>{
|
|
clacSize();
|
|
}, 300)
|
|
});
|
|
clacSize();
|
|
|
|
$(document).on("mousemove", e=>{
|
|
let {screenX, screenY} = e;
|
|
// wind.x = (screenX - innerWidth * 0.5)/innerWidth/2 * 1.2;
|
|
// wind.z = (screenY - innerHeight * 0.5)/innerHeight/2 * 1.2;
|
|
});
|
|
|
|
|
|
function initRender() {
|
|
renderer = new THREE.WebGLRenderer({antialias: true, alpha:true});
|
|
// renderer.setClearColor(new THREE.Color(0x222222)); //设置背景颜色
|
|
renderer.setClearColor(0x000000, 0.2); //设置背景颜色
|
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
|
document.body.appendChild(renderer.domElement);
|
|
}
|
|
|
|
|
|
function initCamera() {
|
|
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 12, swidth * 2);
|
|
camera.position.set(0, 0, swidth * 0.75);
|
|
camera.lookAt(new THREE.Vector3(0, 30, 0));
|
|
}
|
|
|
|
|
|
function initScene() {
|
|
scene = new THREE.Scene();
|
|
}
|
|
|
|
var light;
|
|
|
|
function initLight() {
|
|
scene.add(new THREE.AmbientLight(0x404040));
|
|
light = new THREE.DirectionalLight(0xffffff);
|
|
light.position.set(1, 1, 1);
|
|
scene.add(light);
|
|
}
|
|
|
|
|
|
function initModel() {
|
|
|
|
//轴辅助 (每一个轴的长度)
|
|
var object = new THREE.AxesHelper(500);
|
|
// scene.add(object);
|
|
}
|
|
|
|
//初始化性能插件
|
|
var stats;
|
|
|
|
function initStats() {
|
|
stats = new Stats();
|
|
document.body.appendChild(stats.dom);
|
|
}
|
|
|
|
//用户交互插件 鼠标左键按住旋转,右键按住平移,滚轮缩放
|
|
var controls;
|
|
|
|
function initControls() {
|
|
|
|
controls = new THREE.OrbitControls(camera, renderer.domElement);
|
|
// controls = new THREE.TrackballControls(camera, renderer.domElement);
|
|
|
|
// 如果使用animate方法时,将此函数删除
|
|
//controls.addEventListener( 'change', render );
|
|
// 使动画循环使用时阻尼或自转 意思是否有惯性
|
|
controls.enableDamping = true;
|
|
//动态阻尼系数 就是鼠标拖拽旋转灵敏度
|
|
//controls.dampingFactor = 0.25;
|
|
//是否可以缩放
|
|
controls.enableZoom = true;
|
|
//是否自动旋转
|
|
controls.autoRotate = false;
|
|
//设置相机距离原点的最远距离
|
|
controls.minDistance = 20;
|
|
//设置相机距离原点的最远距离
|
|
controls.maxDistance = 10000;
|
|
//是否开启右键拖拽
|
|
controls.enablePan = true;
|
|
}
|
|
|
|
//生成gui设置配置项
|
|
var gui;
|
|
|
|
var cloud;
|
|
|
|
function initGui() {
|
|
//声明一个保存需求修改的相关数据的对象
|
|
gui = {
|
|
"size": 0.9,
|
|
"transparent": true,
|
|
"opacity": 1,
|
|
"vertexColors": true,
|
|
"color": 0xffffff,
|
|
"sizeAttenuation": true,
|
|
"rotateSystem": false,
|
|
redraw: function () {
|
|
if (cloud) {
|
|
scene.remove(cloud);
|
|
}
|
|
createParticles(gui.size, gui.transparent, gui.opacity, gui.vertexColors, gui.sizeAttenuation, gui.color);
|
|
//设置是否自动旋转
|
|
controls.autoRotate = gui.rotateSystem;
|
|
}
|
|
};
|
|
// var datGui = new dat.GUI();
|
|
// //将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值)gui.add(controls, 'size', 0, 10).onChange(controls.redraw);
|
|
// datGui.add(gui, 'size', 0.1, 10).onChange(gui.redraw);
|
|
// datGui.add(gui, 'transparent').onChange(gui.redraw);
|
|
// datGui.add(gui, 'opacity', 0, 1).onChange(gui.redraw);
|
|
// datGui.add(gui, 'vertexColors').onChange(gui.redraw);
|
|
// datGui.addColor(gui, 'color').onChange(gui.redraw);
|
|
// datGui.add(gui, 'sizeAttenuation').onChange(gui.redraw);
|
|
// datGui.add(gui, 'rotateSystem').onChange(gui.redraw);
|
|
|
|
gui.redraw();
|
|
}
|
|
|
|
//生成粒子的方法
|
|
function createParticles(size, transparent, opacity, vertexColors, sizeAttenuation, color) {
|
|
var texture = new THREE.TextureLoader().load("/static/img/snow.png");
|
|
//存放粒子数据的网格
|
|
var geom = new THREE.Geometry();
|
|
|
|
//样式化粒子的THREE.PointCloudMaterial材质
|
|
var material = new THREE.PointsMaterial({
|
|
size,
|
|
transparent,
|
|
opacity,
|
|
vertexColors,
|
|
sizeAttenuation,
|
|
color,
|
|
depthTest: false, //设置解决透明度有问题的情况
|
|
map: texture,
|
|
});
|
|
|
|
for (var i = 0; i < 16000; i++) {
|
|
//添加顶点的坐标
|
|
var particle = new THREE.Vector3(0,0,0);
|
|
|
|
resetParticle(particle);
|
|
|
|
var v = getVelocity();
|
|
|
|
particle.velocityY = v.y;
|
|
particle.velocityX = v.x;
|
|
particle.velocityZ = v.z;
|
|
particle.ang = v.angle;
|
|
|
|
geom.vertices.push(particle);
|
|
var color = new THREE.Color(0xffffff);
|
|
//.setHSL ( h, s, l ) h — 色调值在0.0和1.0之间 s — 饱和值在0.0和1.0之间 l — 亮度值在0.0和1.0之间。 使用HSL设置颜色。
|
|
//随机当前每个粒子的亮度
|
|
//color.setHSL(color.getHSL().h, color.getHSL().s, Math.random() * color.getHSL().l);
|
|
geom.colors.push(color);
|
|
}
|
|
|
|
//生成模型,添加到场景当中
|
|
cloud = new THREE.Points(geom, material);
|
|
cloud.verticesNeedUpdate = true;
|
|
|
|
scene.add(cloud);
|
|
}
|
|
|
|
|
|
function resetParticle(particle){
|
|
particle.y = _.random(-sheight, sheight, true);
|
|
particle.x = _.random(-swidth, swidth , true);
|
|
particle.z = _.random(-swidth, swidth , true);
|
|
}
|
|
|
|
function render() {
|
|
//产生雨滴动画效果
|
|
var vertices = cloud.geometry.vertices;
|
|
|
|
vertices.forEach(function (v, i) {
|
|
v.ang+=0.05;
|
|
|
|
let a = Math.atan(v.z/v.x);
|
|
if(v.x<0){
|
|
a = a + Math.PI;
|
|
}
|
|
let r = Math.pow(v.x*v.x + v.z*v.z, 0.5);
|
|
a = a + rotateRatio * Math.pow(1 - r/swidth, 3);
|
|
|
|
//漩涡
|
|
v.x = Math.cos(a) * r;
|
|
v.z = Math.sin(a) * r;
|
|
|
|
//速度
|
|
v.y = v.y + v.velocityY;
|
|
v.x = v.x + v.velocityX + Math.cos(v.ang) * 0.09 ;
|
|
v.z = v.z + v.velocityZ + Math.sin(v.ang) * 0.09 ;
|
|
|
|
//风
|
|
v.y = v.y + wind.y * 0.5;
|
|
v.x = v.x + wind.x;
|
|
v.z = v.z + wind.z;
|
|
|
|
if (v.y <= -sheight){
|
|
v.y = sheight;
|
|
}else if (v.x < -swidth) {
|
|
v.x = swidth
|
|
}else if (v.x > swidth) {
|
|
v.x = -swidth;
|
|
}else if (v.z < -swidth) {
|
|
v.z = swidth
|
|
}else if (v.z > swidth) {
|
|
v.z = -swidth;
|
|
}
|
|
});
|
|
|
|
//设置实时更新网格的顶点信息
|
|
cloud.geometry.verticesNeedUpdate = true;
|
|
|
|
renderer.render(scene, camera);
|
|
}
|
|
|
|
//窗口变动触发的函数
|
|
function onWindowResize() {
|
|
camera.aspect = window.innerWidth / window.innerHeight;
|
|
camera.updateProjectionMatrix();
|
|
|
|
render();
|
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
|
|
|
}
|
|
|
|
function animate() {
|
|
//更新控制器
|
|
controls.update();
|
|
render();
|
|
|
|
//更新性能插件
|
|
stats.update();
|
|
requestAnimationFrame(animate);
|
|
}
|
|
|
|
function draw() {
|
|
initRender();
|
|
initScene();
|
|
initCamera();
|
|
initLight();
|
|
initModel();
|
|
initControls();
|
|
initStats();
|
|
initGui();
|
|
animate();
|
|
window.onresize = onWindowResize;
|
|
}
|
|
</script>
|
|
</html>
|