PageSourceSearch

https://products.naganokeiki.co.jp/common/js/smoothscroll.js

js naganokeiki.co.jp collected 2026-10-04 03:30:32 UTC 3,010 bytes, 98 lines download raw bytes

1// スムーススクロール
2(function() {
3
4  const minmax = function(min, val, max) {
5    val = Math.max(val, min);
6    val = Math.min(val, max);
7    return val;
8  };
9
10  const getScrollMaxY = function() {
11    return 'scrollMaxY' in window
12      ? window.scrollMaxY
13      : document.documentElement.scrollHeight - document.documentElement.clientHeight;
14  };
15
16  const getTargetY = function (target) {
17    if (target === '#') {
18      return 0;
19    }
20    const el = typeof target === 'string' ? document.querySelector(target) : target;
21    return el ? el.getBoundingClientRect().top + window.pageYOffset : 0;
22  };
23
24  const getOffsetY = function (val) {
25    if (!val) {
26      return 0;
27    }
28    else if (typeof val === 'number') {
29      return val;
30    }
31    else if (typeof val === 'function') {
32      return val();
33    }
34    else if (typeof val === 'string') {
35      const el = document.querySelector(val);
36      return el ? el.offsetHeight : 0;
37    }
38    return 0;
39  };
40
41  const getScrollYToElem = function(target, offset) {
42    const targetY = getTargetY(target);
43    const offsetY = getOffsetY(offset);
44    const maxY = getScrollMaxY();
45    return minmax(0, targetY - offsetY, maxY);
46  };
47
48  const smoothScroll = function(targetY) {
49    const startX = window.pageXOffset;
50    const startY = window.pageYOffset;
51    const maxY = getScrollMaxY();
52    const endY = minmax(0, targetY, maxY);
53    const dir = (endY - startY) / Math.abs(endY - startY);
54
55    const doScroll = function(currentY) {
56      requestAnimationFrame(function() {
57        const distance = Math.abs(endY - currentY);
58        if (distance > 1.5) {
59          currentY += dir * Math.ceil(Math.min(distance / 3, 2000));
60          window.scrollTo(startX, currentY);
61          doScroll(currentY);
62        } else {
63          window.scrollTo(startX, endY);
64        }
65      });
66    };
67    doScroll(startY);
68  }
69
70  const smoothScrollToElem = function(target, offset) {
71    const y = getScrollYToElem(target, offset);
72    smoothScroll(y);
73  };
74
75  // ページ内リンクをクリックでスムーズスクロール
76  document.addEventListener('click', function (evt) {
77    const link = evt.target.matches('a[href]') ? evt.target : evt.target.closest('a[href]');
78    if (!link) {
79      return;
80    }
81    const isHashLink = link.href.indexOf(location.href.split('#')[0] + '#') === 0;
82    if (!isHashLink) {
83      return;
84    }
85    const hash = link.href.split(location.href.split('#')[0])[1];
86    evt.preventDefault();
87    smoothScrollToElem(decodeURI(hash), '.Header, .hd');
88  });
89
90  // ハッシュ付きリンクで繊維してきたときのスクロール位置調整
91  if (location.hash) {
92    setTimeout(function () {
93      // window.scrollTo(window.pageXOffset, getScrollYToElem(decodeURI(location.hash), '.Header'));
94      window.scrollTo(window.pageXOffset, getScrollYToElem(decodeURI(location.hash), '.Header, .hd'));
95    }, 100);
96  }
97
98})();

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.