PageSourceSearch

https://www.tsuruyagolf.co.jp/tsuruya-wp/wp-content/themes/tsuruya_v2025-10/js/top.js?1763110828

js tsuruyagolf.co.jp collected 2026-10-02 06:14:50 UTC 11,331 bytes, 381 lines download raw bytes

1/**
2 * top
3 */
4
5/**
6 * functions by top
7 */
8const TOP = {
9  // ヘッダーの高さを取得
10  headerHeight: 0,
11  // ヘッダーの高さを取得する場合のりサイズイベントタイマー
12  headerHeightTimer: false,
13  // ヘッダーの高さを取得
14  setHeaderHeight: function(){
15   TOP.headerHeight = $('.header').height();
16  },
17  // ヘッダーの高さをリサイズ時に取得
18  setResizeHeaderHeight: function(){
19    if (TOP.headerHeightTimer !== false) {
20      clearTimeout(TOP.headerHeightTimer);
21    }
22    // リサイズ終わり 0.1秒で処理 
23    TOP.headerHeightTimer = setTimeout(function(){
24      TOP.setHeaderHeight();
25    }, 100);
26  },
27
28  /**
29   * facility アニメーショントリガー処理
30   */
31  // ロード時の位置
32  facilityLoad: false,
33  // スクロールイベントの回数
34  facilityScroll: 0,
35  // スクロールを止める判定
36  facilityScrollStop: true,
37  // スクロールイベントでfacilityを超えたかどうか判定
38  facilityAnimationTrigger: function($type){  
39    if(TOP.facilityScrollStop){
40      if($type === 'load'){
41        TOP.facilityLoad = true;
42      }
43      if($type === 'scroll'){
44        TOP.facilityScroll++;
45      }
46      const facilityScrollStopLine = $('.facility-txt').offset().top - TOP.headerHeight;
47      if($(window).scrollTop() >= facilityScrollStopLine){
48        // facilityの要素を超えてリロードするとスクロールイベントがなにも触らずとも2回発生する
49        // headerの下部位置がfacility上部位置を超えた時点でスクロールイベント回数が3以上あれば画面を停止する
50        if(TOP.facilityLoad && TOP.facilityScroll > 2){
51          lenis.stop();
52          window.scroll({
53            top: facilityScrollStopLine,
54            behavior: "auto"
55          });
56        }
57        TOP.facilityAnimation();
58      }
59    }
60  },
61
62  /**
63   * facility アニメーション本体
64   * @returns 
65   */
66  facilityAnimation: function(){
67    const $facility = $('.facility');
68
69    // 一回だけ
70    if($facility.data('animated')) return;
71
72    // 一回だけのフラグ設定
73    $facility.data('animated', true);
74    let $txtBox = $facility.find('.facility-txt-box');
75    let $topList = $facility.find('#link-list .facility-top-list');
76    let $bottomList = $facility.find('#link-list .facility-bottom-list');
77
78    // フェードイン
79    $txtBox.fadeIn(0, function(){
80      // 1秒表示後に左に飛ばす
81      TOP.facilityScrollStop = false;
82      // setTimeout(function(){
83      //   $txtBox.animate({top:'12vw'}, 500);
84      // }, 1500);
85
86      // setTimeout(function(){
87      //   $txtBox.animate({left:'0'}, 500);
88      // }, 200);
89      $txtBox.animate({left:'0'}, 500);
90    });
91
92    if ($(window).width() > 767) {
93      // --- PC時の動き(従来通り) ---
94        $topList.animate({left:'0'}, 500);
95
96      setTimeout(function(){
97        $bottomList.animate({left:'0'}, 500, function(){
98          setTimeout(function(){
99            lenis.start();
100          }, 500);
101           
102        });
103      }, 100);
104
105    } else {
106      // --- SP時の動き ---
107      setTimeout(function(){
108        // アニメーションするタイミングで動かす
109        lenis.start();
110        // まず facility-top-list を順番に表示
111        let topChildren = $topList.children();
112        let bottomChildren = $bottomList.children();
113        let delay = 0;
114        let interval = 200; // 子要素ごとの間隔
115
116        topChildren.each(function(i){
117          $(this).delay(delay).animate({left: '0'}, 400);
118          delay += interval;
119        });
120
121        // top-list の最後のアニメーションが終わるタイミングで bottom-list 開始
122        let totalDelay = delay; // top-list全体の終了タイミング
123        bottomChildren.each(function(i){
124          $(this).delay(totalDelay + i * interval).animate({left: '0'}, 400);
125        });
126
127      }, 1000);
128    }
129  },
130
131  /**
132   * brand アニメーショントリガー処理
133   */
134  // ロード時の位置
135  brandLoad: false,
136  // スクロールイベントの回数
137  brandScroll: 0,
138  // スクロールを止める判定
139  brandScrollStop: true,
140  // ブランドアニメーション
141  hasAnimated: false,
142  // スクロールイベントでbrandを超えたかどうか判定
143  brandAnimationTrigger: function($type){
144    if (TOP.hasAnimated) return;
145
146    // 広がるアニメーション
147    let $img = $('.scroll-scale');
148    let $parent = $('.original-brand');
149    let scrollTop = $(window).scrollTop();
150    let windowHeight = $(window).height();
151    let parentTop = $parent.offset().top;
152    // 画面下20%に入ったタイミングで画像拡大開始
153    if (scrollTop + windowHeight > parentTop) {
154      let minWidth = 60 * parseFloat(getComputedStyle(document.documentElement).fontSize);
155      let maxWidth = $(window).width();
156      let ratio = Math.min((scrollTop + windowHeight - parentTop) / (windowHeight / 2), 1);
157      let newWidth = minWidth + (maxWidth - minWidth) * ratio;
158      $img.css('width', newWidth + 'px');
159    }
160
161    if(TOP.brandScrollStop){
162      if($type === 'load'){
163        TOP.brandLoad = true;
164      }
165      if($type === 'scroll'){
166        TOP.brandScroll++;
167      }
168      const brandScrollStopLine = $('.original-brand').offset().top - TOP.headerHeight;
169      if($(window).scrollTop() >= brandScrollStopLine){
170        // facilityの要素を超えてリロードするとスクロールイベントがなにも触らずとも2回発生する
171        // headerの下部位置がfacility上部位置を超えた時点でスクロールイベント回数が3以上あれば画面を停止する
172        if(TOP.brandLoad && TOP.brandScroll > 2){
173          lenis.stop();
174          window.scroll({
175            top: brandScrollStopLine,
176            behavior: "auto"
177          });
178        }
179        setTimeout(function(){ TOP.brandAnimation(); }, 500);
180      }
181    }
182  },
183
184  /**
185   * brand アニメーション本体
186   * @returns 
187   */
188  brandAnimation: function(){
189    if (TOP.hasAnimated) return;
190
191    let $img = $('.scroll-scale');
192    let $parent = $('.original-brand');
193    let $title = $parent.find('.brand-title');
194    let $slide = $parent.find('.brand-slide-wrap');
195
196    TOP.hasAnimated = true;
197    TOP.facilityScrollStop = false;
198
199    // 画像を固定100vw
200    $img.css('width', '100%');
201
202    // 少し間を置いてタイトルをフェードイン
203    setTimeout(function() {
204      $title.css({
205        'transition': 'opacity 1s',
206        'opacity': 1
207      });
208
209      // タイトルがフェードインした後、top位置とtransformアニメーション
210      setTimeout(function() {
211        var topValue = window.innerWidth >= 768 ? '6vw' : '25rem';
212        $title.css({
213          'transition': 'top 1s, transform 1s',
214          'top': topValue,
215          'transform': 'translate(-50%, 0)'
216        });
217      }, 500); // タイトルフェードイン完了後にアニメーション
218    }, 0); // 画像100%になった後0.5秒待機
219
220    // タイトルアニメーション終了後にスライドをゆっくりフェードイン
221    setTimeout(function() {
222      $slide.css({
223        'transition': 'opacity 2s',
224        'opacity': 1
225      });
226
227      // 全アニメーション終了後にスクロール解除
228      setTimeout(function() {
229        lenis.start();
230      }, 1000); // スライドフェードイン終了後に解除
231    }, 1000); // 0.5秒 + 1秒 + 1秒目安
232  },
233}
234
235/**
236 * window events
237 */
238$(window)
239  .on('load',function(){
240    TOP.setHeaderHeight();
241    TOP.facilityAnimationTrigger('load');
242    TOP.brandAnimationTrigger('load');
243  })
244  .on('scroll',function(){
245    TOP.facilityAnimationTrigger('scroll');
246    TOP.brandAnimationTrigger('scroll');
247  })
248  .on('resize', function(){
249    TOP.setResizeHeaderHeight();
250  });
251
252
253jQuery(function($){
254  $('.slide-category').each(function(){
255    var $parent = $(this);
256    var $img = $parent.find('img'); // 子のimgを取得
257
258    var srcWhite = $img.attr('src');
259    var srcsetWhite = $img.attr('srcset');
260
261    var srcBlack = srcWhite.replace('-white', '-black');
262    var srcsetBlack = srcsetWhite ? srcsetWhite.replace(/-white/g, '-black') : '';
263
264    $parent.hover(
265      function(){ // mouseenter
266        $img.attr('src', srcBlack);
267        if(srcsetBlack) $img.attr('srcset', srcsetBlack);
268      },
269      function(){ // mouseleave
270        $img.attr('src', srcWhite);
271        if(srcsetWhite) $img.attr('srcset', srcsetWhite);
272      }
273    );
274  });
275});
276
277
278
279$(document).ready(function() {
280    // 元の要素を取得してクローン
281    let bg_top = $('.scroll-loop.top .bg-top').clone(true);
282    let bg_bottom = $('.scroll-loop.bottom .bg-bottom').clone(true);
283    
284    // 元の要素の後ろに追加
285    $('.scroll-loop.top .bg-top').last().after(bg_top);
286    $('.scroll-loop.bottom .bg-bottom').last().after(bg_bottom);
287});
288
289
290//慣性スクロール
291const lenis = new Lenis();
292
293function raf(time) {
294  lenis.raf(time);
295  requestAnimationFrame(raf);
296}
297
298requestAnimationFrame(raf);
299
300
301
302//ONLINE SHOP タイトルアニメーション
303document.addEventListener("DOMContentLoaded", () => {
304  const sections = document.querySelectorAll(".section-ttl");
305
306  sections.forEach(section => {
307    const icon = section.querySelector("i");
308    const h2Inner = section.querySelector("h2 span.enfont") || section.querySelector("h2");
309    const p = section.querySelector("p");
310
311    // 文字を1文字ずつ<span>で包む関数
312    function wrapText(el) {
313      if (!el) return;
314      const text = el.textContent.trim();
315      el.textContent = "";
316      [...text].forEach(char => {
317        const span = document.createElement("span");
318        span.textContent = char;
319        el.appendChild(span);
320      });
321    }
322
323    wrapText(h2Inner);
324    wrapText(p);
325
326    const h2Chars = h2Inner ? h2Inner.querySelectorAll("span") : [];
327    const pChars = p ? p.querySelectorAll("span") : [];
328
329    const observer = new IntersectionObserver(entries => {
330      entries.forEach(entry => {
331        if (entry.isIntersecting) {
332          const tl = gsap.timeline({ defaults: { ease: "power3.out" } });
333
334          // ① アイコン
335          tl.fromTo(icon,
336            { x: -40, opacity: 0 },
337            { x: 0, opacity: 1, duration: 0.6 }
338          );
339
340          // ② h2
341          tl.fromTo(h2Chars,
342            { y: 15, opacity: 0 },
343            { y: 0, opacity: 1, duration: 0.05, stagger: 0.05 }
344          );
345
346          // ③ h2が終わったらp開始
347          tl.fromTo(pChars,
348            { y: 15, opacity: 0 },
349            { y: 0, opacity: 1, duration: 0.04, stagger: 0.04 }
350          );
351
352          observer.unobserve(section);
353        }
354      });
355    }, { threshold: 0.3 });
356
357    observer.observe(section);
358  });
359});
360
361
362
363document.addEventListener('DOMContentLoaded', function() {
364    const slider = document.querySelector('#mv-info-banner');
365    if (!slider) return;
366
367    new Swiper(slider, {
368        loop: true,
369        slidesPerView: 5,
370        spaceBetween: 10,
371        pagination: { 
372          el: slider.querySelector('.swiper-pagination'), 
373          clickable: true 
374        },
375        navigation: false,
376        breakpoints: {
377            0: { slidesPerView: 2, spaceBetween: 10 },
378            1024: { slidesPerView: 5, spaceBetween: 10 }
379        }
380    });
381});

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.