const menuData = [ { text: "TOP", link: "index.html" }, { text: "MESSAGE", link: "#Message" }, { text: "MOVIE", link: "#Movie" }, //{ text: "NEWS", link: "#News" }, { text: "TVPROGRAM", link: "tvprogram.html" }, { text: "EVENT", link: "event.html" }, { text: "HISTORY", link: "history.html" }, { text: "CAMPAIGN", link: "#Campaign" } ]; Vue.createApp({ components: { "header-component": { template: `

khb東日本放送 開局50周年

`, data() { return { isOpen: false, menuItems: menuData, isTopPage: window.location.pathname.endsWith("index.html") || window.location.pathname === "/" }; }, computed: { computedMenuItems() { return this.menuItems.map(item => { if (item.link.startsWith("#")) { return { ...item, link: this.isTopPage ? item.link : "index.html" + item.link }; } return item; }); } }, methods: { toggleMenu() { this.isOpen = !this.isOpen; }, closeMenu() { this.isOpen = false; }, handleClick(link) { if (this.isTopPage && link.startsWith("#")) { const target = document.querySelector(link); if (target) { window.scrollTo({ top: target.offsetTop, behavior: "smooth" }); this.closeMenu(); // ページ内リンククリック時にメニューを閉じる } } else { window.location.href = link; } } } }, "footer-component": { template: ` `, data() { return { menuItems: menuData, isTopPage: window.location.pathname.endsWith("index.html") || window.location.pathname === "/" }; }, computed: { computedMenuItems() { return this.menuItems.map(item => { if (item.link.startsWith("#")) { return { ...item, link: this.isTopPage ? item.link : "index.html" + item.link }; } return item; }); } }, methods: { handleClick(link) { if (this.isTopPage && link.startsWith("#")) { const target = document.querySelector(link); if (target) { window.scrollTo({ top: target.offsetTop, behavior: "smooth" }); } } else { window.location.href = link; } } } }, "subpage-header": { props: ["title", "bgImage"], template: `

{{ title }}

` } }, data() { return { eventArticles: [], // JSON から読み込む programArticles: [], // JSON から読み込む historyData: [], // JSON から読み込む currentIndexes: {}, // 各年のスライド用インデックス currentYear: null, // 現在のアクティブな年代 observer: null, // IntersectionObserver manuallySelected: false, // クリック時の制御 lastYear: null // 直前のアクティブ状態を保持 }; }, methods: { async loadHistoryData() { try { const response = await fetch('./data/historyData.json'); const data = await response.json(); this.historyData = data; this.initImageIndexes(); this.$nextTick(() => { this.initScrollAnimation(); this.startSlideshow(); }); } catch (error) { console.error("historyData の取得に失敗しました:", error); } }, async loadArticleData() { try { const [eventRes, programRes] = await Promise.all([ fetch('./data/eventArticles.json'), fetch('./data/programArticles.json') ]); const eventData = await eventRes.json(); const programData = await programRes.json(); const today = new Date(); let filteredEvents = []; eventData.forEach(monthData => { let validEvents = monthData.events.filter(event => event.timelimit && new Date(event.timelimit) >= today); if (validEvents.length) { filteredEvents.push({ month: monthData.month, // 月情報を保持 events: validEvents.sort((a, b) => new Date(a.timelimit) - new Date(b.timelimit)) }); } }); this.eventArticles = filteredEvents; this.programArticles = programData; } catch (error) { console.error("イベント・番組データの取得に失敗しました:", error); } }, initImageIndexes() { // 各年ごとに、events の数だけ画像スライド用インデックスを初期化 this.currentIndexes = {}; this.historyData.forEach(yearData => { // yearData.events は複数の出来事の配列 this.currentIndexes[yearData.year] = yearData.events.map(() => 0); }); }, startSlideshow() { setInterval(() => { this.historyData.forEach(yearData => { const year = yearData.year; yearData.events.forEach((event, idx) => { if (event.images && event.images.length > 1) { this.currentIndexes[year][idx] = (this.currentIndexes[year][idx] + 1) % event.images.length; } }); }); }, 2000); // 2秒ごとに画像を切り替え }, initScrollAnimation() { let elements = document.querySelectorAll(".js-historybox_animation"); if (elements.length === 0) return; let showTiming = window.innerHeight > 768 ? 100 : 40; function showElementAnimation() { let scrollY = window.scrollY; let windowH = window.innerHeight; elements.forEach(el => { let elemY = el.getBoundingClientRect().top + scrollY; if (scrollY + windowH - showTiming > elemY) { el.classList.add("is-show"); } else if (scrollY + windowH < elemY) { el.classList.remove("is-show"); } }); } showElementAnimation(); window.addEventListener("scroll", showElementAnimation); }, handleScroll() { this.initScrollAnimation(); }, updateCurrentYear() { if (this.manuallySelected) return; // クリック時はスクロールの影響を防ぐ let scrollY = window.scrollY; let closestYear = null; let minDiff = Infinity; document.querySelectorAll('[id^="y_"]').forEach(el => { const year = parseInt(el.id.replace("y_", ""), 10); const top = el.getBoundingClientRect().top + window.scrollY; // 要素のY座標取得 const diff = Math.abs(scrollY - top + 100); // +100pxの余裕をもたせる if (diff < minDiff) { closestYear = year; minDiff = diff; } }); if (closestYear !== null) { this.currentYear = closestYear; } } }, computed: { // groupedHistoryData は、historyData をそのままオブジェクト化する groupedHistoryData() { let grouped = {}; this.historyData.forEach(item => { grouped[item.year] = item; }); return grouped; }, latestProgramArticles() { return this.programArticles.slice(0, 3); // 最新の3つだけ取得 }, latestEventArticles() { let allEvents = []; this.eventArticles.forEach(monthData => { allEvents = allEvents.concat(monthData.events); }); return allEvents.slice(0, 3); // 最新3件のみ取得 } }, mounted() { window.addEventListener("scroll", this.handleScroll); window.addEventListener("scroll", this.updateCurrentYear, { passive: true }); this.loadHistoryData(); this.loadArticleData(); this.$nextTick(() => { this.initScrollAnimation(); }); }, beforeUnmount() { window.removeEventListener("scroll", this.updateCurrentYear); } }).mount("#app");