<div class="main">
<canvas id="bg"></canvas>
<p id="percent">0</p>
<p id="scroll">0</p>
<div class="content1 content"></div>
<div class="content2 content"></div>
<div class="content3 content"></div>
<div class="content4 content"></div>
</div>
body {
margin: 0;
}
#bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#percent, #scroll {
position: fixed;
top: 0;
left: 0;
font-size: 30px;
}
#scroll {
top: 40px;
color: #676767;
}
.main {
width: 100%;
}
.content {
height: 1500px;
width: 100%;
}
.content1 {
background: rgba(255, 0, 0, 0.2);
}
.content2 {
background: rgba(0, 255, 0, 0.2);
}
.content3 {
background: rgba(0, 0, 255, 0.2);
}
.content4 {
background: rgba(0, 0, 0, 0.2);
}
window.addEventListener('load', init);
function random (num) {
return Math.random() * num * 2 - num;
};
/**
* xとyの線形補完
*/
function lerp(x, y, a) {
// return (1 - a) * x + a * y;
return x + (y - x) * easeOutQuad(a);
}
/**
* パーセントのスケール
*/
function scalePercent(start, end) {
return (inertialScrollPercent - start) / (end - start);
}
function easeOutQuad(x) {
let t = x; const b = 0; const c = 1; const d = 1;
return -c * (t /= d) * (t - 2) + b;
}
// 慣性スクロールの値
let inertialScroll = 0;
// 慣性スクロールのパーセント値(0~100)
let inertialScrollPercent = 0;
let scene, camera, renderer;
const animationScripts = [
{
start: 0,
end: 25,
func: () => {
camera.position.z = lerp(
50, 30, scalePercent(0, 25)
);
}
},
{
start: 25,
end: 50,
func: () => {
camera.position.z = lerp(
30, 0, this.scalePercent(25, 50)
);
camera.rotation.x = lerp(
0,
-Math.PI / 2, scalePercent(25, 50)
);
}
},
{
start: 50,
end: 75,
func: () => {
camera.position.x = lerp(
50, 20, this.scalePercent(50, 75)
);
camera.rotation.y = lerp(
0,
-Math.PI / 2, scalePercent(50, 75)
);
}
},
{
start: 75,
end: 100,
func: () => {
camera.position.x = lerp(
20, 0, this.scalePercent(75, 100)
);
camera.position.z = lerp(
0, 30, this.scalePercent(75, 100)
);
camera.rotation.z = lerp(
0,
-Math.PI / 2, scalePercent(75, 100)
);
}
},
];
function playScrollAnimations() {
animationScripts.forEach((item) => {
if (inertialScrollPercent >= item.start && inertialScrollPercent < item.end) {
item.func();
}
});
}
function init() {
const element = document.getElementById('bg');
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(
75, element.width / element.height, 0.1, 1000
);
camera.position.set(50, 50, 50);
camera.rotation.set(0, 0, 0);
renderer = new THREE.WebGLRenderer({
canvas: element,
antialias: true,
alpha: true,
transparent: true
});
renderer.setSize( window.innerWidth, window.innerHeight );
const RANGE = 100;
for(let i = 0; i < 1000; i++) {
const geometry = new THREE.BoxBufferGeometry(4, 4, 4);
const color = new THREE.Color(0x0188c4);
color.offsetHSL(0, 0, Math.random() / 5);
const material = new THREE.MeshBasicMaterial({ color });
const box = new THREE.Mesh(geometry, material);
box.position.set(random(RANGE), random(RANGE), random(RANGE));
box.rotation.set(random(Math.PI*2), random(Math.PI*2), random(Math.PI*2));
scene.add(box);
}
render();
}
/**
* 慣性スクロールのためにスクロール値を取得する
*/
function setScrollPercent() {
inertialScroll +=
((document.documentElement.scrollTop || document.body.scrollTop) - inertialScroll) * 0.08;
// 慣性スクロールでのパーセント
inertialScrollPercent = (inertialScroll / ((document.documentElement.scrollHeight || document.body.scrollHeight) - document.documentElement.clientHeight) * 100).toFixed(2);
// 検証用の通常のパーセント
const scroll = ((document.documentElement.scrollTop || document.body.scrollTop) /
((document.documentElement.scrollHeight ||
document.body.scrollHeight) -
document.documentElement.clientHeight)) * 100;
document.getElementById('percent').innerText = inertialScrollPercent;
document.getElementById('scroll').innerText = Number(scroll).toFixed(2);
}
function render() {
renderer.render(scene, camera);
setScrollPercent();
window.requestAnimationFrame(render);
playScrollAnimations();
}
This Pen doesn't use any external CSS resources.