fix: 锁死页面双指缩放,正文原图与灯箱 pinch 放大
禁止手机/平板整页捏合缩放;帖子与单页正文直接显示原图(含外链可点开灯箱),灯箱内支持双指缩放与拖动。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,22 +2,22 @@
|
|||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
<meta name="description" content="拾三一隅,自在交流" />
|
<meta name="description" content="拾三一隅,自在交流" />
|
||||||
<title>姜十三论坛 - 拾三一隅,自在交流</title>
|
<title>姜十三论坛 - 拾三一隅,自在交流</title>
|
||||||
<style>
|
<style>
|
||||||
/* 关键布局样式:在 JS/CSS 包加载前即固定三栏结构,避免刷新时组件错位 */
|
/* 关键布局样式:在 JS/CSS 包加载前即固定三栏结构,避免刷新时组件错位 */
|
||||||
html { scrollbar-gutter: stable; }
|
html { scrollbar-gutter: stable; }
|
||||||
html, body, #root { height: 100%; margin: 0; }
|
html, body, #root { height: 100%; margin: 0; touch-action: pan-x pan-y; }
|
||||||
body { overflow: hidden; font-size: 14px; line-height: 1.5; }
|
body { overflow: hidden; font-size: 14px; line-height: 1.5; }
|
||||||
.app-shell { height: 100%; max-height: 100dvh; display: flex; flex-direction: column; overflow: hidden; }
|
.app-shell { height: 100%; max-height: 100dvh; display: flex; flex-direction: column; overflow: hidden; touch-action: pan-x pan-y; }
|
||||||
.app-frame { flex: 1; min-height: 0; height: 100%; max-width: 1400px; width: 100%; margin: 0 auto; display: flex; flex-direction: column; overflow: hidden; }
|
.app-frame { flex: 1; min-height: 0; height: 100%; max-width: 1400px; width: 100%; margin: 0 auto; display: flex; flex-direction: column; overflow: hidden; touch-action: pan-x pan-y; }
|
||||||
.app-header { height: 56px; flex-shrink: 0; }
|
.app-header { height: 56px; flex-shrink: 0; }
|
||||||
.site-footer { flex-shrink: 0; }
|
.site-footer { flex-shrink: 0; }
|
||||||
.app-body { flex: 1; display: flex; min-height: 0; width: 100%; overflow: hidden; }
|
.app-body { flex: 1; display: flex; min-height: 0; width: 100%; overflow: hidden; touch-action: pan-x pan-y; }
|
||||||
.content-workspace { flex: 1; display: flex; min-width: 0; min-height: 0; overflow: hidden; }
|
.content-workspace { flex: 1; display: flex; min-width: 0; min-height: 0; overflow: hidden; touch-action: pan-x pan-y; }
|
||||||
.sidebar { width: 210px; flex-shrink: 0; }
|
.sidebar { width: 210px; flex-shrink: 0; }
|
||||||
.main-content { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
|
.main-content { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden; touch-action: pan-x pan-y; }
|
||||||
.aside-panel { width: 280px; flex-shrink: 0; }
|
.aside-panel { width: 280px; flex-shrink: 0; }
|
||||||
@media (max-width: 1100px) { .aside-panel { display: none; } }
|
@media (max-width: 1100px) { .aside-panel { display: none; } }
|
||||||
@media (max-width: 768px) { .sidebar { display: none; } }
|
@media (max-width: 768px) { .sidebar { display: none; } }
|
||||||
@@ -29,6 +29,33 @@
|
|||||||
document.documentElement.style.colorScheme = theme;
|
document.documentElement.style.colorScheme = theme;
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
<script>
|
||||||
|
/* 锁死手机/平板双指与手势缩放;头像裁剪 / 图片灯箱放行 pinch */
|
||||||
|
(function () {
|
||||||
|
function inZoomAllowArea(target) {
|
||||||
|
return !!(
|
||||||
|
target &&
|
||||||
|
target.closest &&
|
||||||
|
target.closest('.avatar-crop-stage, .image-lightbox')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
function blockGesture(e) {
|
||||||
|
if (inZoomAllowArea(e.target)) return;
|
||||||
|
if (e.cancelable) e.preventDefault();
|
||||||
|
}
|
||||||
|
function blockMultiTouch(e) {
|
||||||
|
if (e.touches && e.touches.length > 1) {
|
||||||
|
if (inZoomAllowArea(e.target)) return;
|
||||||
|
if (e.cancelable) e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.addEventListener('gesturestart', blockGesture, { passive: false });
|
||||||
|
document.addEventListener('gesturechange', blockGesture, { passive: false });
|
||||||
|
document.addEventListener('gestureend', blockGesture, { passive: false });
|
||||||
|
document.addEventListener('touchstart', blockMultiTouch, { passive: false });
|
||||||
|
document.addEventListener('touchmove', blockMultiTouch, { passive: false });
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { X } from 'lucide-react';
|
import { X } from 'lucide-react';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
|
|
||||||
@@ -9,8 +9,72 @@ interface Props {
|
|||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 帖子正文图片灯箱:展示原图,点击遮罩 / Esc / 关闭按钮退出 */
|
const MIN_SCALE = 1;
|
||||||
|
const MAX_SCALE = 4;
|
||||||
|
|
||||||
|
function touchDistance(a: Touch, b: Touch) {
|
||||||
|
const dx = a.clientX - b.clientX;
|
||||||
|
const dy = a.clientY - b.clientY;
|
||||||
|
return Math.hypot(dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
function touchMidpoint(a: Touch, b: Touch) {
|
||||||
|
return {
|
||||||
|
x: (a.clientX + b.clientX) / 2,
|
||||||
|
y: (a.clientY + b.clientY) / 2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function clampScale(s: number) {
|
||||||
|
return Math.min(MAX_SCALE, Math.max(MIN_SCALE, s));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 帖子正文图片灯箱:展示原图,支持双指缩放 / 拖动,点击遮罩 / Esc / 关闭按钮退出 */
|
||||||
export default function ImageLightbox({ src, alt = '', open, onClose }: Props) {
|
export default function ImageLightbox({ src, alt = '', open, onClose }: Props) {
|
||||||
|
const [scale, setScale] = useState(1);
|
||||||
|
const [tx, setTx] = useState(0);
|
||||||
|
const [ty, setTy] = useState(0);
|
||||||
|
const [settling, setSettling] = useState(false);
|
||||||
|
|
||||||
|
const scaleRef = useRef(1);
|
||||||
|
const txRef = useRef(0);
|
||||||
|
const tyRef = useRef(0);
|
||||||
|
const pinchRef = useRef<{
|
||||||
|
startDist: number;
|
||||||
|
startScale: number;
|
||||||
|
startTx: number;
|
||||||
|
startTy: number;
|
||||||
|
midX: number;
|
||||||
|
midY: number;
|
||||||
|
} | null>(null);
|
||||||
|
const panRef = useRef<{
|
||||||
|
startX: number;
|
||||||
|
startY: number;
|
||||||
|
startTx: number;
|
||||||
|
startTy: number;
|
||||||
|
} | null>(null);
|
||||||
|
const stageRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const applyTransform = useCallback((nextScale: number, nextTx: number, nextTy: number) => {
|
||||||
|
scaleRef.current = nextScale;
|
||||||
|
txRef.current = nextTx;
|
||||||
|
tyRef.current = nextTy;
|
||||||
|
setScale(nextScale);
|
||||||
|
setTx(nextTx);
|
||||||
|
setTy(nextTy);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const resetTransform = useCallback((animate = false) => {
|
||||||
|
if (animate) setSettling(true);
|
||||||
|
applyTransform(1, 0, 0);
|
||||||
|
}, [applyTransform]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) return;
|
||||||
|
resetTransform(false);
|
||||||
|
setSettling(false);
|
||||||
|
}, [open, src, resetTransform]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open) return;
|
if (!open) return;
|
||||||
const onKey = (e: KeyboardEvent) => {
|
const onKey = (e: KeyboardEvent) => {
|
||||||
@@ -25,6 +89,111 @@ export default function ImageLightbox({ src, alt = '', open, onClose }: Props) {
|
|||||||
};
|
};
|
||||||
}, [open, onClose]);
|
}, [open, onClose]);
|
||||||
|
|
||||||
|
// 原生非 passive 监听,才能在 pinch/pan 时 preventDefault
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) return;
|
||||||
|
const el = stageRef.current;
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
const onTouchStart = (e: TouchEvent) => {
|
||||||
|
setSettling(false);
|
||||||
|
if (e.touches.length === 2) {
|
||||||
|
const a = e.touches[0];
|
||||||
|
const b = e.touches[1];
|
||||||
|
const mid = touchMidpoint(a, b);
|
||||||
|
pinchRef.current = {
|
||||||
|
startDist: touchDistance(a, b) || 1,
|
||||||
|
startScale: scaleRef.current,
|
||||||
|
startTx: txRef.current,
|
||||||
|
startTy: tyRef.current,
|
||||||
|
midX: mid.x,
|
||||||
|
midY: mid.y,
|
||||||
|
};
|
||||||
|
panRef.current = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.touches.length === 1 && scaleRef.current > 1.01) {
|
||||||
|
panRef.current = {
|
||||||
|
startX: e.touches[0].clientX,
|
||||||
|
startY: e.touches[0].clientY,
|
||||||
|
startTx: txRef.current,
|
||||||
|
startTy: tyRef.current,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onTouchMove = (e: TouchEvent) => {
|
||||||
|
if (e.touches.length === 2 && pinchRef.current) {
|
||||||
|
if (e.cancelable) e.preventDefault();
|
||||||
|
const a = e.touches[0];
|
||||||
|
const b = e.touches[1];
|
||||||
|
const dist = touchDistance(a, b) || 1;
|
||||||
|
const nextScale = clampScale(
|
||||||
|
pinchRef.current.startScale * (dist / pinchRef.current.startDist),
|
||||||
|
);
|
||||||
|
const mid = touchMidpoint(a, b);
|
||||||
|
applyTransform(
|
||||||
|
nextScale,
|
||||||
|
pinchRef.current.startTx + (mid.x - pinchRef.current.midX),
|
||||||
|
pinchRef.current.startTy + (mid.y - pinchRef.current.midY),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.touches.length === 1 && panRef.current && scaleRef.current > 1.01) {
|
||||||
|
if (e.cancelable) e.preventDefault();
|
||||||
|
const dx = e.touches[0].clientX - panRef.current.startX;
|
||||||
|
const dy = e.touches[0].clientY - panRef.current.startY;
|
||||||
|
applyTransform(
|
||||||
|
scaleRef.current,
|
||||||
|
panRef.current.startTx + dx,
|
||||||
|
panRef.current.startTy + dy,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onTouchEnd = (e: TouchEvent) => {
|
||||||
|
if (e.touches.length < 2) pinchRef.current = null;
|
||||||
|
if (e.touches.length === 0) {
|
||||||
|
panRef.current = null;
|
||||||
|
if (scaleRef.current <= 1.05) resetTransform(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onWheel = (e: WheelEvent) => {
|
||||||
|
if (!(e.ctrlKey || e.metaKey)) return;
|
||||||
|
e.preventDefault();
|
||||||
|
setSettling(false);
|
||||||
|
const delta = -e.deltaY * 0.01;
|
||||||
|
const next = clampScale(scaleRef.current * (1 + delta));
|
||||||
|
if (next <= 1.01) {
|
||||||
|
resetTransform(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
applyTransform(next, txRef.current, tyRef.current);
|
||||||
|
};
|
||||||
|
|
||||||
|
el.addEventListener('touchstart', onTouchStart, { passive: false });
|
||||||
|
el.addEventListener('touchmove', onTouchMove, { passive: false });
|
||||||
|
el.addEventListener('touchend', onTouchEnd);
|
||||||
|
el.addEventListener('touchcancel', onTouchEnd);
|
||||||
|
el.addEventListener('wheel', onWheel, { passive: false });
|
||||||
|
return () => {
|
||||||
|
el.removeEventListener('touchstart', onTouchStart);
|
||||||
|
el.removeEventListener('touchmove', onTouchMove);
|
||||||
|
el.removeEventListener('touchend', onTouchEnd);
|
||||||
|
el.removeEventListener('touchcancel', onTouchEnd);
|
||||||
|
el.removeEventListener('wheel', onWheel);
|
||||||
|
};
|
||||||
|
}, [open, applyTransform, resetTransform]);
|
||||||
|
|
||||||
|
const handleBackdropClick = useCallback(() => {
|
||||||
|
if (scaleRef.current > 1.01) {
|
||||||
|
resetTransform(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onClose();
|
||||||
|
}, [onClose, resetTransform]);
|
||||||
|
|
||||||
if (!open || !src) return null;
|
if (!open || !src) return null;
|
||||||
|
|
||||||
return createPortal(
|
return createPortal(
|
||||||
@@ -33,7 +202,7 @@ export default function ImageLightbox({ src, alt = '', open, onClose }: Props) {
|
|||||||
type="button"
|
type="button"
|
||||||
className="image-lightbox-backdrop"
|
className="image-lightbox-backdrop"
|
||||||
aria-label="关闭"
|
aria-label="关闭"
|
||||||
onClick={onClose}
|
onClick={handleBackdropClick}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -43,15 +212,20 @@ export default function ImageLightbox({ src, alt = '', open, onClose }: Props) {
|
|||||||
>
|
>
|
||||||
<X size={20} aria-hidden />
|
<X size={20} aria-hidden />
|
||||||
</button>
|
</button>
|
||||||
<div className="image-lightbox-stage">
|
<div ref={stageRef} className="image-lightbox-stage">
|
||||||
<img
|
<img
|
||||||
src={src}
|
src={src}
|
||||||
alt={alt || '原图'}
|
alt={alt || '原图'}
|
||||||
className="image-lightbox-img"
|
className={`image-lightbox-img${settling ? ' image-lightbox-img--settling' : ''}`}
|
||||||
decoding="async"
|
decoding="async"
|
||||||
|
draggable={false}
|
||||||
|
style={{ transform: `translate3d(${tx}px, ${ty}px, 0) scale(${scale})` }}
|
||||||
|
onTransitionEnd={() => setSettling(false)}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p className="image-lightbox-hint">点击空白处关闭</p>
|
<p className="image-lightbox-hint image-lightbox-hint--desktop">点击空白处关闭</p>
|
||||||
|
<p className="image-lightbox-hint image-lightbox-hint--mobile">双指缩放 · 点击空白关闭</p>
|
||||||
</div>,
|
</div>,
|
||||||
document.body,
|
document.body,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -162,6 +162,8 @@ html {
|
|||||||
html, body, #root {
|
html, body, #root {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
/* 允许单指平移滚动,禁止 pinch / 双击放大 */
|
||||||
|
touch-action: pan-x pan-y;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@@ -173,6 +175,20 @@ body {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 嵌套滚动壳会截断祖先 touch-action,需在壳上再次声明 */
|
||||||
|
.app-shell,
|
||||||
|
.app-frame,
|
||||||
|
.app-body,
|
||||||
|
.content-workspace,
|
||||||
|
.main-content,
|
||||||
|
.virtual-list-wrap,
|
||||||
|
.post-list-scroll,
|
||||||
|
.list-page-panel,
|
||||||
|
.article-editor-scroll,
|
||||||
|
.comment-rev-detail {
|
||||||
|
touch-action: pan-x pan-y;
|
||||||
|
}
|
||||||
|
|
||||||
a { color: var(--j13-green); text-decoration: none; }
|
a { color: var(--j13-green); text-decoration: none; }
|
||||||
a:hover { text-decoration: underline; }
|
a:hover { text-decoration: underline; }
|
||||||
|
|
||||||
@@ -5531,16 +5547,22 @@ a.post-title:visited {
|
|||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-detail-content img.post-content-img--zoomable {
|
.post-detail-content img.post-content-img--zoomable,
|
||||||
|
.site-page__body img.post-content-img--zoomable,
|
||||||
|
.post-body img.post-content-img--zoomable {
|
||||||
cursor: zoom-in;
|
cursor: zoom-in;
|
||||||
transition: box-shadow 0.15s, transform 0.15s;
|
transition: box-shadow 0.15s, transform 0.15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-detail-content img.post-content-img--zoomable:hover {
|
.post-detail-content img.post-content-img--zoomable:hover,
|
||||||
|
.site-page__body img.post-content-img--zoomable:hover,
|
||||||
|
.post-body img.post-content-img--zoomable:hover {
|
||||||
box-shadow: 0 4px 18px rgba(15, 23, 42, 0.14);
|
box-shadow: 0 4px 18px rgba(15, 23, 42, 0.14);
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-detail-content img.post-content-img--zoomable:focus-visible {
|
.post-detail-content img.post-content-img--zoomable:focus-visible,
|
||||||
|
.site-page__body img.post-content-img--zoomable:focus-visible,
|
||||||
|
.post-body img.post-content-img--zoomable:focus-visible {
|
||||||
outline: 2px solid var(--j13-green);
|
outline: 2px solid var(--j13-green);
|
||||||
outline-offset: 3px;
|
outline-offset: 3px;
|
||||||
}
|
}
|
||||||
@@ -5596,6 +5618,9 @@ a.post-title:visited {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
/* 由组件接管 pinch / pan,禁止浏览器默认手势 */
|
||||||
|
touch-action: none;
|
||||||
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-lightbox-img {
|
.image-lightbox-img {
|
||||||
@@ -5607,6 +5632,14 @@ a.post-title:visited {
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45);
|
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
-webkit-user-drag: none;
|
||||||
|
touch-action: none;
|
||||||
|
transform-origin: center center;
|
||||||
|
will-change: transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-lightbox-img--settling {
|
||||||
|
transition: transform 0.18s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-lightbox-hint {
|
.image-lightbox-hint {
|
||||||
@@ -5621,14 +5654,22 @@ a.post-title:visited {
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image-lightbox-hint--mobile {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.image-lightbox {
|
.image-lightbox {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-lightbox-hint {
|
.image-lightbox-hint--desktop {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image-lightbox-hint--mobile {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-detail-content p { margin: 0 0 1em; }
|
.post-detail-content p { margin: 0 0 1em; }
|
||||||
@@ -8613,6 +8654,8 @@ button.profile-stat:hover strong {
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #111;
|
background: #111;
|
||||||
|
/* 放行 pinch,供 react-easy-crop 缩放 */
|
||||||
|
touch-action: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar-crop-loading {
|
.avatar-crop-loading {
|
||||||
|
|||||||
@@ -202,18 +202,17 @@ export function renderPostContentHtml(
|
|||||||
if (!img.getAttribute('loading')) img.setAttribute('loading', 'lazy');
|
if (!img.getAttribute('loading')) img.setAttribute('loading', 'lazy');
|
||||||
if (!img.getAttribute('decoding')) img.setAttribute('decoding', 'async');
|
if (!img.getAttribute('decoding')) img.setAttribute('decoding', 'async');
|
||||||
|
|
||||||
const rawSrc = img.getAttribute('src') || '';
|
const rawSrc = (img.getAttribute('src') || '').trim();
|
||||||
const full = img.getAttribute('data-full') || rawSrc;
|
const full = (img.getAttribute('data-full') || rawSrc).trim();
|
||||||
const thumb = toPostImageThumbSrc(full) || toPostImageThumbSrc(rawSrc);
|
// 表情贴纸保持行内展示,不进灯箱;本地上传图与外链图均可点击查看
|
||||||
if (thumb && full) {
|
if (!full || full.startsWith('data:') || full.startsWith('blob:')) return;
|
||||||
// 正文加载缩略图,点击灯箱用原图
|
if (rawSrc.includes('/stickers/') || full.includes('/stickers/')) return;
|
||||||
if (!img.getAttribute('data-full')) img.setAttribute('data-full', full);
|
|
||||||
if (rawSrc !== thumb) img.setAttribute('src', thumb);
|
if (!img.getAttribute('data-full')) img.setAttribute('data-full', full);
|
||||||
img.classList.add('post-content-img--zoomable');
|
img.classList.add('post-content-img--zoomable');
|
||||||
img.setAttribute('role', 'button');
|
img.setAttribute('role', 'button');
|
||||||
img.setAttribute('tabindex', '0');
|
img.setAttribute('tabindex', '0');
|
||||||
img.setAttribute('title', img.getAttribute('title') || '点击查看原图');
|
img.setAttribute('title', img.getAttribute('title') || '点击查看原图');
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 规范化图组 class,保证阅读态宫格样式生效
|
// 规范化图组 class,保证阅读态宫格样式生效
|
||||||
|
|||||||
Reference in New Issue
Block a user