https://www.youtube.com/watch?v=DeHRDNRQhNg
데모 : https://ohikmyeong.github.io/hpp-wand-reveal/
깃허브 : https://github.com/OhIkmyeong/hpp-wand-reveal
마우스의 좌표값에 따라 마술봉이 움직이며, 갤러리의 사진들이 마술봉이 지나간 자리에선 opacity가 1, blur가 0이 되며, 지나가기전엔 opacity가 0, blur가 n값이 된다. 마술봉이 지나가고 나면 보이지 않았고 흐리했던 사진들이 스르륵 보여지는 재밌는 효과...
js의 animate API를 사용하여 단순 css효과가 아닌 부드러운 마술봉의 움직임과,
마우스의 위치보다, 마우스의 위치에 따라 좀 더 왼쪽/오른쪽에 마술봉이 위치하여, 마우스가 아닌 마술봉의 위치에 따라 밑의 사진들이 보이고/안보이고 효과가 전환되는 것 처럼 보이게 함.
마술봉의 위치와 각도를 어떻게 수학적으로 계산할 것인가가 중요한 포인트였음
예를들어 현재 마우스의 좌표를 clientX라고 하고, 화면의 넓이를 winWid라고 할 때,
마술봉이 화면 왼쪽보다 -15%, 화면 오른쪽보다 15% 더 움직이게 하고 싶다면, (단 마우스커서가 중앙일땐 마술봉도 중앙에 있어야함)
/**
* 마술봉의 좌표. 화면 넓이의 -15%를 빼고, 현재 마우스 좌표에서 30%를 더하면 의도한 마술봉의 좌표값이 된다.
* 예) 화면의 넓이가 800px이고, 15%씩 추가/감소 마술봉의 위치를 조절하고 싶을때
* mouseX | 계산 | wandX
* 0 | -120 + 0 | -120
* 400 | -120 + 520 | 400
* 800 | -120 + 1040 | 920
* */
const wandX = (winWid * -0.15) + (clientX * 1.3);
HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Wand Reveal Gallery(opacity,blur)</title>
<link rel="stylesheet" href="./css/main.css">
<script src="./js/main.js" type="module"></script>
</head>
<body>
<div id="wrapper">
<div id="wand"></div>
<a href="https://www.youtube.com/watch?v=DeHRDNRQhNg" target="_blank">[Hyperplexed]This Website Theme Hasn't Been Perfected Since 1996</a>
<ul id="gall">
<li class="gall-item">
<img src="https://images.unsplash.com/photo-1689005046866-9586288969a3?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw1fHx8ZW58MHx8fHx8&auto=format&fit=crop&w=500&q=60" class="gall-item-photo"/>
</li><!-- -->
<li class="gall-item">
<img src="https://images.unsplash.com/photo-1687941336891-1c46fac86075?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxN3x8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=500&q=60" class="gall-item-photo"/>
</li><!-- -->
<li class="gall-item">
<img src="https://images.unsplash.com/photo-1688607932382-f01b0987c897?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw5M3x8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=500&q=60" class="gall-item-photo"/>
</li><!-- -->
</ul>
</div><!-- wrapper -->
</body>
</html>
|
cs |
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import { Gall } from "./Gall.js";
import { Wand } from "./Wand.js";
const WAND = new Wand();
const GALL = new Gall();
window.addEventListener('mousemove',e=>{
WAND.move_wand(e);
GALL.toggle_reveal(e);
});
window.addEventListener('resize', ()=>{
WAND.get_width();
});
|
cs |
Wans.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
export class Wand {
constructor() {
this.$wand = document.getElementById('wand');
this.get_width();
}//constructor
get_width() {
this.winWid = window.innerWidth;
this.winHei = window.innerHeight;
this.winWidHalf = window.innerWidth / 2;
this.width = this.$wand.getBoundingClientRect().width;
}//get_width
move_wand = (e) => {
const { clientX, clientY } = e;
// this.$wand.style.transform = `translate(${clientX - (this.width / 2)}px, ${clientY}px)`;
const per = clientX / this.winWid;
const deg = (per * 50) - 25; //-10 ~ 10이라 20 곱하고 -10 뺀거임
const wandX = (this.winWid * -0.15) + clientX * 1.3;
console.log(wandX);
const wandY = (this.winHei * 0.1) + clientY * 0.4;
this.$wand.animate([
{ transform: `translate(${wandX}px, ${wandY}px) rotate(${deg}deg)` }
], {
duration: 500,
fill: "forwards"
});
}//move_wand
}//class-Wand
|
cs |
Gall.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
export class Gall{
constructor(){
this.$gall = document.getElementById('gall');
this.$$item = this.$gall.querySelectorAll('.gall-item');
this.init();
}//constructor
init(){
/* 각자 부채처럼 회전시키기 */
}//init
toggle_reveal(e){
const {clientX,clientY} = e;
const wandX = (window.innerWidth * -0.5) + clientX * 2.0;
this.$$item.forEach($item=>{
const $img = $item.querySelector('.gall-item-photo');
const {left,width} = $item.getBoundingClientRect();
const relX = wandX - left;
const relXDec = relX / width;
const opacity = relXDec;
const blur = (1 - relXDec) * 10;
$item.style.setProperty('--opacity',opacity);
$item.style.setProperty('--blur',`${blur * 10}px`);
});
}//toggle_reveal
}//class-Gall
|
cs |
css는 특별할거 없어서 생략함. 어차피 Gall.js에서 각 요소의 위치는 getBoundingClientRect()로 가져오기 때문에, 갤러리 요소의 배치를 flex box로 하든 absolute로 하든 상관이 없다.
'CSS&JS > 👀Study and Copy' 카테고리의 다른 글
[WDS] 마크다운 문법 (1) | 2023.08.24 |
---|---|
[Hyperplexed]클릭, 그리드 그라데이션 효과 (0) | 2023.07.12 |
[Hyperplexed]패럴랙스 드래그 슬라이드 (0) | 2023.06.14 |
[HPP]hacker effect text 랜덤으로 다른문자열로 대체되는 텍스트 효과 (0) | 2023.06.14 |
[Hyperplexed] 인터랙티브한 마우스 커서 (0) | 2023.06.13 |