JS 自定义图片预览

自定义图片预览

// 自定义图片预览
ghImgView = function(imgurl) {
    // 防止重复弹窗
    var old = document.getElementById('gh_img_preview');
    if (old) old.remove();

    // 缩放状态
    var scale = 1;
    var minScale = 0.2;
    var maxScale = 10;

    // 遮罩层
    var overlay = document.createElement('div');
    overlay.id = 'gh_img_preview';
    overlay.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);z-index:10000;display:flex;align-items:center;justify-content:center;overflow:hidden;';

    // 关闭按钮
    var closeBtn = document.createElement('div');
    closeBtn.innerHTML = '×';
    closeBtn.style.cssText = 'position:absolute;top:15px;right:15px;width:36px;height:36px;line-height:36px;text-align:center;background:#f00;color:#fff;border-radius:50%;font-size:22px;cursor:pointer;z-index:10001;';

    // 缩放提示
    var scaleTip = document.createElement('div');
    scaleTip.style.cssText = 'position:absolute;bottom:20px;left:50%;transform:translateX(-50%);background:rgba(0,0,0,0.6);color:#fff;padding:6px 16px;border-radius:4px;font-size:14px;z-index:10001;pointer-events:none;opacity:0;transition:opacity 0.3s;';

    function showTip(text) {
        scaleTip.textContent = text;
        scaleTip.style.opacity = '1';
        clearTimeout(showTip._timer);
        showTip._timer = setTimeout(function() { scaleTip.style.opacity = '0'; }, 1000);
    }

    // 图片容器(支持拖拽)
    var imgWrap = document.createElement('div');
    imgWrap.style.cssText = 'position:relative;cursor:grab;';

    // 图片
    var img = document.createElement('img');
    img.src = imgurl;
    img.style.cssText = 'max-width:90vw;max-height:90vh;object-fit:contain;border-radius:4px;transform-origin:center center;transition:transform 0.1s ease;user-select:none;-webkit-user-drag:none;';
    img.draggable = false;

    imgWrap.appendChild(img);
    overlay.appendChild(closeBtn);
    overlay.appendChild(scaleTip);
    overlay.appendChild(imgWrap);
    document.body.appendChild(overlay);

    // 更新缩放
    function updateScale(newScale) {
        scale = Math.max(minScale, Math.min(maxScale, newScale));
        img.style.transform = 'scale(' + scale + ')';
        showTip(Math.round(scale * 100) + '%');
    }

    // 鼠标滚轮缩放
    overlay.onwheel = function(e) {
        e.preventDefault();
        var delta = e.deltaY > 0 ? -0.1 : 0.1;
        // 以鼠标位置为中心缩放
        var rect = img.getBoundingClientRect();
        var cx = e.clientX - rect.left - rect.width / 2;
        var cy = e.clientY - rect.top - rect.height / 2;
        var newScale = scale + delta * scale;
        if (newScale >= minScale && newScale <= maxScale) {
            updateScale(newScale);
        }
    };

    // 拖拽移动
    var isDragging = false;
    var startX, startY, origX, origY;

    imgWrap.onmousedown = function(e) {
        if (e.button !== 0) return;
        isDragging = true;
        startX = e.clientX;
        startY = e.clientY;
        var style = window.getComputedStyle(imgWrap);
        var matrix = new DOMMatrix(style.transform);
        origX = matrix.m41;
        origY = matrix.m42;
        imgWrap.style.cursor = 'grabbing';
        e.preventDefault();
    };

    document.onmousemove = function(e) {
        if (!isDragging) return;
        var dx = e.clientX - startX;
        var dy = e.clientY - startY;
        imgWrap.style.transform = 'translate(' + (origX + dx) + 'px,' + (origY + dy) + 'px)';
    };

    document.onmouseup = function() {
        if (isDragging) {
            isDragging = false;
            imgWrap.style.cursor = 'grab';
        }
    };

    // 双击还原
    img.ondblclick = function() {
        scale = 1;
        img.style.transform = 'scale(1)';
        imgWrap.style.transform = 'translate(0,0)';
        showTip('100%');
    };

    // 禁止背景滚动
    document.body.style.overflow = 'hidden';

    // 关闭方法
    function close() {
        overlay.remove();
        document.body.style.overflow = '';
        document.onmousemove = null;
        document.onmouseup = null;
        document.onkeydown = null;
        overlay.onwheel = null;
    }
    closeBtn.onclick = close;
    overlay.onclick = function(e) {
        if (e.target === overlay) close();
    };
    document.onkeydown = function(e) {
        if (e.key === 'Escape') { close(); }
    };
}