1document.addEventListener("DOMContentLoaded", () => { 2 // ãã¼ã¸å ã®ãã¹ã¦ã®ã«ã«ã¼ã»ã«ã©ããã¼ãåå¾ 3 const carousels = document.querySelectorAll(".carousel-wrapper"); 4 5 // åã«ã«ã¼ã»ã«ã«å¯¾ãã¦åå¥ã«å¦çãå®è¡ 6 carousels.forEach((wrapper) => { 7 const container = wrapper.querySelector(".carousel-container"); 8 const track = wrapper.querySelector(".carousel-track"); 9 const items = wrapper.querySelectorAll(".carousel-item"); 10 const prevBtn = wrapper.querySelector(".carousel-nav.prev"); 11 const nextBtn = wrapper.querySelector(".carousel-nav.next"); 12 13 // å¿ è¦ãªè¦ç´ ãæã£ã¦ããªãå ´åã¯ã¹ããã 14 if (!container || !track || !items.length || !prevBtn || !nextBtn) return; 15 16 let currentIndex = 0; 17 let itemsPerView = 3; // ããã©ã«ãã¯PC表示 18 19 // ã¬ã¹ãã³ã·ã対å¿ï¼ç»é¢å¹ ã«å¿ãã¦è¡¨ç¤ºæ°ã夿´ 20 function updateItemsPerView() { 21 const width = window.innerWidth; 22 if (width <= 768) { 23 itemsPerView = 1; // SP: 1å 24 } else if (width <= 1024) { 25 itemsPerView = 2; // ã¿ãã¬ãã: 2å 26 } else { 27 itemsPerView = 3; // PC: 3å 28 } 29 } 30 31 // ã«ã«ã¼ã»ã«ã®ä½ç½®ãæ´æ° 32 function updateCarousel() { 33 const itemWidth = items[0].offsetWidth; 34 // CSSã®gapã®å¤ãåå¾ï¼è¨ç®ç¨ï¼ 35 const style = window.getComputedStyle(track); 36 const gap = parseFloat(style.gap) || 0; // gapãæªè¨å®ã®å ´åã¯0 37 38 const offset = -(currentIndex * (itemWidth + gap)); 39 track.style.transform = `translateX(${offset}px)`; 40 41 // ãã¿ã³ã®ç¶æ ãæ´æ° 42 updateButtons(); 43 } 44 45 // ãã¿ã³ã®æå¹/ç¡å¹ç¶æ ãæ´æ° 46 function updateButtons() { 47 const maxIndex = Math.max(0, items.length - itemsPerView); 48 49 // æåã®ä½ç½® 50 if (currentIndex <= 0) { 51 prevBtn.disabled = true; 52 prevBtn.classList.add('disabled'); // CSSã¹ã¿ã¤ãªã³ã°ç¨ã¯ã©ã¹ 53 } else { 54 prevBtn.disabled = false; 55 prevBtn.classList.remove('disabled'); 56 } 57 58 // æå¾ã®ä½ç½® 59 if (currentIndex >= maxIndex) { 60 nextBtn.disabled = true; 61 nextBtn.classList.add('disabled'); 62 } else { 63 nextBtn.disabled = false; 64 nextBtn.classList.remove('disabled'); 65 } 66 } 67 68 // å㸠69 function movePrev() { 70 if (currentIndex > 0) { 71 currentIndex--; 72 updateCarousel(); 73 } 74 } 75 76 // 次㸠77 function moveNext() { 78 const maxIndex = Math.max(0, items.length - itemsPerView); 79 if (currentIndex < maxIndex) { 80 currentIndex++; 81 updateCarousel(); 82 } 83 } 84 85 // ã¤ãã³ããªã¹ãã¼ï¼ãã¿ã³ï¼ 86 prevBtn.addEventListener("click", movePrev); 87 nextBtn.addEventListener("click", moveNext); 88 89 // ãªãµã¤ãºå¯¾å¿ 90 let resizeTimer; 91 window.addEventListener("resize", () => { 92 clearTimeout(resizeTimer); 93 resizeTimer = setTimeout(() => { 94 const oldItemsPerView = itemsPerView; 95 updateItemsPerView(); 96 97 // 表示æ°ãå¤ãã£ãå ´åãä½ç½®ãèª¿æ´ 98 if (oldItemsPerView !== itemsPerView) { 99 const maxIndex = Math.max(0, items.length - itemsPerView); 100 if (currentIndex > maxIndex) { 101 currentIndex = maxIndex; 102 } 103 updateCarousel(); 104 } 105 }, 250); 106 }); 107 108 // --- ã¿ããã¹ã¯ã¤ã対å¿ï¼ã¹ããç¨ï¼ --- 109 let touchStartX = 0; 110 let touchEndX = 0; 111 let touchStartY = 0; 112 let touchEndY = 0; 113 const minSwipeDistance = 50; 114 115 container.addEventListener("touchstart", (e) => { 116 touchStartX = e.changedTouches[0].screenX; 117 touchStartY = e.changedTouches[0].screenY; 118 }, { passive: true }); 119 120 container.addEventListener("touchend", (e) => { 121 touchEndX = e.changedTouches[0].screenX; 122 touchEndY = e.changedTouches[0].screenY; 123 handleSwipe(); 124 }, { passive: true });
125 126 // --- ãã¦ã¹ãã©ãã°å¯¾å¿ï¼PCç¨ï¼ --- 127 let isDragging = false; 128 let hasDragged = false; 129 130 container.addEventListener("mousedown", (e) => { 131 if (e.target.closest('.carousel-nav')) return; 132 isDragging = true; 133 hasDragged = false; 134 touchStartX = e.clientX; 135 touchStartY = e.clientY; 136 container.style.cursor = 'grabbing'; 137 e.preventDefault(); 138 }); 139 140 container.addEventListener("mousemove", (e) => { 141 if (!isDragging) return; 142 const moveX = Math.abs(e.clientX - touchStartX); 143 const moveY = Math.abs(e.clientY - touchStartY); 144 if (moveX > 5 || moveY > 5) { 145 hasDragged = true; 146 e.preventDefault(); 147 } 148 }); 149 150 container.addEventListener("mouseup", (e) => { 151 if (!isDragging) return; 152 isDragging = false; 153 container.style.cursor = 'grab'; 154 touchEndX = e.clientX; 155 touchEndY = e.clientY; 156 if (hasDragged) { 157 handleSwipe(); 158 e.preventDefault(); 159 } 160 }); 161 162 container.addEventListener("mouseleave", () => { 163 if (isDragging) { 164 isDragging = false; 165 container.style.cursor = 'grab'; 166 } 167 }); 168 169 container.addEventListener("dragstart", (e) => { 170 e.preventDefault(); 171 }); 172 173 container.style.cursor = 'grab'; 174 175 function handleSwipe() { 176 const swipeDistanceX = touchEndX - touchStartX; 177 const swipeDistanceY = touchEndY - touchStartY; 178 179 if (Math.abs(swipeDistanceY) > Math.abs(swipeDistanceX)) return; 180 181 if (swipeDistanceX < -minSwipeDistance) { 182 moveNext(); 183 } else if (swipeDistanceX > minSwipeDistance) { 184 movePrev(); 185 } 186 } 187 188 // åæåå®è¡ 189 updateItemsPerView(); 190 updateCarousel(); 191 }); 192});
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.