PageSourceSearch

https://www.hotel-kawakyu.jp/wp-content/themes/lm-child/js/pages/kawakyu-top/heritage.js?ver=1789655968

js hotel-kawakyu.jp collected 2026-09-30 15:51:21 UTC 3,474 bytes, 70 lines download raw bytes

1(() => {
2    'use strict';
3
4    const root = document.querySelector('.kw-heritage');
5    const gsap = window.gsap;
6    const ScrollTrigger = window.ScrollTrigger;
7    if (!root || !gsap || !ScrollTrigger) return;
8
9    const frame = root.querySelector('.kw-heritage__frame');
10    const topLine = root.querySelector('.js-heritage-line-top');
11    const bottomLine = root.querySelector('.js-heritage-line-bottom');
12    const label = root.querySelector('.kw-heritage__label');
13    const image = frame.querySelector('img');
14    const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
15    const scrollLength = reduceMotion ? 1.2 : 3.6;
16
17    const measure = () => {
18        const viewportWidth = window.innerWidth;
19        const viewportHeight = window.innerHeight;
20        const imageRatio = image.naturalWidth && image.naturalHeight
21            ? image.naturalWidth / image.naturalHeight
22            : 1400 / 780;
23        // SPは画像本来の横長比率ではなく、2:3の縦長フレームで切り抜く。
24        // 拡大中も同じフレーム比率を保つため、計測値自体を切り替える。
25        const frameRatio = viewportWidth <= 768 ? 2 / 3 : imageRatio;
26        const baseHeight = viewportWidth / frameRatio;
27        const endScale = Math.max(1, viewportHeight / baseHeight);
28        const lineHeight = parseFloat(window.getComputedStyle(topLine).fontSize) * 0.5;
29        const startScale = lineHeight / baseHeight;
30        frame.style.width = `${viewportWidth}px`;
31        frame.style.height = `${baseHeight}px`;
32        return { baseHeight, endScale, startScale, lineHeight };
33    };
34
35    const render = (progress) => {
36        const { baseHeight, endScale, startScale, lineHeight } = measure();
37        const clamp = (value, start, end) => Math.min(1, Math.max(0, (value - start) / (end - start)));
38        const zoomProgress = gsap.parseEase('power2.inOut')(clamp(progress, 0.10, 0.68));
39        const scale = startScale * Math.pow(endScale / startScale, zoomProgress);
40        const imageHeight = baseHeight * scale;
41        // 画像が拡大する間も、上下コピーとの間に常時20pxの呼吸を残す。
42        const offset = Math.max(0, (imageHeight - lineHeight) / 2) + 20;
43        const lineOpacity = 1 - clamp(progress, 0.50, 0.66);
44        const labelOpacity = clamp(progress, 0.72, 0.85);
45
46        frame.style.transform = `translate(-50%, -50%) scale(${scale})`;
47        frame.style.opacity = String(clamp(progress, 0.10, 0.21));
48        topLine.style.transform = `translateY(${-offset}px)`;
49        bottomLine.style.transform = `translateY(${offset}px)`;
50        topLine.style.opacity = String(lineOpacity);
51        bottomLine.style.opacity = String(lineOpacity);
52        label.style.opacity = String(labelOpacity);
53        label.style.transform = `translateY(${(1 - labelOpacity) * 14}px)`;
54    };
55
56    root.style.height = `${(scrollLength + 1) * 100}svh`;
57    const trigger = ScrollTrigger.create({
58        trigger: root,
59        start: 'top top',
60        end: () => `+=${window.innerHeight * scrollLength}`,
61        scrub: reduceMotion ? true : 0.6,
62        invalidateOnRefresh: true,
63        onUpdate: (self) => render(self.progress),
64        onRefresh: (self) => render(self.progress),
65    });
66
67    image.addEventListener('load', () => ScrollTrigger.refresh(), { once: true });
68    window.addEventListener('resize', () => ScrollTrigger.refresh(), { passive: true });
69    render(0);
70})();

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.