-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
강태희
committed
Jan 8, 2025
1 parent
379dbf2
commit 4e8567f
Showing
12 changed files
with
6,377 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Mouse Reactive Smoke</title> | ||
<style> | ||
body { | ||
margin: 0; | ||
overflow: hidden; | ||
} | ||
canvas { | ||
display: block; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<!-- <script src="" integrity="sha512-1Ta3TNpk5OD+XKlVMaJY7dC5Tu/Lx4jd2BPu8kxUZ/+hAHpxawrvSiRN0cvBU+oDmSwWVzK8FbILwudcZF6KEQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> --> | ||
<script type="module"> | ||
import * as THREE from 'https://cdnjs.cloudflare.com/ajax/libs/three.js/0.172.0/three.module.min.js'; | ||
|
||
// Scene, Camera, Renderer | ||
const scene = new THREE.Scene(); | ||
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); | ||
const renderer = new THREE.WebGLRenderer(); | ||
renderer.setSize(window.innerWidth, window.innerHeight); | ||
document.body.appendChild(renderer.domElement); | ||
|
||
// Particle System | ||
const particleCount = 50; | ||
const particles = new THREE.BufferGeometry(); | ||
const positions = new Float32Array(particleCount * 3); // x, y, z for each particle | ||
const velocities = new Float32Array(particleCount * 3); // velocity for each axis | ||
|
||
for (let i = 0; i < particleCount; i++) { | ||
positions[i * 3] = (Math.random() - 0.5) * 20; // x | ||
positions[i * 3 + 1] = (Math.random() - 0.5) * 20; // y | ||
positions[i * 3 + 2] = (Math.random() - 0.5) * 20; // z | ||
|
||
velocities[i * 3] = 0; | ||
velocities[i * 3 + 1] = 0; | ||
velocities[i * 3 + 2] = 0; | ||
} | ||
|
||
particles.setAttribute('position', new THREE.BufferAttribute(positions, 3)); | ||
particles.setAttribute('velocity', new THREE.BufferAttribute(velocities, 3)); | ||
|
||
const material = new THREE.PointsMaterial({ | ||
color: 0xffffff, | ||
size: 0.2, | ||
transparent: true, | ||
opacity: 0.8, | ||
blending: THREE.AdditiveBlending, | ||
}); | ||
const particleSystem = new THREE.Points(particles, material); | ||
scene.add(particleSystem); | ||
|
||
// Camera position | ||
camera.position.z = 10; | ||
|
||
// Mouse interaction | ||
const mouse = new THREE.Vector2(); | ||
window.addEventListener('mousemove', (event) => { | ||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; | ||
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; | ||
}); | ||
|
||
// Animation loop | ||
function animate() { | ||
const positions = particles.getAttribute('position'); | ||
const velocities = particles.getAttribute('velocity'); | ||
|
||
for (let i = 0; i < particleCount; i++) { | ||
// Add mouse influence | ||
const dx = mouse.x * 10 - positions.array[i * 3]; | ||
const dy = mouse.y * 10 - positions.array[i * 3 + 1]; | ||
const distance = Math.sqrt(dx * dx + dy * dy); | ||
|
||
const force = Math.min(1 / distance, 0.02); | ||
|
||
velocities.array[i * 3] += force * dx * 0.1; | ||
velocities.array[i * 3 + 1] += force * dy * 0.1; | ||
|
||
// Update positions with velocity | ||
positions.array[i * 3] += velocities.array[i * 3]; | ||
positions.array[i * 3 + 1] += velocities.array[i * 3 + 1]; | ||
positions.array[i * 3 + 2] += velocities.array[i * 3 + 2] * 0.95; // Slow Z-axis | ||
|
||
// Fade out effect | ||
velocities.array[i * 3] *= 0.95; | ||
velocities.array[i * 3 + 1] *= 0.95; | ||
velocities.array[i * 3 + 2] *= 0.95; | ||
} | ||
|
||
particles.getAttribute('position').needsUpdate = true; | ||
particles.getAttribute('velocity').needsUpdate = true; | ||
|
||
renderer.render(scene, camera); | ||
requestAnimationFrame(animate); | ||
} | ||
|
||
animate(); | ||
</script> | ||
</body> | ||
</html> |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/*! locomotive-scroll v4.1.3 | MIT License | https://github.com/locomotivemtl/locomotive-scroll */ | ||
html.has-scroll-smooth { | ||
overflow: hidden; } | ||
|
||
html.has-scroll-dragging { | ||
-webkit-user-select: none; | ||
-moz-user-select: none; | ||
-ms-user-select: none; | ||
user-select: none; } | ||
|
||
.has-scroll-smooth body { | ||
overflow: hidden; } | ||
|
||
.has-scroll-smooth [data-scroll-container] { | ||
min-height: 100vh; } | ||
|
||
[data-scroll-direction="horizontal"] [data-scroll-container] { | ||
height: 100vh; | ||
display: inline-block; | ||
white-space: nowrap; } | ||
|
||
[data-scroll-direction="horizontal"] [data-scroll-section] { | ||
display: inline-block; | ||
vertical-align: top; | ||
white-space: nowrap; | ||
height: 100%; } | ||
|
||
.c-scrollbar { | ||
position: absolute; | ||
right: 0; | ||
top: 0; | ||
width: 11px; | ||
height: 100%; | ||
transform-origin: center right; | ||
transition: transform 0.3s, opacity 0.3s; | ||
opacity: 0; } | ||
.c-scrollbar:hover { | ||
transform: scaleX(1.45); } | ||
.c-scrollbar:hover, .has-scroll-scrolling .c-scrollbar, .has-scroll-dragging .c-scrollbar { | ||
opacity: 1; } | ||
[data-scroll-direction="horizontal"] .c-scrollbar { | ||
width: 100%; | ||
height: 10px; | ||
top: auto; | ||
bottom: 0; | ||
transform: scaleY(1); } | ||
[data-scroll-direction="horizontal"] .c-scrollbar:hover { | ||
transform: scaleY(1.3); } | ||
|
||
.c-scrollbar_thumb { | ||
position: absolute; | ||
top: 0; | ||
right: 0; | ||
background-color: black; | ||
opacity: 0.5; | ||
width: 7px; | ||
border-radius: 10px; | ||
margin: 2px; | ||
cursor: -webkit-grab; | ||
cursor: grab; } | ||
.has-scroll-dragging .c-scrollbar_thumb { | ||
cursor: -webkit-grabbing; | ||
cursor: grabbing; } | ||
[data-scroll-direction="horizontal"] .c-scrollbar_thumb { | ||
right: auto; | ||
bottom: 0; } |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<!DOCTYPE html> | ||
<html lang="ko"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Document</title> | ||
<link rel="stylesheet" href="locomotive-scroll.css" /> | ||
</head> | ||
<body> | ||
<script src="https://cdn.jsdelivr.net/npm/locomotive-scroll@beta/bundled/locomotive-scroll.min.js"></script> | ||
<script> | ||
(function () { | ||
const locomotiveScroll = new LocomotiveScroll(); | ||
})(); | ||
</script> | ||
<div style="height: 100vh"></div> | ||
<main style="height: 150vh"> | ||
<div data-scroll > | ||
<div> | ||
<h1>Hello 👋</h1> | ||
</div> | ||
<div> | ||
<h2>What's up?</h2> | ||
<p>😬</p> | ||
</div> | ||
</div> | ||
</main> | ||
|
||
<script > | ||
// import LocomotiveScroll from 'locomotive-scroll'; | ||
|
||
const scroll = new LocomotiveScroll(); | ||
|
||
scroll.on('call', (func) => { | ||
// Using modularJS | ||
this.call(...func); | ||
// Using jQuery events | ||
$(document).trigger(func); | ||
// Or do it your own way 😎 | ||
}); | ||
</script> | ||
</body> | ||
</html> |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
// import {TweenMax, Power2, TimelineLite} from "gsap"; | ||
import { TweenMax, TimelineMax, Power2, Power1, TweenLite, Circ } from 'gsap/all'; | ||
|
||
class ActivitiesAnimationComponent { | ||
constructor(options) { | ||
console.log(options) | ||
this.el = options.el; | ||
this._setup(); | ||
this._setupEventListener(); | ||
} | ||
|
||
_setup() { | ||
this._ui = { | ||
animationContainer: this.el.querySelector('.section-activites__content'), | ||
imageAnimationContainer: this.el.querySelector('.section-activites__images-container'), | ||
nextImageContainer: this.el.querySelector(".section-activites__next-image"), | ||
currentImageContainer: this.el.querySelector(".section-activites__current-image"), | ||
nextImage: this.el.querySelector(".section-activites__next-image .section-activites__image"), | ||
currentImage: this.el.querySelector(".section-activites__current-image .section-activites__image"), | ||
listActivities: this.el.querySelector(".section-activites__list"), | ||
activity: this.el.querySelectorAll(".section-activites__list-item"), | ||
activityLinks: this.el.querySelectorAll(".section-activites__list-item a"), | ||
activityLinksSpan: this.el.querySelectorAll(".section-activites__list-item a span") | ||
|
||
} | ||
this.mouse = { x: 0, y: 0 }; | ||
this._setupTween(); | ||
|
||
|
||
} | ||
|
||
_setupTween() { | ||
this.timelineIntro = new TimelineMax({ paused: true, onComplete: () => { this._onCompleteIntro() } }); | ||
this.timelineIntro | ||
.fromTo(this._ui.nextImageContainer, 1, { height: 0 }, { height: 500, ease: Power2.easeInOut }, 0) | ||
.fromTo(this._ui.nextImage, 1.1, { autoAlpha: 0, scale: 1.3 }, { autoAlpha: 1, scale: 1, ease: Power1.easeOut }, 0) | ||
} | ||
|
||
_setupEventListener() { | ||
this._ui.animationContainer.addEventListener('mousemove', () => this._mouseFollow()); | ||
|
||
for (let index = 0; index < this._ui.activity.length; index++) { | ||
this._ui.activity[index].addEventListener('mouseenter', () => { this._mouseEnterFunction(index) }); | ||
} | ||
|
||
this._ui.listActivities.addEventListener('mouseleave', () => this._leaveContainer()); | ||
|
||
} | ||
|
||
_mouseEnterFunction(index) { | ||
TweenMax.to(this._ui.imageAnimationContainer, .5, { autoAlpha: 1, ease: Power1.easeInOut }); | ||
if (this._ui.currentImage.src === "") { | ||
this._firstImageAnimation(index); | ||
} else { | ||
this._imageAnimation(index); | ||
this._textAnimation(index); | ||
} | ||
} | ||
|
||
_textAnimation(index) { | ||
let textBounds = this._ui.activityLinks[index].getBoundingClientRect(); | ||
let imageAnimationContainerBounds = this._ui.imageAnimationContainer.getBoundingClientRect(); | ||
this._ui.activityLinks[index].addEventListener('mousemove', () => { | ||
|
||
let positionMouse = event.clientX - textBounds.left, | ||
minPositionPath = positionMouse - imageAnimationContainerBounds.width / 2, | ||
maxPositionPath = positionMouse + imageAnimationContainerBounds.width / 2; | ||
|
||
TweenMax.to(this._ui.activityLinksSpan[index], 0.7, { webkitClipPath: `polygon(${minPositionPath}px 0, ${maxPositionPath}px 0, ${maxPositionPath}px 100%, ${minPositionPath}px 100%)`, ease: Power2.easeInCubic }); | ||
TweenMax.to(this._ui.activityLinksSpan[index], 0.7, { clipPath: `polygon(${minPositionPath}px 0, ${maxPositionPath}px 0, ${maxPositionPath}px 100%, ${minPositionPath}px 100%)`, ease: Power2.easeInCubic }); | ||
|
||
}); | ||
} | ||
|
||
_firstImageAnimation(index) { | ||
this._ui.currentImage.style.opacity = 0; | ||
this._ui.nextImage.src = this._ui.activity[index].dataset.image; | ||
this.currentImageLink = this._ui.activity[index].dataset.image; | ||
this._ui.currentImage.src = this.currentImageLink; | ||
|
||
this.timelineIntro.play(); | ||
} | ||
|
||
_leaveContainer() { | ||
TweenMax.to(this._ui.imageAnimationContainer, .5, | ||
{ | ||
autoAlpha: 0, | ||
onComplete: () => { | ||
this._ui.currentImage.src = ""; | ||
this._ui.nextImage.src = ""; | ||
}, | ||
ease: Power1.easeInOut | ||
} | ||
); | ||
} | ||
|
||
_onCompleteIntro() { | ||
this._ui.currentImage.src = this.currentImageLink; | ||
this._ui.currentImage.style.opacity = 1 | ||
} | ||
|
||
_onCompleteImageChange() { | ||
this._ui.currentImage.src = this.currentImageLink | ||
} | ||
|
||
_imageAnimation(index) { | ||
this.currentImageLink = this._ui.activity[index].dataset.image; | ||
this._ui.nextImage.src = this._ui.activity[index].dataset.image; | ||
TweenLite.fromTo(this._ui.nextImageContainer, 1, { height: 0, ease: Power2.easeInOut }, { height: 500, ease: Power2.easeInOut, onComplete: () => this._onCompleteImageChange() }, 0) | ||
TweenLite.fromTo(this._ui.nextImage, 1.1, { scale: 1.3 }, { scale: 1, ease: Power1.easeOut }, 0) | ||
} | ||
|
||
_mouseFollow() { | ||
let imageAnimationContainerBounds = this._ui.imageAnimationContainer.getBoundingClientRect(); | ||
|
||
this.mouse.x = event.clientX; | ||
this.mouse.y = event.clientY - this.el.getBoundingClientRect().y; | ||
|
||
|
||
TweenMax.to(this._ui.imageAnimationContainer, 0.7, { x: this.mouse.x - (imageAnimationContainerBounds.width / 2), y: this.mouse.y - (imageAnimationContainerBounds.height / 2), ease: Power2.easeInCubic }) | ||
} | ||
|
||
} | ||
// const instance = new ActivitiesAnimationComponent(); | ||
// instance._setup() | ||
// export default ActivitiesAnimationComponent; | ||
|
||
|
||
const COMPONENTS = { | ||
'activities-animation': ActivitiesAnimationComponent | ||
} | ||
|
||
class ComponentFactory { | ||
constructor() { | ||
this._selector = 'data-component'; | ||
this._elements = document.querySelectorAll(`[${this._selector}]`); | ||
this._components = {}; | ||
} | ||
|
||
start() { | ||
for (let i = 0, limit = this._elements.length; i < limit; i++) { | ||
const element = this._elements[i]; | ||
const componentName = element.getAttribute(this._selector); | ||
if (COMPONENTS[componentName]) { | ||
const Component = COMPONENTS[componentName]; | ||
new Component({ el: element }); | ||
} else { | ||
console.log(`Component: '${componentName}' not found`); | ||
} | ||
} | ||
} | ||
} | ||
|
||
const instance = new ComponentFactory(); | ||
instance.start() |
Oops, something went wrong.