PageSourceSearch

https://yokohama-sakae-kurasi.jp/js/switchtriple.js

js yokohama-sakae-kurasi.jp collected 2026-10-08 08:10:06 UTC 5,148 bytes, 157 lines download raw bytes

1/**
2 * 画像3枚の切り替え
3 *
4 * @author ao-system, Inc.
5 * @date 2024-12-18
6 */
7(() => {
8	'use strict';
9	class SwitchTriple {
10		//constant
11		#stage			= document.querySelector('section.switchtriple');
12		#figures		= [
13			document.querySelector('section.switchtriple > div > figure:nth-of-type(1)'),
14			document.querySelector('section.switchtriple > div > figure:nth-of-type(2)'),
15			document.querySelector('section.switchtriple > div > figure:nth-of-type(3)'),
16		];
17		#images					= [new Image(), new Image(), new Image()];
18		#imageChangeInterval	= 7000;	//画像と画像の時間間隔
19		#slideTime				= 800;	//フェードアウト、フェードイン時間
20		#slideTimeDelay			= 300;	//3枚の画像のタイムラグ
21		#slideWidth				= 20;	//スライド幅
22		#swipeShreshold			= 50;	//スワイプ判定幅
23		//variable
24		#imagePaths				= [];		//処理する画像
25		#imageIndex				= 0;		//imagePathsのインデックス
26		#isBusy					= false;	//動作中
27		#loopTimeoutId			= null;		//setTimeoutのタイマー
28		#swipeStartX			= 0;		//スワイプ開始位置
29		#isSwiping				= false;	//スワイプ中
30		#slideDirection			= 1;		//1|-1	正方向,逆方向
31		//
32		constructor(imagePaths) {
33			this.#imagePaths = imagePaths;
34			this.#init();
35		}
36		#init() {
37			for (let i = 0; i < 3; i++) {
38				this.#figures[i].appendChild(this.#images[i]);
39				this.#images[i].src = this.#imagePaths[0][i];
40				this.#images[i].setAttribute('draggable','false');
41			}
42			this.#initSwipe();
43			this.#autoSlide();
44		}
45		#initSwipe() {
46			this.#stage.addEventListener('click', (e) => { e.preventDefault();});
47			this.#stage.addEventListener('mousedown', (e) => { this.#swipeStart(e.clientX); });
48			this.#stage.addEventListener('mouseup', (e) => { this.#swipeEnd(e.target, e.clientX); });
49			this.#stage.addEventListener('touchstart', (e) => { this.#swipeStart(e.touches[0].clientX); });
50			this.#stage.addEventListener('touchend', (e) => { this.#swipeEnd(e.target, e.changedTouches[0].clientX); });
51		}
52		#swipeStart(positionX) {
53			if (this.#isBusy) {
54				return;
55			}
56			this.#swipeStartX = positionX;
57			this.#stage.style.cursor = 'grabbing';
58			this.#isSwiping = true;
59		}
60		#swipeEnd(targetElm,positionX) {
61			if (this.#isSwiping == false) {
62				return;
63			}
64			if (this.#swipeStartX - positionX > this.#swipeShreshold) {
65				this.#slideAction(this.#withinRange(this.#imageIndex + 1));
66			} else if (this.#swipeStartX - positionX < -this.#swipeShreshold) {
67				this.#slideDirection = -1;
68				this.#slideAction(this.#withinRange(this.#imageIndex - 1));
69			}
70			this.#stage.style.cursor = '';
71			this.#isSwiping = false;
72		}
73		#slideForward() {
74			if (this.#isBusy) {
75				return;
76			}
77			this.#isBusy = true;
78			const promises = [null,null,null];
79			for (let i = 0; i < 3; i++) {
80				promises[i] = this.#imageFadeOut(i);
81			}
82			Promise.all(promises).then(() => {
83				this.#slideForward02();
84			});
85		}
86		#imageFadeOut(num) {
87			return new Promise((resolve) => {
88				this.#images[num].animate(
89					[
90						{opacity: 1, transform: 'translateX(0px)'},
91						{opacity: 0, transform: `translateX(${this.#slideWidth}px)`},
92					],
93					{delay:this.#slideTimeDelay * num, duration:this.#slideTime, fill:'forwards', easing: 'ease-in'}
94				).finished.then(() => {
95					this.#images[num].src = this.#imagePaths[this.#imageIndex][num];
96					this.#images[num].onload = () => {
97						resolve();
98					}
99				});
100			});
101		}
102		#imageFadeIn(num) {
103			return new Promise((resolve) => {
104				this.#images[num].animate(
105					[
106						{opacity: 0},
107						{opacity: 1},
108					],
109					{delay:this.#slideTimeDelay * num, duration:this.#slideTime, fill:'forwards'}
110				);
111				this.#images[num].animate(
112					[
113						{transform: `translateX(${this.#slideWidth}px)`},
114						{transform: 'translateX(0px)'},
115					],
116					{delay:this.#slideTimeDelay * num, duration:this.#slideTime, fill:'forwards', easing: 'ease-out'}
117				).finished.then(() => {
118					this.#images[num].src = this.#imagePaths[this.#imageIndex][num];
119					this.#images[num].onload = () => {
120						resolve();
121					}
122				});
123			});
124		}
125		#slideForward02() {
126			const promises = [null,null,null];
127			for (let i = 0; i < 3; i++) {
128				promises[i] = this.#imageFadeIn(i);
129			}
130			Promise.all(promises).then(() => {
131				this.#slideDirection = 1;
132				this.#isBusy = false;
133			});
134		}
135		#autoSlide() {
136			this.#loopTimeoutId = setTimeout(() => {
137				this.#slideAction();
138			}, this.#imageChangeInterval - this.#slideTime);
139		}
140		#slideAction(num = this.#imageIndex + 1) {
141			clearTimeout(this.#loopTimeoutId);
142			this.#imageIndex = this.#withinRange(num);
143			this.#slideForward();
144			this.#autoSlide();
145		}
146		#withinRange(nextNumber) {
147			const num = (nextNumber >= 0) ? nextNumber : this.#imagePaths.length - 1;
148			return num % this.#imagePaths.length;
149		}
150	}
151	new SwitchTriple([
152		['./image/triple01a.webp',	'./image/triple01b.webp',	'./image/triple01c.webp'	],
153		['./image/triple02a.webp',	'./image/triple02b.webp',	'./image/triple02c.webp'	],
154		['./image/triple03a.webp',	'./image/triple03b.webp',	'./image/triple03c.webp'	],
155		['./image/triple04a.webp',	'./image/triple04b.webp',	'./image/triple04c.webp'	],
156	]);
157})();

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.