LoginSignup
5
2

More than 1 year has passed since last update.

vuetifyのv-calendarで祝日の色を変える

Last updated at Posted at 2022-07-19

前回(vuetifyのv-calendarで土日の色を変える)の続きです。

前提

vue: 2.6.11
vuetify: 2.6.0

手順

祝日ライブラリーの選定

JavaScriptで日本の祝日を扱うライブラリ5選を参考にし
今回は japanese-holidays-js 使うこととしました。

採用理由

  • 2020年のオリンピック特例も対応されており、メンテナンスがされていること
  • ライブラリの容量が軽いこと

祝日ライブラリーを設定する

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <script src="https://cdn.rawgit.com/osamutake/japanese-holidays-js/v1.0.10/lib/japanese-holidays.min.js"></script>
    <title><%= htmlWebpackPlugin.options.title %></title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
+    <script>
+      const getJPHoliday = function(year) {
+        return JapaneseHolidays.getHolidaysOf(year)
+      }
+    </script>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app">
+      <App :get-jp-holiday-list="getJPHoliday"></App>
    </div>
    <!-- built files will be auto injected -->
  </body>
</html>

vueの中ではライブラリを設定することができないので、index.htmlで設定し、vueに渡します。
JapaneseHolidays.getHolidaysOf でその年の祝日の月・日・祝日名を配列で取得します。

App.vue
<script>
export default {
  name: 'App',
+  props: ['getJPHolidayList'],
  methods:{
    changeColor: function () {
      setTimeout(() => {
        const dayList = Array.from(this.$refs.calendar.$vnode.elm.getElementsByClassName('v-calendar-weekly__week'))
        dayList.map(el => {
          el.children[0].classList.add('sunday')
          el.children[6].classList.add('saturday')
        })
      }, 200)
 +     // eslint-disable-next-line no-undef
 +     const holidaysOfYear = getJPHoliday(2022);
 +    console.log(holidaysOfYear)

    }
  },
};
</script>

+が前回土日カレンダーから変更した箇所です。

これで、console.log(holidaysOfYear)で2022年の祝日を配列で取得することを確認することができました。

スクリーンショット 2022-07-07 17.43.24.png

const holidaysOfYear = getJPHoliday(2022);がeslintでエラーが出てしまったので、例外的に下記のコメントを入れてエラーを回避してます。
// eslint-disable-next-line no-undef

祝日を抽出する

App.vue
methods:{
    changeColor: function () {
      setTimeout(() => {
        const dayList = Array.from(this.$refs.calendar.$vnode.elm.getElementsByClassName('v-calendar-weekly__week'))
        dayList.map(el => {
          el.children[0].classList.add('sunday')
          el.children[6].classList.add('saturday')
        })
      }, 200)
      // eslint-disable-next-line no-undef
      const holidaysOfYear = getJPHoliday(2022);
       console.log(holidaysOfYear)
 +    const holidayList = holidaysOfYear.filter(holiday => {
 +       if (holiday.month == 7) {
 +         return holiday
 +       }
 +       })
 +       console.log("holidayList:",holidayList)

今月(2022/7)の祝日を抽出します。

スクリーンショット 2022-07-15 17.09.38.png

祝日に背景色を設定

App.vue
    const holidayList = holidaysOfYear.filter(holiday => {
       if (holiday.month == 7) {
         return holiday
       }
       })
 +     setTimeout(() => {
 +       const dayList = Array.from(this.$refs.calendar.$vnode.elm.getElementsByClassName('v-calendar-weekly__day'))
 +           .filter(el => !el.classList.contains('v-outside'))
 +       for (let [i, dayEl] of dayList.entries()) {
 +         let dayNum = i + 1
 +         holidayList.forEach((holiday) => {
 +          if (holiday.date === dayNum) {
 +            dayEl.classList.add('holiday');
 +          }
 +           })
 +          }
 +         }, 200)

スクリーンショット 2022-07-15 17.52.34.png

v-outsideは当月ではない日付の部分なので、こちらは排除します。

entriesでkey, valueをそれぞれ取得し、取得した祝日のdateとkeyが一緒であれば、classListにholidayを追加します。

スクリーンショット 2022-07-19 10.56.52.png

完成 :clap:

最終形のソースはこちらです。

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <script src="https://cdn.rawgit.com/osamutake/japanese-holidays-js/v1.0.10/lib/japanese-holidays.min.js"></script>
    <title><%= htmlWebpackPlugin.options.title %></title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
    <script>
      const getJPHoliday = function(year) {
        return JapaneseHolidays.getHolidaysOf(year)
      }
    </script>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app">
      <App :get-jp-holiday-list="getJPHoliday"></App>
    </div>
    <!-- built files will be auto injected -->
  </body>
</html>

App.vue
<template>
  <v-app>
    <div>
      <v-sheet height="94vh">
        <v-calendar ref="calendar" @change="changeColor"></v-calendar>
      </v-sheet>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  props: ['getJPHolidayList'],
  methods:{
    changeColor: function () {
      setTimeout(() => {
        const dayList = Array.from(this.$refs.calendar.$vnode.elm.getElementsByClassName('v-calendar-weekly__week'))
        dayList.map(el => {
          el.children[0].classList.add('sunday')
          el.children[6].classList.add('saturday')
        })
      }, 200)
      // eslint-disable-next-line no-undef
      const holidaysOfYear = getJPHoliday(2022);
      const holidayList = holidaysOfYear.filter(holiday => {
        if (holiday.month == 7) {
          return holiday
        }
      })
      setTimeout(() => {
        const dayList = Array.from(this.$refs.calendar.$vnode.elm.getElementsByClassName('v-calendar-weekly__day'))
            .filter(el => !el.classList.contains('v-outside'))
        for (let [i, dayEl] of dayList.entries()) {
          let dayNum = i + 1
          holidayList.forEach((holiday) => {
            if (holiday.date === dayNum) {
              dayEl.classList.add('holiday');
            }
          })
        }
      }, 200)
    }
  },
};
</script>
<style>
.saturday {
  background: rgba(0, 0, 255, .1);
}
.sunday {
  background: rgba(255, 0, 0, .1);
}
.holiday {
  background: rgba(255, 0, 0, .3);
}
</style>

感想

意外と探せばあるようでなかったので、今回は土日編と祝日編に分けて記事を書かせていただきました。

この記事では今月(2022年7月)の祝日に色を塗るだけでしたが、moment.jsなどを使って、カレンダーの月が変わったらその都度取得するようにしたり、祝日名も取得できるので、ラベルで祝日を出してもいいかもしれません。

moment.jsをかなり苦戦した部分もあるので、いつか記事にできたらなと思います。

お付き合いいただき、ありがとうございました。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2