<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r78/three.min.js"></script>
<!-- This pen isn't a fan of small view heights, check it out in fullpage view for optimal viewing -->
<div class="x-mark">
<div class="container">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
<div class="intro-container">
<h2 class="fancy-text">Christopher Lis</h2>
<h1>ONE WITH AN EVERLASTING DESIRE <br> FOR THE UNKNOWN & UNTOLD</h1>
<div class="button shift-camera-button">
<div class="border">
<div class="left-plane"></div>
<div class="right-plane"></div>
</div>
<div class="text">To The Stars</div>
</div>
</div>
<div class="sky-container">
<div class="text-right sky-container__left">
<h2 class="portfolio">
PORTFOLIO
</h2>
<h2 class="resurrection">
resurrection
</h2>
</div>
<div class="text-left sky-container__right">
<h2 class="08">
08
</h2>
<h2 class="thirty-one">
31
</h2>
<h2 class="2016">
2016
</h2>
</div>
</div>
</body>
</html>
"use strict";
/* globals THREE, $, TweenLite, Power3, TimelineMax */
var camera = undefined,
scene = undefined,
renderer = undefined;
var plane = undefined;
var raycaster = new THREE.Raycaster();
var normalizedMouse = {
x: 0,
y: -180
};
// let lightBlue = {
// r: 34,
// g: 183,
// b: 236
// };
var darkBlue = {
r: 0,
g: 52,
b: 74
};
var baseColorRGB = darkBlue;
var baseColor = "rgb(" + baseColorRGB.r + "," + baseColorRGB.g + "," + baseColorRGB.b + ")";
var nearStars = undefined,
farStars = undefined,
farthestStars = undefined;
function init() {
scene = new THREE.Scene();
// 远景相机(PerspectiveCamera) 第一个参数 相机视锥体垂直视角,从下到上的观察角度。但好像跟观察事物大小也有关
// 最后两个是构成可视范围的近远值 超过这两个范围的 都不会渲染出来 也就是不会显示
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight,0.1, 1000);
renderer = new THREE.WebGLRenderer(); // Canvas渲染器(CanvasRenderer)
// Scene initialization
camera.position.z = 50; //镜头Z轴高度
renderer.setClearColor("#121212", 1.0); //这个颜色看不出有啥用
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio); //屏幕分辨率
document.body.appendChild(renderer.domElement);
// Lights //灯光 因为是立体模型 所有上下两个灯光 显得透亮些
var topLight = new THREE.DirectionalLight(0xffffff, 1);
topLight.position.set(0, 1, 1).normalize();
scene.add(topLight);
var bottomLight = new THREE.DirectionalLight(0xffffff, 0.4);
bottomLight.position.set(1, -1, 1).normalize();
scene.add(bottomLight);
//天空的灯光 真是没看出有什么用 - 还是有用的 从不同角度照亮 只不过亮度值比较低不容易发现
var skyLightRight = new THREE.DirectionalLight(0x666666, 0.2);
skyLightRight.position.set(-1, -1, 0.2).normalize();
scene.add(skyLightRight);
var skyLightCenter = new THREE.DirectionalLight(0x666666, 0.2);
skyLightCenter.position.set(-0, -1, 0.2).normalize();
scene.add(skyLightCenter);
var skyLightLeft = new THREE.DirectionalLight(0x666666, 0.2);
skyLightLeft.position.set(1, -1, 0.2).normalize();
scene.add(skyLightLeft);
// Mesh creation
var geometry = new THREE.PlaneGeometry(400, 400, 70, 70); //平面模型(PlaneGeometry) 后面两个70 是平面创造多少个截面
//Phong网孔材料(MeshPhongMaterial) - 用于表面有光泽的材料 比如金属
var darkBlueMaterial = new THREE.MeshPhongMaterial({
color: 0xffffff,
shading: THREE.FlatShading, //定义着色类型 THREE.SmoothShading 带有过渡的着色接近真实 THREE.FlatShading 平面着色,也称之为“恒量着色” 也就是颜色没有过渡
side: THREE.DoubleSide, //这些常量用来定义几何体哪些面需要应用材料。注意3D空间一个表面有内外两边,默认情况下是THREE.FrontSide(前外面)。
vertexColors: THREE.FaceColors //就是上色 不过点和面区别不大 //THREE.FaceColors:顶点使用面的颜色 //THREE.VertexColors:顶点使用顶点的颜色。 //THREE.NoColors:顶点没有颜色
});
//vertices 是这个几何模型里所有点的数组 上面最后两个参数就是分段 这样交叉就会有点
geometry.vertices.forEach(function(vertice) {
//console.log(geometry.vertices);
vertice.x += (Math.random() - 0.5) * 4; //移动这个点的坐标
vertice.y += (Math.random() - 0.5) * 4;
vertice.z += (Math.random() - 0.5) * 4;
vertice.dx = Math.random() - 0.5; //后面这几个都是自定义的
vertice.dy = Math.random() - 0.5;
vertice.randomDelay = Math.random() * 5; //随机延迟 好像上面的摆动的延迟
});
//console.log( geometry.vertices.length);
//geometry.faces 三角面数组
for (var i = 0; i < geometry.faces.length; i++) {
geometry.faces[i].color.setStyle(baseColor); //给面上色 这个如果没有就是白色
geometry.faces[i].baseColor = baseColorRGB; //这个没有就彻底黑了//这个可能是自定义的吧 //看下面函数 这个真是自定义的
}
plane = new THREE.Mesh(geometry, darkBlueMaterial); //网孔(Mesh 几何模型(Geometry). //材料(Material) (optional).
scene.add(plane);
// Create stars //创建星星 函数在下面
farthestStars = createStars(1200, 420, "#0952BD"); //第一个是个数,第二个是y坐标,第三个是颜色
farStars = createStars(1200, 370, "#A5BFF0");
nearStars = createStars(1200, 290, "#118CD6");
scene.add(farthestStars);
scene.add(farStars);
scene.add(nearStars);
//这是自转效果,会使得星星有点眨眼睛的效果
farStars.rotation.x = 0.25;
nearStars.rotation.x = 0.25;
//自己玩的盒子
// var geometry = new THREE.BoxGeometry( 100, 100, 100 );
// //这么写移动有点笨,上面这么写是为了做成波浪效果
// // geometry.vertices.forEach(function(vertice) {
// // vertice.z += 100;
// // vertice.y += 200;
// // });
// geometry.translate (0,200,100); //对应的是mesh.position
// geometry.rotateY(20); //根据文档这个函数操作的就是对象mesh的 .rotation
// var material = new THREE.MeshPhongMaterial( { color: 0xffff00 } );
// var mesh = new THREE.Mesh( geometry, material );
// //mesh.rotation.y = 0.6; //效果一直这两个
// // mesh.rotateY(6);
// mesh.position.y = 50; //喔 他现在改变的量 是基于上面模型的位置坐标系
// scene.add( mesh );
// Uncomment for testing second camera position
// camera.rotation.x = Math.PI / 2;
// camera.position.y = -0;
// camera.position.z = 20;
// plane.scale.x = 2;
}
function createStars(amount, yDistance,color="0x000000") {
//这... 可以定义默认值啊 为啥多此一举 不懂
//var color = arguments.length <= 2 || arguments[2] === undefined ? "0x000000" : arguments[2]; //默认颜色 js不能参数定义么
var opacity = Math.random();
var starGeometry = new THREE.Geometry(); //几何模型
var starMaterial = new THREE.PointsMaterial({ //点材料
color: color,
opacity: opacity
});
for (var i = 0; i < amount; i++) {
var vertex = new THREE.Vector3();
vertex.z = (Math.random() - 0.5) * 1500;
vertex.y = yDistance;
vertex.x = (Math.random() - 0.5) * 2000;
// 固定y值这样就是个扁平的面 调整z可以发现 数值小 离远了 就能看出是在一条直线上 离近了则出现高低 这是因为摄像机有角度
// vertex.z = (Math.random() - 0.5) * 1500;
// vertex.y = 20;
// vertex.x = (Math.random() - 0.5) * 1500;
starGeometry.vertices.push(vertex);
}
return new THREE.Points(starGeometry, starMaterial);
}
var timer = 0;
function render() {
//这是html自带函数 不断刷新动画 详细介绍 https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame
requestAnimationFrame(render);
//console.log(Math.sin(timer + 5) / 40 * (Math.random() - 0.5));// 这是正负值都有的 //Math.random() 在0~1之间的值
timer += 0.01;
var vertices = plane.geometry.vertices;
//改变点的位置 使面不停移动 做出动态效果 Math.sin(x) x 的正玄值。返回值在 -1.0 到 1.0 之间;
for (var i = 0; i < vertices.length; i++) {
// Ease back to original vertice position while still maintaining sine wave
// 这应该是个公式 是个正弦波动 就是平面动态波纹的感觉 就是Ease那个动态感觉 下面也有 只不过好像没法来对点作用
vertices[i].x -= Math.sin(timer + vertices[i].randomDelay) / 40 * vertices[i].dx; //向左移动
vertices[i].y += Math.sin(timer + vertices[i].randomDelay) / 40 * vertices[i].dy; //像上移动
// ((vertices[i].x - vertices[i].originalPosition.x) * 0.1) +
}
// Determine where ray is being projected from camera view 确定从相机视图中投射光线的位置 (不懂这个有啥用)
raycaster.setFromCamera(normalizedMouse, camera); //光线投射器(Raycaster) arg1 鼠标的二维坐标 arg2 射线起点处的相机,即把射线起点设置在该相机位置处。
// Send objects being intersected into a variable
var intersects = raycaster.intersectObjects([plane]);
//这段好像就是 鼠标跟随改变每个面的颜色
if (intersects.length > 0) {
(function() {
var faceBaseColor = intersects[0].face.baseColor;
//被鼠标改变颜色后恢复原本颜色
plane.geometry.faces.forEach(function(face) {
face.color.r *= 255;
face.color.g *= 255;
face.color.b *= 255;
face.color.r += (faceBaseColor.r - face.color.r) * 0.01;
face.color.g += (faceBaseColor.g - face.color.g) * 0.01;
face.color.b += (faceBaseColor.b - face.color.b) * 0.01;
var rInt = Math.floor(face.color.r);
var gInt = Math.floor(face.color.g);
var bInt = Math.floor(face.color.b);
var newBasecol = "rgb(" + rInt + "," + gInt + "," + bInt + ")";
face.color.setStyle(newBasecol);
});
//更新颜色
plane.geometry.colorsNeedUpdate = true;
intersects[0].face.color.setStyle("#006ea0"); //最初那块颜色//这应该鼠标所指那个面吧
plane.geometry.colorsNeedUpdate = true;
})();
}
plane.geometry.verticesNeedUpdate = true; //更新点
plane.geometry.elementsNeedUpdate = true; //更新面
farthestStars.rotation.y -= 0.00001; //哦 是向左转 不过因为是面 但视角关系 看远方是向右走
farStars.rotation.y -= 0.00005;
nearStars.rotation.y -= 0.00011;
renderer.render(scene, camera);
}
init();
window.addEventListener("resize", function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
//监听鼠标位置
window.addEventListener("mousemove", function(event) {
// Normalize mouse coordinates
normalizedMouse.x = event.clientX / window.innerWidth * 2 - 1;
normalizedMouse.y = -(event.clientY / window.innerHeight) * 2 + 1; //y是负的 可能是因为坐标系不同吧
});
var introContainer = $('.intro-container');
var skyContainer = $('.sky-container');
var xMark = $('.x-mark');
$('.shift-camera-button').click(function() {
var introTimeline = new TimelineMax();
introTimeline.add([TweenLite.fromTo(introContainer, 0.5, {
opacity: 1 //透明度 转动镜头后把原本的层隐藏掉 否则都会显示
}, {
opacity: 0,
ease: Power3.easeIn
}), TweenLite.to(camera.rotation, 3, { //to()的参数 1:对象,2:动画完成时间,3:参数(这是前面对象的参数) //转动镜头
x: Math.PI / 2,
ease: Power3.easeInOut
}), TweenLite.to(camera.position, 2.5, {
z: 20,
ease: Power3.easeInOut
}), TweenLite.to(camera.position, 3, {
y: 120,
ease: Power3.easeInOut
}), TweenLite.to(plane.scale, 3, {
x: 2,
ease: Power3.easeInOut
})]);
introTimeline.add([TweenLite.to(xMark, 0.5, {
opacity: 1,
ease: Power3.easeInOut
}), TweenLite.to(skyContainer, 2, {
opacity: 1,
ease: Power3.easeInOut
})]);
});
//更上面一样了
$('.x-mark').click(function() {
var outroTimeline = new TimelineMax();
outroTimeline.add([TweenLite.to(xMark, 0.5, {
opacity: 0,
ease: Power3.easeInOut
}), TweenLite.to(skyContainer, 0.5, {
opacity: 0,
ease: Power3.easeInOut
}), TweenLite.to(camera.rotation, 3, {
x: 0,
ease: Power3.easeInOut
}), TweenLite.to(camera.position, 3, {
z: 50,
ease: Power3.easeInOut
}), TweenLite.to(camera.position, 2.5, {
y: 0,
ease: Power3.easeInOut
}), TweenLite.to(plane.scale, 3, {
x: 1,
ease: Power3.easeInOut
})]);
outroTimeline.add([TweenLite.to(introContainer, 0.5, {
opacity: 1,
ease: Power3.easeIn
})]);
});
render();
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |