PageSourceSearch

https://ttquk.netlify.app/js/kira-image.js

js ttquk.netlify.app collected 2026-10-03 11:32:54 UTC 5,875 bytes, 178 lines download raw bytes

1window.addEventListener('load', () => {
2	// 定义阻止默认事件函数
3	const preventDefault = (ev) => {
4		ev.preventDefault();
5	};
6
7	/**
8	 * 1. 先获取需要展示的 img DOM
9	 */
10	const articleImageDoms = Array.from(
11		document.querySelectorAll(
12			'div.kira-content > div.kira-main-content article img:not(.disabled-kira-image)'
13		)
14	);
15
16	const modal = document.querySelector('.kira-image > .kira-image-modal');
17	const nowImage = modal.querySelector('.kira-image-now > img');
18	const prevImage = modal.querySelector('.kira-image-prev > img');
19	const nextImage = modal.querySelector('.kira-image-next > img');
20	const zoomButton = modal.querySelector(
21		'.kira-image-header > .kira-image-operation > #kira-image-operation-button-zoom'
22	);
23
24	const zoomIn = () => {
25		nowImage.classList.add('zoom');
26		zoomButton.querySelector('i').classList.remove('icon-zoom-in');
27		zoomButton.querySelector('i').classList.add('icon-zoom-out');
28	};
29	const zoomOut = () => {
30		nowImage.style.transform = 'translate(0px, 0px)';
31		nowImage.classList.remove('zoom');
32		zoomButton.querySelector('i').classList.remove('icon-zoom-out');
33		zoomButton.querySelector('i').classList.add('icon-zoom-in');
34	};
35
36	zoomButton.addEventListener('click', () => {
37		if (zoomButton.querySelector('i').classList.contains('icon-zoom-in')) {
38			zoomIn();
39		} else {
40			zoomOut();
41		}
42	});
43	/**
44	 * 2. 定义放大后图片拖动函数
45	 */
46	const translateRegex = new RegExp(
47		/translate\((-?\d{1,}(\.\d{1,})?)px,.*?(-?\d{1,}(\.\d{1,})?)px\)/
48	);
49	const onDragStart = (evt) => {
50		if (!nowImage.classList.contains('zoom')) return;
51		if (evt.button !== 0) return; // 仅匹配鼠标左键
52		const startTransform = nowImage.style.transform;
53		const [_0, initialX, _1, initialY, _2] = (
54			translateRegex.exec(startTransform) || new Array(5).fill(0)
55		)
56			.map(Number)
57			.map((num) => num * 2);
58		// 鼠标按下的坐标
59		const startX = evt.clientX;
60		const startY = evt.clientY;
61
62		const onDragging = (evt) => {
63			const finalX = initialX + (evt.clientX - startX);
64			const finalY = initialY + (evt.clientY - startY);
65			// 因为放大了倍数,所以移动时需要除以相应的倍数
66			nowImage.style.transform = `translate(${finalX / 2}px, ${finalY / 2}px)`;
67		};
68		const onDragEnd = () => {
69			nowImage.removeEventListener('mousemove', onDragging);
70			nowImage.removeEventListener('mouseup', onDragEnd);
71		};
72
73		nowImage.addEventListener('mouseup', onDragEnd);
74		nowImage.addEventListener('mousemove', onDragging);
75	};
76	nowImage.addEventListener('mousedown', onDragStart);
77	nowImage.addEventListener('click', zoomIn);
78	/**
79	 * 3. 声明图片地址缓存
80	 */
81	let nowImageIndex = undefined;
82	const imgProps = [];
83	/**
84	 * 4. 定义替换图片函数
85	 */
86	const setImageProp = () => {
87		const index = nowImageIndex;
88		const { src: prevSrc } = index === 0 ? imgProps[imgProps.length - 1] : imgProps[index - 1];
89		const { src: nowSrc, alt: nowAlt } = imgProps[index];
90		const { src: nextSrc } = index === imgProps.length - 1 ? imgProps[0] : imgProps[index + 1];
91
92		prevImage.setAttribute('src', prevSrc);
93		nowImage.setAttribute('src', nowSrc);
94		nextImage.setAttribute('src', nextSrc);
95
96		modal.querySelector('.kira-image-header > .kira-image-counter').innerText = `${index + 1} / ${
97			imgProps.length
98		}`;
99		modal.querySelector('.kira-image-header > .kira-image-title').innerText = `${nowAlt || ''}`;
100	};
101	/**
102	 * 5. 定义关闭模态屏事件
103	 */
104	const onVisibleModalClick = (evt) => {
105		if (evt.target !== modal) return;
106		onClose();
107	};
108	const onClose = () => {
109		modal.classList.remove('visible');
110		// 恢复页面滚动
111		modal.removeEventListener('mousewheel', preventDefault);
112		modal.removeEventListener('touchmove', preventDefault);
113		modal.removeEventListener('click', onVisibleModalClick);
114	};
115	modal
116		.querySelector(
117			'.kira-image-header > .kira-image-operation > #kira-image-operation-button-close'
118		)
119		.addEventListener('click', onClose);
120	/**
121	 * 6. 定义点击事件
122	 */
123	const onKiraImagesClick = (index) => {
124		nowImageIndex = index;
125		zoomOut();
126		setImageProp();
127		modal.classList.add('visible');
128		modal.addEventListener('click', onVisibleModalClick);
129		// 阻止页面滚动
130		modal.addEventListener('mousewheel', preventDefault, { passive: false });
131		// 阻止移动端页面滚动
132		modal.addEventListener('touchmove', preventDefault, { passive: false });
133	};
134	/**
135	 * 7. 定义切换图片函数
136	 */
137	let switchingImage = false;
138	const switchImage = (prevOrNext) => {
139		if (switchingImage) return;
140		switchingImage = true;
141		const imgListDom = document.querySelector('.kira-image .kira-image-modal .kira-image-list');
142		zoomOut();
143		setTimeout(() => {
144			imgListDom.style.animationName = '';
145			if (prevOrNext === 'prev') {
146				nowImageIndex = nowImageIndex === 0 ? imgProps.length - 1 : nowImageIndex - 1;
147			} else {
148				nowImageIndex = nowImageIndex === imgProps.length - 1 ? 0 : nowImageIndex + 1;
149			}
150			setImageProp();
151			switchingImage = false;
152		}, 200);
153		imgListDom.style.animationName = `kira-image-to-${prevOrNext}`;
154	};
155	/**
156	 * 8. 绑定切换图片函数
157	 */
158	const prevButton = document.querySelector(
159		'.kira-main-content > .kira-image div.kira-image-container > div.kira-image-prev-button-panel > div'
160	);
161	const nextButton = document.querySelector(
162		'.kira-main-content > .kira-image div.kira-image-container > div.kira-image-next-button-panel > div'
163	);
164	prevButton.addEventListener('click', () => switchImage('prev'));
165	nextButton.addEventListener('click', () => switchImage('next'));
166	/**
167	 * 9. 提取图片地址
168	 */
169	articleImageDoms.forEach((articleImageDom, index) => {
170		imgProps.push({
171			src: articleImageDom.getAttribute('data-src') || articleImageDom.getAttribute('src'),
172			alt: articleImageDom.getAttribute('alt'),
173		});
174		articleImageDom.addEventListener('click', () => {
175			onKiraImagesClick(index);
176		});
177	});
178});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.