Last active
November 10, 2024 10:41
-
-
Save ks-tmatsuoka/7fcdf489df2ba411f29d0189da9a4379 to your computer and use it in GitHub Desktop.
kobesoft.co.jpのトップページクリエイティブjs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="ja"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Three.js Example</title> | |
<style> | |
body { margin: 0; } | |
#container { | |
width: 100%; | |
height: 500px; | |
background: linear-gradient(to bottom, #ff7e5f, #feb47b); | |
} | |
</style> | |
</head> | |
<body> | |
<div id="container"></div> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> | |
<script> | |
let scene, camera, renderer, points, lines; | |
let targetPosition = new THREE.Vector3(); | |
let direction = new THREE.Vector3(); | |
let speed = 0.02; | |
let lastUpdateTime = 0; | |
function init() { | |
// シーンの作成 | |
scene = new THREE.Scene(); | |
// カメラの作成 | |
camera = new THREE.PerspectiveCamera(75, window.innerWidth / 500, 0.1, 1000); | |
camera.position.z = 5; | |
// レンダラーの作成(背景透過) | |
renderer = new THREE.WebGLRenderer({ alpha: true }); | |
renderer.setSize(window.innerWidth, 500); | |
renderer.autoClear = false; // 加算合成のために自動クリアを無効にする | |
document.getElementById('container').appendChild(renderer.domElement); | |
// 頂点の作成 | |
const vertices = []; | |
for (let i = 0; i < 300; i++) { | |
vertices.push(new THREE.Vector3( | |
(Math.random() - 0.5) * 10, | |
(Math.random() - 0.5) * 10, | |
(Math.random() - 0.5) * 10 | |
)); | |
} | |
// グロー効果のシェーダーマテリアルを作成 | |
const vertexShader = ` | |
varying vec3 vColor; | |
void main() { | |
vColor = color; | |
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0); | |
gl_PointSize = 0.1 * (300.0 / -mvPosition.z); // 点のサイズを調整 | |
gl_Position = projectionMatrix * mvPosition; | |
} | |
`; | |
const fragmentShader = ` | |
uniform vec3 color; | |
varying vec3 vColor; | |
void main() { | |
float distance = length(gl_PointCoord - vec2(0.5, 0.5)); | |
float strength = 1.0 - distance * 2.0; | |
gl_FragColor = vec4(color * vColor, strength); | |
} | |
`; | |
const shaderMaterial = new THREE.ShaderMaterial({ | |
uniforms: { | |
color: { value: new THREE.Color(0xffffff) } | |
}, | |
vertexShader: vertexShader, | |
fragmentShader: fragmentShader, | |
blending: THREE.AdditiveBlending, | |
depthTest: false, | |
transparent: true, | |
vertexColors: true | |
}); | |
const pointsGeometry = new THREE.BufferGeometry().setFromPoints(vertices); | |
points = new THREE.Points(pointsGeometry, shaderMaterial); | |
scene.add(points); | |
// 距離が近い点同士を線で結ぶ | |
const maxDistance = 5.0; // 最大距離を5に設定 | |
const edges = []; | |
const colors = []; | |
for (let i = 0; i < vertices.length; i++) { | |
const distances = []; | |
for (let j = 0; j < vertices.length; j++) { | |
if (i !== j) { | |
const distance = vertices[i].distanceTo(vertices[j]); | |
if (distance < maxDistance) { | |
distances.push({ index: j, distance: distance }); | |
} | |
} | |
} | |
distances.sort((a, b) => a.distance - b.distance); | |
for (let k = 0; k < Math.min(5, distances.length); k++) { // 最大5本に制限 | |
const j = distances[k].index; | |
const distance = distances[k].distance; | |
edges.push(vertices[i].x, vertices[i].y, vertices[i].z); | |
edges.push(vertices[j].x, vertices[j].y, vertices[j].z); | |
const alpha = Math.min(0.1, 1.0 - (distance / maxDistance)); // アルファ値を最大0.1に制限 | |
colors.push(1.0, 1.0, 1.0, alpha); | |
colors.push(1.0, 1.0, 1.0, alpha); | |
} | |
} | |
const lineGeometry = new THREE.BufferGeometry(); | |
lineGeometry.setAttribute('position', new THREE.Float32BufferAttribute(edges, 3)); | |
lineGeometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 4)); | |
const lineMaterial = new THREE.LineBasicMaterial({ | |
vertexColors: true, | |
transparent: true, | |
blending: THREE.AdditiveBlending | |
}); | |
lines = new THREE.LineSegments(lineGeometry, lineMaterial); | |
scene.add(lines); | |
// 初期目標位置の設定 | |
updateTargetPosition(); | |
// アニメーションの開始 | |
animate(); | |
} | |
function updateTargetPosition() { | |
targetPosition.set( | |
(Math.random() - 0.5) * 10, | |
(Math.random() - 0.5) * 10, | |
(Math.random() - 0.5) * 10 | |
); | |
} | |
function animate(time) { | |
requestAnimationFrame(animate); | |
// 5秒ごとに目標位置を更新 | |
if (time - lastUpdateTime > 5000) { | |
updateTargetPosition(); | |
lastUpdateTime = time; | |
} | |
// カメラが目標位置の近くに来たら目標位置を更新 | |
if (camera.position.distanceTo(targetPosition) < 1) { | |
updateTargetPosition(); | |
} | |
// カメラの移動方向を目標位置に向けてゆるやかに更新 | |
direction.lerp(targetPosition.clone().sub(camera.position).normalize(), 0.02); | |
// カメラを移動 | |
camera.position.add(direction.clone().multiplyScalar(speed)); | |
// カメラが常に中央を見る | |
camera.lookAt(scene.position); | |
renderer.clear(); | |
renderer.render(scene, camera); | |
} | |
init(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment