原生JS實現類似《掘金》網站的圖片檢視器

jinzhe發表於2018-05-15

經常看掘金網站發現他的圖片預覽挺不錯的,跟以前的 fancyBox 外掛效果差不多。在這裡我為大家提供一些編寫思路。

  • 記錄頁面的圖片所在位置offsetTop / offsetLeft / width /height。
  • 建立div層鋪滿整螢幕。
  • 如果是載入大圖需要顯示loading。
  • 建立白色遮罩層。
  • 複製一份圖片填充到螢幕之前記錄的位置。
  • 根據螢幕算出中心位置並動畫移動。
  • 點選關閉,返回到之前記錄的位置即可,但是這裡需要注意的是如果有滾動條則需要減去srcollTop的值,原因是動態建立的層和圖片是position:fixed屬性。
  • 滾動條滾動立即隱藏。

完整程式碼

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>圖片預覽</title>
<style>
*{
    margin:0;
    padding:0;
}
.image{
    width:100px;
}
</style>

</head>
<body>
<div style="margin:auto;width:1000px">
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
<img src="https://user-gold-cdn.xitu.io/2018/5/13/16359c7b4fffa97c?imageslim" class="image"><br>
</div>
</body>
</html>

<script>
let container = document.documentElement||document.body;
let img,div,src;
let x,y,w,h,tx,ty,tw,th,ww,wh;
let closeMove=function(){
    if(div==undefined){
        return false;
    }
    div.style.opacity=0;
    img.style.height=h+"px";
    img.style.width=w+"px";
    img.style.left=x+"px";
    img.style.top=(y - container.scrollTop)+"px";
    // 延遲移除dom
    setTimeout(function(){
        div.remove();
        img.remove();
    },100);
};

let closeFade=function(){
    if(div==undefined){
        return false;
    }
    div.style.opacity=0;
    img.style.opacity=0;
    // 延遲移除dom
    setTimeout(function(){
        div.remove();
        img.remove();
    },100);
};

// 監聽滾動關閉層
document.addEventListener("scroll",function(){
    closeFade();
});
document.querySelectorAll("img").forEach(v=>{
    v.addEventListener("click",function(e){ // 註冊事件
        // 記錄小圖的位置個大小
        x=e.target.offsetLeft;
        y=e.target.offsetTop;
        w=e.target.offsetWidth;
        h=e.target.offsetHeight;
        src=e.target.src;

        // 建立遮罩層
        div=document.createElement("div");
        div.style.cssText=`
            position:fixed;
            left:0;
            top:0;
            bottom:0;
            right:0;
            background-color:#fff;
            transition:all .3s cubic-bezier(0.165, 0.84, 0.44, 1);
            opacity:0;
        `;
        document.body.appendChild(div);
        setTimeout(function(){
            div.style.opacity=1;
        },0);
        // (此處可以加loading)

        // 建立副本
        img=new Image();
        img.src=src;
        img.style.cssText=`
            position:fixed;
            left:${x}px;
            top:${y - container.scrollTop}px;
            width:${w}px;
            height:${h}px;
            transition:all .3s cubic-bezier(0.165, 0.84, 0.44, 1);
            opacity:0;
        `;
        img.onload=function(){
            document.body.appendChild(img);
            // 瀏覽器寬高
            wh=window.innerHeight;
            ww=window.innerWidth;

            // 目標寬高和座標
            tw=w/h*wh >> 0;
            th=wh;
            tx=(ww - tw) / 2;
            ty=0;
            
            // 延遲寫入否則不會有動畫
            setTimeout(function(){
                img.style.opacity=1;
                img.style.height=wh+"px";
                img.style.width=tw+"px";
                img.style.left=tx+"px";
                img.style.top=ty+"px";
                // 點選隱藏
                div.onclick=img.onclick=closeMove;
            },0);
        };
    });//end event
});//end forEach
</script>
複製程式碼

DEMO: jinzhe.github.io/todo/image-…

原文:im.zee.kim/post/79/

相關文章