LoginSignup
11
5

More than 3 years have passed since last update.

【Vue】喘ぎ声メーカー作ってみた

Last updated at Posted at 2020-03-18

image.png
スーパー喘ぎ声メーカー
用意した単語をシャッフルして喘ぎ声を生成するツールを作ってみました。
喘ぎ声に限らず、好きな単語を入れて遊べます。

何故作ろうと思ったのか

BL小説書きの友人が「この喘ぎ声の組み合わせさっきも書いたな?
となるので自動生成してくれるツールがほしい
」と言っていたので。
BLに限らずいやらしい小説を書く方への負担を少しでも減らせないかと思い、作成にいたりました。
あとVueの勉強になりそうだと思ったので。
筆者は文系のwebデザイナー(見習い)であり、プログラミングの分野は勉強中です。

使ったもの

制作の流れ

プロトタイプ①

02.png

<button onclick="shuffle()">生成</button>
<p id="result1"></p>
<p id="result2"></p>
<p id="result3"></p>
<p id="result4"></p>
<p id="result5"></p>

<script>
Array.prototype.shuffle = function () {
  var i = this.length;
  while (i) {
    var j = Math.floor(Math.random() * i);
    var t = this[--i];
    this[i] = this[j];
    this[j] = t;
  }
  return this;
}

var words = ['あっ…', 'やっ', 'そん', '…っ', 'だめ', '',];

function shuffle() {
  words.shuffle();
  document.getElementById('result1').innerText = words.join('');
  words.shuffle();
  document.getElementById('result2').innerText = words.join('');
  words.shuffle();
  document.getElementById('result3').innerText = words.join('');
  words.shuffle();
  document.getElementById('result4').innerText = words.join('');
  words.shuffle();
  document.getElementById('result5').innerText = words.join('');
}

for (var i = 0; i < words.length; i++) {
  var li = document.createElement('li');
  li.textContent = words[i];
  document.getElementById('list').append(li);
}
</script>

まずHTMLとJavaScriptのみでプロトタイプを作成。
「生成!」ボタンを押すと配列をシャッフルした結果が表示されます。
決め打ちのデータしか組み合わせられませんが、大体のイメージができあがりました。

ちなみに「やっそん(おそらく「やめて、そんな」→「やっ…そん…」→「やっそん」と転じた)」は
一部界隈のスラングでBLの性行為のことを指します。永遠に使えないムダ知識をあなたに。

使用例:出会って5秒でやっそん

プロトタイプ②

image.png
Vue.jsでよくあるTodoアプリのコードを元にプロトタイプ第二弾を作成。
入力したデータを組み合わせられるようになった点はいい感じです。

<div id="app" class="container">
  <h1 class="header">喘ぎ声メーカー</h1>
  <div class="left">
    <h1>使用する単語</h1>
    <form @submit.prevent="addItem">
      <input type="text" v-model="newItem">
      <input type="submit" value="追加">
    </form>
    <ul>
      <li v-for="(word, index) in words">
        {{ word }}
        <span @click="deleteItem(index)" class="command">[x]</span>
      </li>
    </ul>
  </div>
  <div class="right">
    <h1>結果</h1>
    <ul>
      <li v-for="(word, index) in words.length">
        <span v-for="n in words.length" class="result">{{ random() }}</span>
      </li>
    </ul>
  </div>
</div>

<script>
  (function () {
    'use strict';

    var vm = new Vue({
      el: '#app',
      data: {
        newItem: '',
        words: [
          'あっ',
          'やっ',
          'んっ…',
          '',
          '',
          '',
        ]
      },
      methods: {
        addItem: function () {
          this.words.push(this.newItem);
          this.newItem = '';
        },
        deleteItem: function (index) {
          this.words.splice(index, 1);
        },
        random: function () {
          const rnd = Math.floor(Math.random() * this.words.length);
          return this.words[rnd];
        }
      }
    });
  })();
</script>

ただ現在のrandomメソッドだと同じ単語を何度も使ってしまうため、「あっあっあっ」と
ネフェルピトーに脳を弄くられるポックルみたいになってしまいます。
配列をシャッフルするコードに書き換えなければなりません。

モックアップ

image.png
Bootstrap4で見た目だけのものを作成。レスポンシブにも対応です。

完成品

完成品がこちらです!→スーパー喘ぎ声メーカー


var vm = new Vue({
  el: '#app',
  data: {
    newItem: '',
    array: [
      'やっ',
      'あっ',
      'んっ…',
    ],
  },
  methods: {
    addItem: function () {
      this.array.push(this.newItem);
      this.newItem = '';
    },
    deleteItem: function (index) {
      this.array.splice(index, 1);
    },
    shuffle: function (array) {
      var sArray = [];
      sArray = array.slice(0, array.length);
      var n = sArray.length, t, i;
      while (n) {
        i = Math.floor(Math.random() * n--);
        t = sArray[n];
        sArray[n] = sArray[i];
        sArray[i] = t;
      }
      return sArray.join('');
    },
    reset: function () {
      this.array = []
    }
  }
});

長くなるのでVue部分だけ掲載。(HTML含む全文はgithubで公開してます

shuffle: function (array) {
  var n = array.length, t, i;
  while (n) {
    i = Math.floor(Math.random() * n--);
    t = array[n];
    array[n] = array[i];
    array[i] = t;
  }
  return array.join('');
}

これは過去のコードなのですが、このメソッドだと
シャッフル実行時配列そのものもシャッフルされてしまいます。下図参照。
image.png

shuffle: function (array) {
  var sArray = [];
  sArray = array.slice(0, array.length);
  var n = sArray.length, t, i;
  while (n) {
    i = Math.floor(Math.random() * n--);
    t = sArray[n];
    sArray[n] = sArray[i];
    sArray[i] = t;
  }
  return sArray.join('');
}

コピーした配列にシャッフル処理をするように書き換えたら
単語のリストはシャッフルされなくなりました。
この対処法が正しいかはわかりませんが…

list.pngimage.png
また生成結果を表示するリストは、idを個別に用意するため
clipboard-target1~clipboard-target10までわざわざ一つ一つ<li>要素を作成していました。
何故idを個別に用意する必要があるのかと言うと、
clipboard.jsで特定のdivのテキストをコピーするために
個別のターゲットを指定しなければならないからです。
data-clipboard-targetの指定先がid名になっているのがお分かりいただけると思います。

でもVueならもっとスッキリ書けるんじゃないか?とよく考えたら、
v-forのループ処理でなんとかできそうだと思い至る。

<li v-bind:id="`clipboard-target${n}`" class="clipboard-target mb-2" v-for="n in 10">
  <span>{{ shuffle(array) }}</span>
  <div class="btn btn-danger btn-sm ml-3 btn-clipboard" data-toggle="tooltip"
    v-bind:data-clipboard-target="`#clipboard-target${n}`">
    コピー
  </div>
</li>

v-bindv-forでidとdata-clipboard-targetが連番になった<li>要素を10個作ることができました。
v-for="n in 10"の10の部分を変更すれば、喘ぎ声セットを10個でも100個でも作成できますね!
JavaScriptでやったら多分めちゃくちゃ面倒くさい処理ですよね…
ありがとうVue。

感想

  • 明確な目的があったためVue勉強のモチベーションが保ててよかった
  • 友達にややウケした

課題・問題点

  • 双方向バインディングすぎてEnterを押すたびに結果が再生成される→コメントのおかげで解決
  • 最初のイメージに合わせる知識がなかった(本当は「生成」ボタン押下時に結果が表示されるようにしたかった)→コメントのおかげで解決
  • 一度リセットしてから再度単語を追加して生成すると、ツールチップが表示されない(コピー自体は問題なくできる)
  • 本当はVueのコンポーネント機能を使いたかったが調べてもわからなかった

GitHubでコードを公開しておりますので、アドバイスいただけたら嬉しいです。
https://github.com/mitaru/superxxxmaker
コード見たら私がマジの初心者であることはお分かりになるかと思います…
プルリクお待ちしております。

追記

いただいたコメントを元に改造を進めております。

ver1.1(2020-03-19)
・配列がLocalStorageでキャッシュされるようになりました
・代わりに初期配列を表示できなくなりました
ver1.2(2020-03-20)
・「生成!」ボタン押下時に結果が表示されるようになりました
・なぜかツールチップが表示できなくなりました
ver1.3(2020-03-21)
・軽微な修正

11
5
7

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
11
5