본문 바로가기
Programming

[PROGRAMMING] 프로그래밍 (Programming) - 이미지(Image) 돋보기(Magnifier-glass)

by 물코더 2021. 10. 2.

코드

· HTML, CSS(SCSS). 자바스크립트(Javascript)

기능

· 마우스 커서를 따라 부분 확대, 돋보기(Magnifier-glass) 효과

 

1. HTML & CSS

1) 코드 뷰

 <body>
	<!-- main-body -->
 	<main id="main-body">  
		<!-- container : magnifying_glass -->
		<section class="container flex-align-center flex-column" id="magnifier-glass"> 
			<!-- ex-2 : Magnifying-Glass -->
			<article class="content" name="ex-2">
				<!-- title -->
				<h2 class="cm-title"> Image : Magnifying-Glass </h2>
				<!-- wrap : image wrap -->
				<div class="wrap wrap-img"> 
					<!-- image -->
					<figure class="ct-img" >
						<img class="img-main" src="resource/00__example_1.jpg" decoding="async" loading="lazy" />
						<!-- <div class="magnifying-glas"> </div> -->
					</figure>
				</div>
			</article> 
			<!-- ~/ ex-1 : Magnifying-Glass-->
		</section>
	</main>
</body>
/* #main-body #magnifier-glass > .content */
.wrap 
{
  width: 100%;
  text-align: center;
  padding: 2rem 0; 
}
.wrap > .ct-img 
{
  max-width: 100%;
  position: relative;
  display: inline-block;
  border: 1px solid RGB(0, 0, 0, 0.1);
  overflow: hidden; 
}
/* 자식 노드(child) 사이즈가 큰 경우, 스크롤바 자동 활성화 */
.wrap > .ct-img.scrollbar 
{  
  overflow: auto; 
}
.wrap > .ct-img > img 
{
  width: 100%; 
}
.wrap > .ct-img .magnifying-glass 
{
  background-repeat: no-repeat;
  position: absolute;
  z-index: 2;
  left: 0;
  top: 0; 
}
/* 크기 고정 (돋보기 모드) */
.ct-img .magnifying-glass:not(.fill) 
{
  width: 150px;
  height: 150px; 
}
/* 꽉 찬 크기 */
.ct-img .magnifying-glass.fill 
{
    width: 100%;
    height: 100%; 
}

2) 노드 뷰

· main > section.container > div.wrap > figure.ct-img > img.img-main

main > section.container
article.content > div.wrap
div.wrap > figure.ct-img
div.wrap > figure.ct-img > img.img-main

 

2. 자바스크립트

· figure.ct-img 노드 이벤트 바인드 (mouseenter, mouseleave, mousemove)

1) 코드 뷰

· figure.ct-img :: mouseenter (마우스 커서 진입)

var zoom = 2; // 확대 배율

// figure.ct-img : event "mouseenter"
function ex_mouse_enter (e) 
{    
    // self : figure.ct-img 노드
    var self = this;

    // .magnifying-glass 노드 생성 
    // <div class="magnifying-glass" />
    var mglass = document.createElement("div");
    mglass.className = "magnifying-glass";

    // this > .img-main 노드
    var mimg = this.querySelector(".img-main");
    
    // * checkedDevice () : 모바일, 테블릿, PC 감지 함수 (커스텀 함수)
    if ( checkedDevice() != "pc" ) 
    {
        // 모바일 또는 테블릿
        // * addClass () : 클래스 이름 추가 함수 (커스텀 함수)
        // figure.ct-img 노드 - 'scrollbar' 클래스 이름 검사 및 추가
        addClass(this, "scrollbar"); 
        // .magnifying-glass 노드 - 'fill' 클래스 이름 검사 및 추가
        addClass(mglass, "fill");  

        // 새 이미지 노드 생성
        var _img = new Image();
        _img.onload = function () {
            // 이미지 리사이즈 (확대 배율 적용)
            this.width *= zoom;
            this.height *= zoom;
            // 노드 추가 - figure.ct-img > .magnifying-glass
            self.appendChild( mglass ); 
        };
        _img.src = mimg.src;  // 새 이미지 노드 리소스(src) 초기화
        // 노드 추가 - .magnifying-glass > img
        mglass.appendChild( _img ); 
    }
    else 
    {       
        // pc 
        // .magnifying-glass 노드 배경 이미지(background-image) 초기화
        mglass.style.backgroundImage = "URL('" + mimg.src + "')";
        // .magnifying-glass 노드 배경 크기(background-size) 확대 배율(scale) 적용
        mglass.style.backgroundSize = (mimg.clientWidth * parseInt(zoom)) + "px auto";

        // 노드 추가 - figure.ct-img > .magnifying-glass
        self.appendChild( mglass ); 
    }

    return e.stopPropagation();
}

· figure.ct-img :: mouseleave (마우스 커서 떠남)

var zoom = 2; // 확대 배율

// figure.ct-img : event "mouseleave"
function ex_mouse_leave (e) 
{
    // figure.ct-img > .magnifying-glass 노드 삭제
    var mglass = this.querySelector(".magnifying-glass");
    if ( mglass )  mglass.remove();

    // * removeClass() : 클래스 이름 삭제 함수 (커스텀 함수)
    // figure.ct-img 노드 - 'scrollbar' 클래스 이름 검사 및 삭제
    removeClass(this, "scrollbar");

    return e.stopPropagation();
}

· figure.ct-img :: mousemove (마우스 커서 움직임)

var zoom = 2; // 확대 배율

// figure.ct-img : event "mousemove"
function ex_mouse_move (e) 
{    
    // * checkedDevice () : 모바일, 테블릿, PC 감지 함수 (커스텀 함수)
    if ( checkedDevice() != "pc" ) return; 

    // figure.ct-img > .magnifying-glass 노드 선택
    var mglass = this.querySelector(".magnifying-glass");
    
    // figure.ct-img 노드 오프셋(offset)
    var _offset = this.getBoundingClientRect();  // element.getBoundingClientRect() : GET 오프셋 (내장 함수) 

   /* 
    - element.getBoundingClientRect() 함수를 통해 얻은 값(left, top)은 스크롤 위치가 포함되지 않은 절대값(오차 발생)
    - 오프셋 값에 스크롤 값을 더해 정확한 위치 값을 얻음 
   */ 
    var _left = _offset.left + (window.scrollX || window.scrollLeft || document.getElementsByTagName("html")[0].scrollLeft);
    var _top = _offset.top + (return window.scrollY || window.scrollTop || document.getElementsByTagName("html")[0].scrollTop);

    // 마우스 커서 위치 (e.pageX, e.pageY)
    var _px = e.pageX - _left;
    var _py = e.pageY - _top;
    // .magnifying-glass 위치 이동(시작점)
    mglass.style.left = _px - (mglass.clientWidth / 2) + "px"; 
    mglass.style.top = _py - (mglass.clientHeight / 2) + "px";

    // .magnifying-glass 배경 위치(background-position) 변경
    var _bpx = -(_px * zoom - mglass.clientWidth / 2);
    var _bpy = -(_py * zoom - mglass.clientHeight / 2);
    mglass.style.backgroundPosition = _bpx + "px " + _bpy + "px";
}

 

3. 결과

반응형

댓글