From e931ea8f4facebde9937e007e0daa2d71ecc7319 Mon Sep 17 00:00:00 2001 From: XPoet Date: Sat, 8 Oct 2022 20:56:08 +0800 Subject: [PATCH] perf(post): optimize zoom in image function (#148) --- layout/_partial/image-viewer.ejs | 4 +- scripts/filters/lazyload-handle.js | 6 +- source/css/common/basic.styl | 4 +- source/css/common/markdown.styl | 7 +- source/css/common/variables.styl | 1 + source/css/layout/_partial/image-viewer.styl | 29 +++---- source/js/utils.js | 80 ++++++++++++++------ 7 files changed, 83 insertions(+), 48 deletions(-) diff --git a/layout/_partial/image-viewer.ejs b/layout/_partial/image-viewer.ejs index 2573efe..6c1c154 100644 --- a/layout/_partial/image-viewer.ejs +++ b/layout/_partial/image-viewer.ejs @@ -1,3 +1,3 @@ -
- +
+
diff --git a/scripts/filters/lazyload-handle.js b/scripts/filters/lazyload-handle.js index 985ef98..ea3abe1 100644 --- a/scripts/filters/lazyload-handle.js +++ b/scripts/filters/lazyload-handle.js @@ -13,7 +13,11 @@ hexo.extend.filter.register( function (match, attrBegin, src, attrEnd) { let hasAlt = false if (!src) return match - ;[attrBegin, attrEnd].forEach(x => { if (x.includes('alt="')) { hasAlt = true } }) + if (attrBegin.includes('alt="')) { + hasAlt = true + } else if (attrBegin.includes('alt="')) { + hasAlt = true + } return ` { } }, - // big image viewer - imageViewer() { - let isBigImage = false + // zoom in image + zoomInImage() { + const SIDE_GAP = 30 + let isZoomIn = false + let selectedImgDom = null + const imgDomList = document.querySelectorAll('.markdown-body img') + const zoomInImgMask = document.querySelector('.zoom-in-image-mask') + const zoomInImg = zoomInImgMask.querySelector('.zoom-in-image') - const showHandle = (maskDom, isShow) => { - document.body.style.overflow = isShow ? 'hidden' : 'auto' - if (isShow) { - maskDom.classList.add('active') - } else { - maskDom.classList.remove('active') + const zoomOut = () => { + if (isZoomIn) { + isZoomIn = false + zoomInImg && (zoomInImg.style.transform = `scale(1)`) + zoomInImgMask && zoomInImgMask.classList.remove('show') + const timer = setTimeout(() => { + clearTimeout(timer) + selectedImgDom && selectedImgDom.classList.remove('hide') + }, 300) } } - const imageViewerDom = document.querySelector('.image-viewer-container') - const targetImg = document.querySelector('.image-viewer-container img') - imageViewerDom && - imageViewerDom.addEventListener('click', () => { - isBigImage = false - showHandle(imageViewerDom, isBigImage) + const zoomOutHandle = () => { + zoomInImgMask && + zoomInImgMask.addEventListener('click', () => { + zoomOut() + }) + + document.addEventListener('scroll', () => { + zoomOut() }) + } - const imgDoms = document.querySelectorAll('.markdown-body img') - - if (imgDoms.length) { - imgDoms.forEach((img) => { + if (imgDomList.length) { + zoomOutHandle() + imgDomList.forEach((img) => { img.addEventListener('click', () => { - isBigImage = true - showHandle(imageViewerDom, isBigImage) - targetImg.setAttribute('src', img.getAttribute('src')) + isZoomIn = !isZoomIn + zoomInImg.setAttribute('src', img.getAttribute('src')) + selectedImgDom = img + if (isZoomIn) { + const imgRect = selectedImgDom.getBoundingClientRect() + const imgW = imgRect.width + const imgH = imgRect.height + const imgL = imgRect.left + const imgT = imgRect.top + const winW = document.body.offsetWidth - SIDE_GAP * 2 + const winH = document.body.offsetHeight - SIDE_GAP * 2 + const scaleX = winW / imgW + const scaleY = winH / imgH + const scale = (scaleX < scaleY ? scaleX : scaleY) || 1 + const translateX = winW / 2 - (imgRect.x + imgW / 2) + SIDE_GAP + const translateY = winH / 2 - (imgRect.y + imgH / 2) + SIDE_GAP + + selectedImgDom.classList.add('hide') + zoomInImgMask.classList.add('show') + zoomInImg.style.top = imgT + 'px' + zoomInImg.style.left = imgL + 'px' + zoomInImg.style.width = imgW + 'px' + zoomInImg.style.height = imgH + 'px' + zoomInImg.style.transform = `translateX(${translateX}px) translateY(${translateY}px) scale(${scale}) ` + } }) }) - } else { - this.pageContainer_dom.removeChild(imageViewerDom) } }, @@ -441,7 +471,7 @@ KEEP.initUtils = () => { KEEP.utils.initFirstScreenHeight() // big image viewer handle - KEEP.utils.imageViewer() + KEEP.utils.zoomInImage() // set how long age in home article block KEEP.utils.setHowLongAgoInHome()