-
[에스비지] SVG -(15편)- 자바스크립트를 이용한 마스크 돋보기 효과 (2/2) (feat. mask, JavaScript)SVG 2021. 2. 8. 00:09
이번 시간은,
돋보기가 마우스를 따라 움직이며 저 돋보기 안쪽부분에서만 보이도록 할 것이다.
그래서 일러스트레이터로 돋보기를 그렸다.
그럼 svg는 저 초록영역의 path와
검정부분의 circle이 있을거라고 예상이 된다.
그렇게 svg 파일을 만든다.
<svg id="레이어_1" data-name="레이어 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 97.17 97.17"> <defs> <style> .cls-1 { fill: #231815; } .cls-2 { fill: #1b8964; } </style> </defs> <title>magnifier</title> <circle class="cls-1" cx="38.88" cy="38.88" r="30.15"/> <path class="cls-2" d="M86.32,25.33A38.88,38.88,0,1,0,82.06,84l26.75,26.75a1.25,1.25,0,0,0,1.77,0l6.17-6.17a1.25,1.25,0,0,0,0-1.77L90,76.06A38.88,38.88,0,0,0,86.32,25.33ZM80.15,74.15a30.15,30.15,0,1,1,0-42.64A30.16,30.16,0,0,1,80.15,74.15Z" transform="translate(-19.95 -13.95)"/> </svg>
svg 파일의 코드다.
예상대로 circle과 path가 있다.
circle은 마스크 영역이 될테다.
그럼 html에 body 안에 svg태그 안에
저 path와 circle을 복사해와서 붙여넣기 하자 색상도 같이 가져오자.
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>SVG: mask</title> <style> .magnifier { position: absolute; left: 0; top: 0; width: 100%; height: 100%; background-color: #eee; } </style> </head> <body> <svg class="magnifier"> <path class="cls-2" d="M86.32,25.33A38.88,38.88,0,1,0,82.06,84l26.75,26.75a1.25,1.25,0,0,0,1.77,0l6.17-6.17a1.25,1.25,0,0,0,0-1.77L90,76.06A38.88,38.88,0,0,0,86.32,25.33ZM80.15,74.15a30.15,30.15,0,1,1,0-42.64A30.16,30.16,0,0,1,80.15,74.15Z" transform="translate(-19.95 -13.95)" fill="#1b8964" /> <circle class="cls-1" cx="38.88" cy="38.88" r="30.15"/> </svg> </body> </html>
svg 전체 영역잡아준 뒤,
path의 색상도 inline으로 바로 적어줬다.
여기까지는 아래의 모습이다.
잘 나오고 있다.
자 그럼 마스크를 씌어보자.
이전시간에 배웠던 마스크 적용하는 것을 해보자.
https://nyjchoi.tistory.com/19
<defs></defs>
안에
<mask></mask>
쓰고 그안에 마스크 씌울
circle태그 옮겨오면 된다.
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>SVG: mask</title> <style> .magnifier { position: absolute; left: 0; top: 0; width: 100%; height: 100%; background-color: #eee; } </style> </head> <body> <svg class="magnifier"> <defs> <mask id="mask-mag"> <circle class="cls-1" cx="38.88" cy="38.88" r="30.15"/> </mask> </defs> <path class="mag-line" d="M86.32,25.33A38.88,38.88,0,1,0,82.06,84l26.75,26.75a1.25,1.25,0,0,0,1.77,0l6.17-6.17a1.25,1.25,0,0,0,0-1.77L90,76.06A38.88,38.88,0,0,0,86.32,25.33ZM80.15,74.15a30.15,30.15,0,1,1,0-42.64A30.16,30.16,0,0,1,80.15,74.15Z" transform="translate(-19.95 -13.95)" fill="#1b8964" /> </svg> </body> </html>
마스크는 설정이 됐다.
그러나 뒤에 아무것도 없으니 뒤에 배경을 깔고,
저 마스크 부분이 잘 보이는지 확인을 해보자.
그전에!! 저 circle의 색깔이 현재 검정이니 fill값으로 흰색으로 만들고,
그뒤에 배경을 깔자.
배경은 패턴을 넣어 보자.
패턴이 기억안난다면,
https://nyjchoi.tistory.com/17?category=875542
https://nyjchoi.tistory.com/18?category=875542
이 두곳에서 학습하고 돌아와 보자.
우리가 만들었던 그 얼굴모양을 넣어보겠다.
1. face.svg 파일의 도형들 및 패스들을 가져와
pattern 태그 안에 넣어준다.
자 지금 우리는 바로 눈에 보이는 것을 작업하고 있는게 아니라
defs 안에 마스크를 생성했고,
패턴을 생성했다.
연결하지 않으면, 확인할 수 없다.
따라서,
2. 우리는 패턴을 설정은 했지만 깔아줘야 보이기 때문에,
<rect></rect>
를 통해서
svg 사이즈에 맞게 너비 와 높이를 설정한 뒤에
패턴을 넣을 것이다.
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>SVG: mask</title> <style> .magnifier { position: absolute; left: 0; top: 0; width: 100%; height: 100%; background-color: #eee; } </style> </head> <body> <svg class="magnifier"> <defs> <pattern id="pattern_face" x="0" y="0" width="0.1" height="0.1" viewBox="0 0 500 500"> <circle cx="213.63" cy="186" r="156" stroke-width="10" fill="none" stroke="#231815" stroke-miterlimit="10"/> <circle class="cls-2" cx="273.13" cy="162.94" r="23.06"/> <circle class="cls-2" cx="154.13" cy="162.94" r="23.06"/> <path d="M301.36 240.03a100 100 0 01-175.47 0" stroke-linecap="round" stroke-width="11" fill="none" stroke="#231815" stroke-miterlimit="10"/> <circle class="cls-2" cx="85.83" cy="95.33" r="30"/> <circle class="cls-2" cx="109.83" cy="68.67" r="30"/> <circle class="cls-2" cx="133.83" cy="42" r="30"/> <circle class="cls-2" cx="169.83" cy="32.67" r="30"/> <circle class="cls-2" cx="203.83" cy="30" r="30"/> <circle class="cls-2" cx="243.63" cy="32.67" r="30"/> <circle class="cls-2" cx="280.07" cy="42" r="30"/> <circle class="cls-2" cx="310.07" cy="60" r="30"/> <circle class="cls-2" cx="336.07" cy="85.33" r="30"/> <ellipse class="cls-4" cx="29.83" cy="196.33" rx="27.33" ry="36.33"/> <ellipse class="cls-4" cx="396.96" cy="196.33" rx="27.33" ry="36.33"/> <path class="cls-2" d="M398.29 218.22l3.98 12.27h12.9l-10.43 7.57 3.98 12.26-10.43-7.57-10.43 7.57 3.99-12.26-10.43-7.57h12.89l3.98-12.27zM28.96 218.22l-3.98 12.27h-12.9l10.43 7.57-3.98 12.26 10.43-7.57 10.43 7.57-3.99-12.26 10.43-7.57H32.94l-3.98-12.27z"/> </pattern> <mask id="mask-mag"> <circle class="cls-1" cx="38.88" cy="38.88" r="30.15" fill="#fff"/> </mask> <style> <![CDATA[ .cls-4{fill:none;stroke:#231815;stroke-miterlimit:10} .cls-2{fill:#231815} .cls-4{stroke-width:5px} .bg-pattern { fill: url(#pattern_face); } ]]> </style> </defs> <path class="mag-line" d="M86.32,25.33A38.88,38.88,0,1,0,82.06,84l26.75,26.75a1.25,1.25,0,0,0,1.77,0l6.17-6.17a1.25,1.25,0,0,0,0-1.77L90,76.06A38.88,38.88,0,0,0,86.32,25.33ZM80.15,74.15a30.15,30.15,0,1,1,0-42.64A30.16,30.16,0,0,1,80.15,74.15Z" transform="translate(-19.95 -13.95)" fill="#1b8964" /> <rect class="bg-pattern" x="0" y="0" width="100%" height="100%"></rect> </svg> </body> </html>
여기까지의 모습은,
그럼 우리는 마스크를 설정해 뒀기에
3. 우리는 그 마스크를 전체 사각형에 연결시켜주면 될 것이다.
g태그를 통해서!
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>SVG: mask</title> <style> .magnifier { position: absolute; left: 0; top: 0; width: 100%; height: 100%; background-color: #eee; } </style> </head> <body> <svg class="magnifier"> <defs> <pattern id="pattern_face" x="0" y="0" width="0.1" height="0.1" viewBox="0 0 500 500"> <circle cx="213.63" cy="186" r="156" stroke-width="10" fill="none" stroke="#231815" stroke-miterlimit="10"/> <circle class="cls-2" cx="273.13" cy="162.94" r="23.06"/> <circle class="cls-2" cx="154.13" cy="162.94" r="23.06"/> <path d="M301.36 240.03a100 100 0 01-175.47 0" stroke-linecap="round" stroke-width="11" fill="none" stroke="#231815" stroke-miterlimit="10"/> <circle class="cls-2" cx="85.83" cy="95.33" r="30"/> <circle class="cls-2" cx="109.83" cy="68.67" r="30"/> <circle class="cls-2" cx="133.83" cy="42" r="30"/> <circle class="cls-2" cx="169.83" cy="32.67" r="30"/> <circle class="cls-2" cx="203.83" cy="30" r="30"/> <circle class="cls-2" cx="243.63" cy="32.67" r="30"/> <circle class="cls-2" cx="280.07" cy="42" r="30"/> <circle class="cls-2" cx="310.07" cy="60" r="30"/> <circle class="cls-2" cx="336.07" cy="85.33" r="30"/> <ellipse class="cls-4" cx="29.83" cy="196.33" rx="27.33" ry="36.33"/> <ellipse class="cls-4" cx="396.96" cy="196.33" rx="27.33" ry="36.33"/> <path class="cls-2" d="M398.29 218.22l3.98 12.27h12.9l-10.43 7.57 3.98 12.26-10.43-7.57-10.43 7.57 3.99-12.26-10.43-7.57h12.89l3.98-12.27zM28.96 218.22l-3.98 12.27h-12.9l10.43 7.57-3.98 12.26 10.43-7.57 10.43 7.57-3.99-12.26 10.43-7.57H32.94l-3.98-12.27z"/> </pattern> <mask id="mask-mag"> <circle class="cls-1" cx="38.88" cy="38.88" r="30.15" fill="#fff"/> </mask> <style> <![CDATA[ .cls-4{fill:none;stroke:#231815;stroke-miterlimit:10} .cls-2{fill:#231815} .cls-4{stroke-width:5px} .bg-pattern { fill: url(#pattern_face); } ]]> </style> </defs> <path class="mag-line" d="M86.32,25.33A38.88,38.88,0,1,0,82.06,84l26.75,26.75a1.25,1.25,0,0,0,1.77,0l6.17-6.17a1.25,1.25,0,0,0,0-1.77L90,76.06A38.88,38.88,0,0,0,86.32,25.33ZM80.15,74.15a30.15,30.15,0,1,1,0-42.64A30.16,30.16,0,0,1,80.15,74.15Z" transform="translate(-19.95 -13.95)" fill="#1b8964" /> <g mask="url(#mask-mag)"> <rect class="bg-pattern" x="0" y="0" width="100%" height="100%"></rect> </g> </svg> </body> </html>
g태그로 rect를 묶고 mask속성으로 url 연결 해주면,
보기와 같이 마스크가 적용이 됐다.
이제는 저 돋보기의 움직임을 자바스크립트를 통해 주면 된다.
DOM script로 만들어 줄것이다.
script태그 안에 써주면 된다.
<script> window.addEventListener('DOMContentLoaded', function(){ }); </script>
이렇게 시작을 한다.
이것의 의미는 컴퓨터는 위에서 부터 차례로 읽어들이기 때문에,
아직 정의되지 않은 이름이거나 셀렉터나 등등이 나오면,
자바스크립트가 그게 뭔지 알 수 없어
오류아닌 오류가 난다.
그래서 전체를 로드한 뒤에 자바스크립트를 읽어라 라는 명령문이
저 위에 있는,
<script> window.addEventListener('DOMContentLoaded', function(){ }); </script>
이다.
하지만,
DOMContentLoaded
대신에
load
를 해도 잘 작동 되지만,
둘의 차이는 load는 용량이 큰 이미지가 있다면 그런것들까지 다 로드 한 뒤에 명령이 실행된다면,
DOMContentLoaded는 DOM구조(태그들의 구조)만 로드 되면, 명령문이 실행되는 것이기 때문에,
용량이 큰 어떤 것들이 다 로드 될때까지 기다릴 필요 없이,
속도면에서 조금 더 빠를 수 밖에 없다.
그래서 우리는 변수나 상수로 가져올 것들을 먼저 선언하고 그것들을 이용해
마우스의 움직임에 따라 움직일 수 있도록 만들어 볼 것이다.
우선 변수나 상수부터 만들어보자
<script> window.addEventListener('DOMContentLoaded', function(){ const magnifierElem = document.querySelector('.mag-line'); const circleElem = document.querySelector('#mask-mag circle'); }); </script>
그럼 마우스가 움직일때를 사용할때는,
<script> window.addEventListener('DOMContentLoaded', function(){ const magnifierElem = document.querySelector('.mag-line'); const circleElem = document.querySelector('#mask-mag circle'); window.addEventListener('mousemove', function(){ }); }); </script>
mousemove 이벤트를 사용한다.
그리고 마우스의 이동에 따라 위치값을 가지려면
이벤트객체가 가진 clientX 와 clientY 값을 사용하면 된다.
<script> window.addEventListener('DOMContentLoaded', function(){ const magnifierElem = document.querySelector('.mag-line'); const circleElem = document.querySelector('#mask-mag circle'); window.addEventListener('mousemove', function(e){ magnifierElem.style.transform = `translate(${e.clientX}px, ${e.clientY}px)`; }); }); </script>
저기서 ``는 키보드에서 보면 숫자 1 왼쪽에 있는 키다.
보간법이라고 해서,
영어로는
Template Strings
이라고 한다.
https://blog.naver.com/nicholasdw/222216524747
여기에서 이에대한 설명을 해뒀으니 확인바란다.
1분코딩님이 설명하시길,
예전에는 "" 나 '' 같은 따옴표과 ++를 사용하여 저렇게 넣었다면,
<script> window.addEventListener('DOMContentLoaded', function(){ const magnifierElem = document.querySelector('.mag-line'); const circleElem = document.querySelector('#mask-mag circle'); window.addEventListener('mousemove', function(e){ magnifierElem.style.transform = "translate("+ e.clientX +"px," + e.clientY +"px)"; }); }); </script>
요즘은 저 위에 설명한
템플릿 스프링스
방식으로 간결하게 사용한다고 한다.
<script> window.addEventListener('DOMContentLoaded', function(){ const magnifierElem = document.querySelector('.mag-line'); const circleElem = document.querySelector('#mask-mag circle'); window.addEventListener('mousemove', function(e){ magnifierElem.style.transform = `translate(${e.clientX}px, ${e.clientY}px)`; circleElem.style.transform = `translate(${e.clientX}px, ${e.clientY}px)`; }); }); </script>
이렇게 작성해주면,
마우스가 움직일때 따라다니는 걸 만들 수 있다.
그리고 그 마스크를 통해
돋보기 안에만 뒷 배경이 보이게 할 수 있는 것이다.
오늘은 여기까지.
'SVG' 카테고리의 다른 글