【Vue】シャッフルし続ける文字列を実装する方法を✅

わたくし暖房器具がない家に住んでいるのですが、ついに同居人が「俺耳から体温あげてくわ」と言い出し沖縄の民謡を流し始めて困惑している23期中野昴こと酒ケジュール作成中です。

#おじい自慢のオリオンビール~♪

現在の進捗

なんかiphoneだと診断がカクカク動いてしまう現象に見舞われています。どうしたものか。。

https://zeroken.herokuapp.com/

今日は「下戸証明書」と「酒ケジュール」の作成に取り掛かっていました。

まだ本番環境に反映できていないので使うことはできません。早く正式リリースしたいです、、!

下戸証明書とは

アルハラから身を守るお守り。診断結果が下戸だった場合のみ現れるため、真の下戸にしか与えられない由緒正しき証明書

下戸証明書の進捗

真の下戸に飲み表示される下戸証明書。

Image from Gyazo

下戸証明書の中身

絶対飲ませるな?私のバックには弁護士と警察官がいるかんな?という雰囲気を伝えたい。

Image from Gyazo

酒ケジュールとは

1軒目で飲むお酒の順番。その人のお酒の強さや1軒目でなりたい気分に応じて変動する。

モーダルが反応してないため、ただbooleanがtrueになって画面に表示されただけになっている。

背景に設定した木目が滲んでガチャガチャしている。

Image from Gyazo

今回はtransitionを使って文字に躍動感を加える方法を学習していきたいと思います。

transitionを使ったら何ができるか

transitionで囲んだ要素に対して動きをつけることができる。modalやpop、fadeなどのモードがある。

transitionを制するものはweb制作を制しそう。普通にいじっていて楽しい。

文字に躍動感をつけてみる

コンポーネントの全体像

コンポーネント

frontend/pages/ZerokenTop.vue

template部分

親データautoplayをautoplayとしてprop downしている。

<template>
<ZerokenAbout :autoplay="autoplay" />
</template>

script部分

ZerokenAboutコンポーネントをインポートしている。

<script>

import ZerokenAbout from '../components/top/ZerokenAbout';
export default {
  components: {
    ZerokenAbout,
  },
data() {
    return {
      autoplay: true,

frontend/components/top/ZerokenAbout.vue

template部分

算出メソッドのeditor内でgetしたtextをリストレンダリングしている。

<template>
  <div class="black--text about text-center">
    <transition-group tag="div" class="title">
      <span v-for="el in text" :key="el.id" class="item" v-text="el.text" />
    </transition-group>
  </div>
</template>

script部分

<script>
export default {
  props: {
    autoplay: Boolean,
  },
  data() {
    return {
      timer: null,
      index: 0,
      // オリジナルメッセージ
      original: [
        'ZEROKENは、あなたが1軒目で飲むお酒の順番を提供するアプリです。お酒の強さを診断する機能や、アルハラ防止機能を搭載しています。',
        'ZEROKENを使うことによって、1軒目では自分のペースでお酒を飲むことができます。',
        '診断で出てきた酒ケジュールや下戸証明書はそのままTwitterで拡散したり、お守りとしてとっておくことができます。',
      ],
      // 分解したメッセージ
      messages: [],
      text: '',
    };
  },
  computed: {
    editor: {
      get() {
        return this.text.map((e) => e.text).join('');
      },
      set(text) {
        this.text = this.convText(text);
      },
    },
  },
  watch: {
    autoplay(val) {
      clearTimeout(this.timer);
      if (val) {
        this.ticker();
      }
    },
  },
  methods: {
    // デモ用のオートタイマー
    ticker() {
      this.timer = setTimeout(() => {
        if (this.autoplay) {
          this.index = this.index < this.messages.length - 1 ? this.index + 1 : 0;
          this.text = this.messages[this.index];
          this.ticker();
        }
      }, 5000);
    },
    // テキストを分解してオブジェクトに
    convText(text) {
      const alms = {};
      const result = text.split('').map((el) => {
        alms[el] = alms[el] ? ++alms[el] : 1;
        return { id: `${el}_${alms[el]}`, text: el };
      });
      return Object.freeze(result); // 監視しない
    },
  },
  created() {
    this.messages = this.original.map((el) => this.convText(el));
    this.text = this.messages[0];
    this.ticker();
  },
};
</script>

まずcreatedが実行され、最初の導線が発動される。具体的に下記の三つが実行される。

messagesの中に、convTextで加工されたoriginalが格納される。

textの中にmessage内の最初のオブジェクトが入る。

そしてtickerが走り、5秒ごとにtext配列の中身が変わる。

次にwatchによってtimerがリセットされ、仮引数の中身がまだあれば再度tickerが実行される。

これが繰り返し行われている。

style部分

<style scoped>
.about {
  margin: 0, auto;
  background-color: aliceblue;
  display: flex;
  align-items: center;
  justify-content: center;
}
.title {
  font-size: 2rem;
}
.item {
  display: inline-block;
  min-width: 0.3em;
}
/* トランジション用スタイル */
.v-enter-active,
.v-leave-active,
.v-move {
  transition: all 1s;
}
.v-leave-active {
  position: absolute;
}
.v-enter,
.v-leave-to {
  opacity: 0;
  transform: translateY(-30px);
}
</style>

v-enter-active,v-leave-active,v-move

transitionが1秒かけて行われている。

v-enter,v-leave-to

y軸に-30pxの方向へ消えていっている。

最終的なアウトプット

Image from Gyazo

もっとスタイリッシュに表示させたいですね〜

基礎から学ぶ Vue.js