20201129のvue.jsに関する記事は11件です。

【Vue.js】cowsayをブラウザ上に表示させてみた

はじめに

スクリーンショット 2020-11-29 23.07.31.png
cowsayがかわいいのでVue.jsでブラウザ上に表示させたくなりました。

インストール

cowsay-browserを使用します。

ターミナル
npm install cowsay-browser

インポート

cowsay-browserをインポートします。

とりあえずコンソールに表示させてみます。

App.vue
<script>
import cowsay from 'cowsay-browser'

export default {
  created() {
    console.log(cowsay.say({text : "Hello!"}));
  }
}
</script>

スクリーンショット 2020-11-29 23.19.33.png

来た!!

あとはブラウザに表示させるだけです。

ブラウザへ

App.vue
<template>
  <div>
    <pre>{{ cowsay }}</pre>
  </div>
</template>

<script>
import cowsay from 'cowsay-browser'
export default {
  data() {
    return {
      cowsay: '' 
    }
  },
  created() {
    this.cowsay = cowsay.say({text : "Hello!"});
  }
}
</script>

スクリーンショット 2020-11-29 23.23.47.png


な、なんかズレて...る.......

調整する

せっかくなので少しソースコードをいじります。
node_modules>cowsay-browser>lib>cow-definitions.jsをいじればいけそうです。

cow-definitions.js
//-------省略


  "default": "$the_cow = <<\"EOC\";\r\n        $thoughts   ^__^\r\n         $thoughts  ( $eyes )\\\\_____\r\n             (__)\\\\              )\\\\/\\\\\r\n             $tongue       ||-------w |\r\n                      ||             ||\r\nEOC\r\n",


//-------省略

スクリーンショット 2020-11-29 23.36.43.png
・・・まあいいでしょう!(投げやり)

おしまい

スクリーンショット 2020-11-29 23.47.52.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

svelte.jsでゲームをつくってみた

この記事の概要

svelte.jsで間違い探しゲームをつくってみました。いろいろとハマったポイントもあったので忘れないようにメモしていきます。

作ったモノの概要

ピクトグラムを使った間違い探しゲームです。

svelte_1.gif

チュートリアルも実装されています。

svelte_2.gif

公開先

使ったフレームワーク

  • svelte.js (JavaScript全体のフレームワーク)
  • driver.js (チュートリアル用のライブラリ)
  • bulma (CSSのフレームワーク)

svelte.jsを使って困ったこと

npm installで他のパッケージが上手くインストールできない

webpackあたりでエラーが出てインストールできなかったモノがあったので、一旦はindex.htmlCDNで利用するようにしました。ここらへんはもう少し調査が必要そうです。今回は作ることを優先したので一旦CDNで利用する形を取りました。

配列を追加しても再描画されない

公式のドキュメントにも書いていますが配列を追加しただけだと画面上のオブジェクトが更新されません。
ログで出力するとちゃんと変数に入っているので、結構ココでハマるポイントかもしれません。
それじゃどうすればいいのかというと、変数として再代入することで解決します。svelte.jsの仕様上、変数に再代入されたときだけちゃんと再描画として認識するようです。vue.jsで慣れていると「ナンデダヨ!!」っていう部分です。

ちなみに今回のソースで該当の部分は以下のとおり

<script>
    export const changeImage = () => {
        setAnimation();
        imgArray = [];
        const appearRnd = Math.ceil(Math.random() * appearImg) - 1;
        const imageRnd = Math.ceil(Math.random() * imageCount);
        for (let step = 0; step < appearImg; step++) {
            if (appearRnd == step) {
                // imgArray.push(`pict_img/${imageRnd}-A.png`);
                // ※pushの場合は変数に再代入する必要がある
                // imgArray = imgArray;
                imgArray = [...imgArray, `pict_img/${imageRnd}-A.png`];
            } else {
                // imgArray.push(`pict_img/${imageRnd}-B.png`);
                imgArray = [...imgArray, `pict_img/${imageRnd}-B.png`];
            }
        }
    };
</script>

{#if isVisible}
    <div transition:fly={{ y: 100 }} class="container has-text-centered">
        {#each imgArray as img}
            <BtnPict imagePath={img} clickFunc={clickAction} />
        {/each}
    </div>
{/if}

使う機能をimportする必要がある

vue.jsだと初期で読み込むcreatedmountedなどはimportせずに利用できます。svelte.jsの場合は以下のように、その都度読み込む必要があるため面倒です。もしかすると上手くやる方法があるかもしれません。

<script>
    // onMountを使うなら毎回宣言する必要がある
    import { onMount } from "svelte";
</script>

動的にon:clickに対して関数を設定するときに注意が必要

on:clickに関数を設定するときにそのまま設定すると死にます。引数がない場合は()なしで設定すればよいのですが、引数付きの関数の場合は気をつける必要があります。

以下はダメパターン。

<script>
    export let clickFunc = (msg) => console.log(msg);
</script>

<p on:click={clickFunc ('コンソールログがタイヘンなことに・・・')}>TEST</p>

以下はイイパターン。

<script>
    export let clickFunc = (msg) => console.log(msg);
</script>

<p on:click={() => {clickFunc ('ヤッホー')} }>TEST</p>

svelte.jsを使ってよかったこと

変数の扱いがわかりやすい

vue.jsに比べてそのままJavaScriptの変数を扱うような感じです。具体的にいうとvue.jsの場合はテンプレートに渡す変数はpropsとして渡す必要があります。そしてpropsから渡ってきた変数はそのまま再代入するとwarningで怒られます。dataで変数を宣言しなおして再代入することが正しいわけです。

vue.jsですが以下はwarningで怒られます。

export default {
  props: {
    propsValue: Number
  },
  methods: {
    editValue() {
      this.propsValue = 20
    }
}

vue.jsでは以下が正しい姿

export default {
  props: {
    propsValue: Number
  },
  data() {
    // プロパティの値を設定
    dataValue: this.propsValue
  },
  methods: {
    editValue() {
      // データに定義した値を変更
      this.dataValue = 20
    }
}

ここまでvue.jsのことを書いてきましたが、propsdata()でそれぞれの変数の扱いがありますが、svelte.jsだとそういった扱いの違いがなく直感的に扱えるのは良い点だと思いました。

svelte.jsで違うコンポーネントに渡したい場合は・・・

■ App.svelte

<script>
    import Nested from './Nested.svelte';
</script>

<Nested answer={42}/>

exportをつけるだけで渡せます。

■ Nested.svelte

<script>
    export let answer;
</script>

<p>The answer is {answer}</p>

読み取り専用のストアの変数を設定できる

上記のようにコンポネントで変数を渡し合うことでどこで何の変数が使われているか把握しづらくなります。1対1で渡すだけならいいのですが、コンポネントに渡してその先のコンポネントに渡してのバケツリレーになったりすると悲惨です。

そのためにアプリケーションで扱うデータセットをstoreと呼ばれる領域で一元管理することで、各コンポーネントはstoreにアクセスすれば常に共通の値を参照する仕組みがあります。これはvue.jsでも同様でいろいろなコンポネントから値を参照する場合に有効だったりします。

ここでもvue.jsの話になりますが、vue.jsの場合はstoregettersetterを記述して、storeの変数を参照したいときはgetterを使い、storeの変数を更新したいときはsetterを使うわけです。

svelte.jsでもstoreを使えるわけですがよりわかりやすく使用できます。

■store.js

import { writable } from 'svelte/store';
export const ST_score = writable(0);

■App.js

<script>
    import { ST_score, ST_gamestart } from "./stores.js";
    import { get } from "svelte/store";
    //更新
    ST_score.set(100);

    //他のコンポネントから更新されたか検知したい場合はsubscribeを利用
    let score = 0;
    ST_score.subscribe((value) => {
        score = value;
    });

    //ちなみにsvelte/storeのgetでも取得はできる
    //(ただし他での更新は検知されない)
    //初期値を代入するときに利用できそう
    console.log(get(ST_score));

</script>

ただし扱いやすくなる反面、使われたくないタイミングで使われるケースもあるわけです。例えば、変なところで変数を更新されたくないため、読み取り専用にしたいな~というケースもあるわけです。そこでsvelte.jsではJavaとかでいうところのカプセル化のような隠蔽化するような仕組みもあります。

今回の作ってみたモノではハイスコアを読み取り専用にしてスコアの状態からハイスコアを更新するようにしています。ちなみにハイスコアはローカルストレージに保存するようにしています。

import { readable, writable } from 'svelte/store';
import { get } from 'svelte/store';

const lsKey_hiScore = "hiscore"
let lsHiScore = localStorage.getItem(lsKey_hiScore);
lsHiScore = lsHiScore ? lsHiScore : 0;

export const ST_score = writable(0);
export const ST_hiScore = readable(null, function start(set) {
    //readableで初期値をセットできる
    set(lsHiScore);

    //この中だけで値の更新ができる
    //スコアの変更を検知して条件によって更新する
    ST_score.subscribe(value => {
        console.log('hi-score: ' + get(ST_score));
        if (lsHiScore < value) {
            set(value);
            localStorage.setItem(lsKey_hiScore, value);
        }
    });
});

最初から使えるトランジションが便利(効果や演出がラク)

フェードインやスクロールインのアニメーションなどカンタンに使えます。
時間の設定なども細かくできるので他のCSSのライブラリとか使わずアニメーションを設定出来るのは便利かなと。
ただし、使うトランジションごとにインポートは必要で、コンポネント各所で利用すると思ったとおりの演出にならないこともあるので、イイカンジにお付き合いする必要があります。
実際にトランジションを使う場合は、ifなどで切り替わることでトランジションを発生させることができるようです。もしも初回の表示でトランジションを使いたい場合は、onMountなどで切り替えるとよさそうです。

<script>
    import { onMount } from "svelte";
    import { fly } from "svelte/transition";
    let isVisible = false;

    onMount(() => {
        let isVisible = true;
    });
</script>

{#if isVisible}
    <p transition:fly={{ y: 100 }}>
       下から上にせり上がる感じのやーつ 
    </p>
{/if}

総評

最初こそはいろいろとvue.jsとの違いで文句があったりしましたが、あとになればなるほどサクサク書けるようになりました。
storeによるreadableですが設定することで他のstore変数をトリガーにする形にしているので面倒くさいことになったかなと。
あとは1つのコンポネントが大きくなってきたら細かく分けたり、ここらへんはvue.jsと同様のセンスが必要だったりします。
あとはチュートリアルのライブラリがかゆいところに手が届かなくて試行錯誤したのが苦労したところかなと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vue.js】Vue-Cli(4.5.4)でSCSSを読み込む

環境

OS: macOS Big Sure 11.0.1
zsh: 5.8
Vue: 2.6.12
vue-cli: 4.5.4

何もせず使用してみる

インストールせずに使用すると

Module not found: Error: Can't resolve 'sass-loader' in <ディレクトリ名>

エラーが出ます。

解決方法

npm install sass-loader node-sass --save-dev 

これで使用できるようになりました。

参考記事

【Vue.js】Vue-CLI(4.1.1)でSCSSを読み込む手順

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vuexを使ってStoreに保存した値を使用する

src/pages/PageFood.vue
<template>
 <div class="container">
  <div class="row">
   <ul v-for="food in foods" :key="food.id">
    <li>Name:{{ food.name }}</li>
    <li>Description: {{ food.description }}</li>
   </ul>
  <div>
 <div>
</template>

<sctipt>
 import { mapGetters } from 'vuex' //vuexからmapGettersというものをインポートする

 export default {
  data() {
   return {}
  },
  computed: {
   ...mapGetters('foods',['foods']) 
  }
 }
</script>
store/store-foods.js
import Vue from 'vue'

const state = {
  foods: [
    {
      name: 'ハンバーガー',
      description: 'アメリカ合衆国を代表する国民食とされる。マクドナルドがフランチャイズを成功させ、ファストフードの代名詞となっている。付け合わせはフライドポテトが定番となっている。',

    },
    {
      name: 'ピザ',
      description: '日本で初めて紹介されたピザは一般的ではなかったが、1980年代後半より始まったバブル景気の最中(さなか)に起きたイタリア料理ブームに伴い、次第にイタリア風のものも広く知られるようになっていった。',

    },
    {
      name: 'そら豆',
      description: '塩ゆでするか、さやごと焼いて、中のマメをそのまま食べる。',
    },
  ]
}

const getters = {
  foods(state) {
    return state.foods //stateのfoodsを返す
  }
}

export default {
  namespaced: true,
  getters
}

store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

import foods from './store-foods' 

Vue.use(Vuex)

export default function (/* { ssrContext } */) {
  const Store = new Vuex.Store({
    modules: {
     foods
    },

    // enable strict mode (adds overhead!)
    // for dev mode only
    strict: process.env.DEV
  })

  return Store
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

5000兆回LGTMしたい!無限にLGTMできるネタアプリを作った

こんなやつ

5000兆円欲しい!という古のネタに触発された。(PCのみ対応)

URL: https://i-want-to-5senchou-lgtm.netlify.app/
GitHub: https://github.com/crypt0box/i_want_to_5senchou_lgtm
takusan_lgtm.gif

作った理由

1. 5000兆回いいねしたかった
Qiitaに溢れる幾多の良記事に1LGTMしかできないのって欠陥じゃない!?!?!?!?
何時間もハマったエラーを解決できたときに、

オラァッ!!!!
5000chou.JPG
感謝の5000兆LGTMをしたいがために作りました。

2.CSSの勉強
CSSフレームワークに頼ってばかりだったのでCSSだけで実装してみたかった

3.TypeScriptの勉強
TypeScript+Vueの書き方を学びたかった

4.Vue.js単体テストの勉強(これから)
テストの書き方がいまだにわかっていないのでシンプルなアプリで試してみたかった

使用技術

  • TypeScript 3.9.3
  • Vue 2.6.11
  • axios 0.21.0
  • Netlify

Qiitaからトレンドを持ってくるAPIは@HelloRusk様の素晴らしいAPIを使わせて頂きましたm(_ _)m
Netlify Functions を使って Qiita のトレンド API を非公式で作ってみた

おわりに

これからは下記の対応をしていこうと思います。

  1. テストコードの実装
  2. レスポンシブ対応
  3. LGTMボタンのチェックボックス化

ちなみにページをリロードするとLGTMは初期化されます。
takusan_lgtm_rest.gif
全ては儚い夢だったのだ。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

診察番号表示WEBアプリの作成

概要

耳鼻科の開業医をしています。自院の予約システムをGASを使ったLINE Botで作成し改良してきました。これまでに4500人ほどの患者さんが利用しています。
1時間で出来る LINE×GASで順番取り予約システムの作成
LINE×GASで作成した順番取り予約LINE Botを改良
診察予約システム(LINE×GAS)にプッシュメッセージ機能を追加

待合室の患者さんが現在診察中の番号が分かりように今までは既存の無料番号アプリを使って手動で番号を更新していました。自動化できないかと今回も友人に手取り足取り教えてもらいながら作成しました。

実装内容

 予約システムのバックエンドはGoogle Spread Sheetを利用、App Script(GAS)でLINE botと連携しています。
作成法はこちら 1時間で出来る LINE×GASで順番取り予約システムの作成
 Spread SheetのA1セルが発券済み番号、B1セルが診察中番号、C1セルが「1」の時に発券停止、D1セルが一人当たりの待ち時間(分)、E列に予約券を発行した患者さんのLINE userIDです。

image.png

今回診察中番号であるGASのB1セルの内容を2秒おきに取得し表示するWEBアプリを作成しました。

機能を追加

1.GASにブラウザからB1セルの内容を取得できるコードを追加

//B1セルの中身を取得できるように追加
function doGet(e) {
  var result = getNumberB1();

  return ContentService.createTextOutput(
    JSON.stringify({ number: result })
  ).setMimeType(ContentService.MimeType.JSON);
}

2.WEBアプリ用のindex.htmlを作成

<script>
// Vue.jsの設定
const app = new Vue({
    el: '#app', // <div id="app"></div>をVue.jsの管理対象に指    data() {
        return {
            number: 0,
        }
    },
    async mounted() {
        await this.updateView();

        setInterval(async () => {
            await this.updateView();
        }, 2000);
    },
    methods: {
        async getNumber() {
            const result = await axios.get('GASのURL');
            return result.data.number;
        },
        async updateView() {
            const result = await this.getNumber();
            this.number = result;
        },
        async updateViewManually() {
            try {
                await this.updateView();
                setTimeout(() => {
                    alert('更新しました。');
                }, 500);
            } catch(e) {
                alert('更新に失敗しました。');
            }
        },
    }
});
</script>

3.WEBアプリ用style.cssを作成

4.Herokuにデプロイ
公式はこちらDeploying with Git
gitが認識されない時はgitをインストール https://git-scm.com/

cd myapp
heroku create
git init
git add .
git commit -m "commit"
heroku git:remote -a アプリ名
git push heroku master

エラーが出る

remote:  !     No default language could be detected for this app.
remote:                         HINT: This occurs when Heroku cannot detect the buildpack to use for this application automatically.
remote:                         See https://devcenter.heroku.com/articles/buildpacks
remote:
remote:  !     Push failed

「No default language could be detected for this app.heroku html」で検索するとこちらの記事がトップに出てくる。

単純なHTML/CSS/JSをHerokuにデプロイする時つまずいたこと

HerokuはHTMLとCSSだけのデプロイは基本許してないサービスだが、PHP追加するとかわせるよう。

5.こちらの記事を参考にindex.phpとcomposer.jsonを追加

Gitのコマンドは基本、add → commit → pushが1セットなので、変更したら必ずこの3つを実行する

完成

おおおお!!!出来たー!!!
欲しいものが作れるとすごく楽しいですね。

image.png

明日から実際に使ってみます。
Takahiro Mitsuokaさん(マイページはこちら)ありがとうございました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

診察中番号表示WEBアプリの作成

概要

耳鼻科の開業医をしています。自院の予約システムをGASを使ったLINE Botで作成し改良してきました。これまでに4500人ほどの患者さんが利用しています。
1時間で出来る LINE×GASで順番取り予約システムの作成
LINE×GASで作成した順番取り予約LINE Botを改良
診察予約システム(LINE×GAS)にプッシュメッセージ機能を追加

待合室の患者さんが現在診察中の番号が分かりように今までは既存の無料番号アプリをipadで表示し手動で番号を更新していました。自動化できないかと今回も友人に手取り足取り教えてもらいながら作成しました。

実装内容

 予約システムのバックエンドはGoogle Spread Sheetを利用、App Script(GAS)でLINE botと連携しています。作成法はこちら 1時間で出来る LINE×GASで順番取り予約システムの作成

 Spread SheetのA1セルが発券済み番号、B1セルが診察中番号、C1セルが「1」の時に発券停止、D1セルが一人当たりの待ち時間(分)、E列に予約券を発行した患者さんのLINE userIDです。

image.png

今回診察中番号であるGASのB1セルの内容を2秒おきに取得し表示するWEBアプリを作成しました。

機能を追加

1.GASにブラウザからB1セルの内容を取得できるコードを追加

//B1セルの中身を取得できるように追加
function doGet(e) {
  var result = getNumberB1();

  return ContentService.createTextOutput(
    JSON.stringify({ number: result })
  ).setMimeType(ContentService.MimeType.JSON);
}

2.WEBアプリ用のindex.htmlを作成

<script>
// Vue.jsの設定
const app = new Vue({
    el: '#app', // <div id="app"></div>をVue.jsの管理対象に指    data() {
        return {
            number: 0,
        }
    },
    async mounted() {
        await this.updateView();

        setInterval(async () => {
            await this.updateView();
        }, 2000);
    },
    methods: {
        async getNumber() {
            const result = await axios.get('GASのURL');
            return result.data.number;
        },
        async updateView() {
            const result = await this.getNumber();
            this.number = result;
        },
        async updateViewManually() {
            try {
                await this.updateView();
                setTimeout(() => {
                    alert('更新しました。');
                }, 500);
            } catch(e) {
                alert('更新に失敗しました。');
            }
        },
    }
});
</script>

3.WEBアプリ用style.cssを作成

4.Herokuにデプロイ
公式はこちらDeploying with Git
gitが認識されない時はgitをインストール https://git-scm.com/

cd myapp
heroku create
git init
git add .
git commit -m "commit"
heroku git:remote -a アプリ名
git push heroku master

エラーが出る

remote:  !     No default language could be detected for this app.
remote:                         HINT: This occurs when Heroku cannot detect the buildpack to use for this application automatically.
remote:                         See https://devcenter.heroku.com/articles/buildpacks
remote:
remote:  !     Push failed

「No default language could be detected for this app.heroku html」で検索するとこちらの記事がトップに出てくる。

単純なHTML/CSS/JSをHerokuにデプロイする時つまずいたこと

HerokuはHTMLとCSSだけのデプロイは基本許してないサービスだが、PHP追加するとかわせるよう。

5.こちらの記事を参考にindex.phpとcomposer.jsonを追加

Gitのコマンドは基本、add → commit → pushが1セットなので、変更したら必ずこの3つを実行する

完成

おおおお!!!出来たー!!!
欲しいものが作れるとすごく楽しいですね。

image.png

明日から実際に使ってみます。
Takahiro Mitsuokaさん(マイページはこちら)ありがとうございました!

(2020年12月1日追記)

「あれ?Vue.jsがちゃんと表示できてない!?」

IMG_1457.JPG

とても古いiPadを使っていたからのようです。少し新しいiPadにしたら表示されました。スタッフも喜んでました。

予約システムの動画はこちら

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.js Props $emit 個人チート

 propsについて

  1. 親子間でのデータの受け渡しを行う為に使用する。
    • 親では任意の属性名でを子コンポーネントタグで作成して、渡したいデータの定義を行う
親コンポーネント
<template>
  <div id="app">
    <Nav :data="message" />
    <router-view />
    <input type="text" v-model="message" />
    <Footer />
  </div>
</template>

<script>
import Nav from './component/Nav.vue';

export default {
  conponents: {
    Nav,
  },
  data () => {
    message: 'this is props'
  }
}
</script>

受け取るには子の方でpropsとして配列で受け取る。
親は属性名にデータが格納された変数と考えよう。なのでpropsに登録するのは属性名。

<template>
  <div>
    <p>{{ message }}</p>
    <p>Navです</p>
  </div>
</template>

<script>
export default {
  props: ["message"],
};
</script>
  required: true,

ちなにオブジェクトとして受けて、型のチェックもできる。
詳しい内容は公式でキュメンとで: Vue.js,props

<template>
  <div>
    <p>{{ message }}</p>
    <p>Navです</p>
  </div>
</template>

<script>
export default {
  props: {
    message: {
      type: String,
      required: true,
    },
  },
};
</script>

reactと比較すると

//親
import React from "react";
import { Nav } from "./Nav";

export default function App() {
  const message = "this is props";
  return (
    <>
      <p>親</p>
      <Nav message={message} />
    </>
  );
}

//子コンポーネント
import React from "react";

export const Nav = (props) => {
  const { message } = props;
  return <>{message}</>;
};

ここで忘れてはいけないのは親、子、ひ孫というコンポーネント管理があったとしたら、親→ひ孫へのデータ渡しはできない。
なので上記の方法と一緒でpropsを経由して一つ一つデータを渡して行かないといけない。
流石にこれではprops地獄になるので大規模になればデータの一元管理はVuexが望ましい。

$emit

  1. 子から親へデータを渡す際に活用する。
    • 子コンポーネントでmethodsとして$emitを活用する。
    • $emit()第1引数はカスタムイベント名、第2引数は渡したいデータ。親はこの第1引数のカスタムイベント名を使用する。登録はケバブ出ないとダメ  
<template>
  <div>
    <p>{{ message }}</p>
    <p>Navです</p>
    <button @click="send">親にデータ送ります</button>
  </div>
</template>

<script>
export default {
  props: {
    message: {
      type: String,
      required: true,
    },
  },
  data() {
    return {
      emitData: "this is emit",
    };
  },
  methods: {
    send() {
      this.$emit("send-emit-data", this.emitData);
    },
  },
};
</script>
  1. 親でデータを受け取る。
    • データを送ってきた子コンポーネントタグで$emitで送られたエベント名を使用する。
    • 今回は引数にメソッドを定義している。
    • メソッドの引数はvalueとして受け取る。これが$emitで送信したデータ。後はこれをデータプロパティに代入するだけ。
<template>
  <div id="app">
    <Nav :message="message" @send-emit-data="receive" />
  </div>
</template>

<script>
import Nav from "./components/Nav";

export default {
  components: {
    Nav,
  },
  data() {
    return {
      emitData: "",
    };
  },
  methods: {
    receive(value) {
      this.emitData = value;
      console.log(this.emitData);
    },
  },
};
</script>

終わりに

実践的チートシートにするべく再度編集予定

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

オンライン配信授業で、手を挙げたら【●●さん】とさしてくれるwebアプリを作ってみた

自己紹介

大学時代C言語を学んでから十数年以来のプログラミングを始めています。
本業はweb制作で、お客様から悩みや感じている課題についてに相談を受ける事も多いです。
LINEbotを中心に、webの技術を利用してどのようにお客様の悩みや課題を解決出来るのか、広く学んでいます!

今回は、Teachable Machineというgoogleが提供する機械学習が簡単に行えるウェブブラウザツールを知り、普段の生活に取り入れてみる事にしました!

【オンライン授業でのメンタルサポートAI】

実際に小学校中学年の子どもがオンラインで配信される塾の授業を受けているのですが、テレビ同様一方通行の授業なので、子供のやる気に波があるんです。
すぐに画面からいなくなったり、気が付いたら違う事をしていたり。。。
やっぱり対面での先生の問いかけがあったら、もっと積極的に授業に参加できるのになとは思いますが、このようなご時世なのでオンラインの方が安心ですよね。

家での経験だけではなく、オンライン授業が浸透してきいるなという実感が最近ありました。先日とある塾の保護者会で、通学に不安を感じる低学年向けに配信授業コースを開設するという話がありました。

その時に、低学年だとさらに親が管理をする負担が大きいな~と思っていた所、オンライン授業をサポートするAIがあったら面白い!と思いついたので早速実装してみる事にしました。

シュミレーションです。
こんな機能があったら良いなと思ってます。

image.png

子どもの表情や動きを機械学習して、状況を判断して問いかけます。

全体の流れ

今回は、機械学習初心者なので単純に

「手を挙げたらさしてくれる」

をまずはwebアプリとして実装します。

image.png

実際に作ったもの

webにアップしているのでクリックしていただくと体験できます

image.png

開発環境・利用ツール

・Teachable Machine
・Visual Code
・Line API
・node.js
・vue.js

Teachable Machineで画像サンプルを登録

Teachable Machine

Teachable Machineの使い方は【備忘録】Teachable Machineの利用方法で紹介しています。

1.手を挙げない
2.手を挙げる

この2パターンの画像を学習させます。

登録をしたらトレーニング

手を挙げていないあ/挙げたか
画像サンプルを撮りました。
image.png

トレーニングしてTeachable Machine上では成功!
image.png

#Visual Conde
いよいよ、node.jsを利用して、Teachable Machineで作成したモデルを利用して、web上で動作させるようにしたいと思います。

<body>
    <div class="wrap">
        <h1>わかったらてをあげてくださいね!</h1>
        <div id="app">
            <input v-model="name" placeholder="おなまえをおしえてください" size="30">
            <p>おななえ: {{name}}</p>
            <p>よろしく おねがいします</p>
            <p>わかったら てのひらがみえるように てをあげてくださいね</p>
            <p class="res">{{result}}</p>
            <video id="video" width="640" height="480" autoplay></video>
        </div>
    </div>
    <script src="https://unpkg.com/ml5@latest/dist/ml5.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        const imageModelURL =
            'https://teachablemachine~始まるコードを入力します。';
        let video;
        // let classifier;

        const app = new Vue({
            el: '#app',
            data: {
                modelStat: 'モデルロード中...',
                detectedName: '見つかってない',
                name: '',
                result: '',
            },
            //最初の1度だけ実装
            async created() {
                // カメラからの映像取得
                const stream = await navigator.mediaDevices.getUserMedia({
                    audio: false,
                    video: true,
                });
                // html内のidがvideoのdomを取得
                video = document.getElementById('video');
                // videoにカメラ映像を適用
                video.srcObject = stream;

                // 自作モデルのロード
                classifier = await ml5.imageClassifier(
                    imageModelURL + 'model.json',
                    video,
                    modelLoaded
                );

                // モデルのロード完了時に実行される
                async function modelLoaded() {
                    console.log('Model Loaded!');
                    app.modelStat = 'モデルデータのロード完了';
                }
                async function interval() {
                    // 挙手しているかjudge
                    const myHandResults = await classifier.classify();
                    const myHand = myHandResults[0].label;

                    if (myHand == "手を挙げる") {
                        app.result = app.name + "さんっ!";
                    } else {
                        app.result = "";
                    }
                    console.log(myHand);
                }
                setInterval(interval, 3000); // 3秒ごとに処理
            },
        });
    </script>
</body>

今回ポイントとなったのは2か所

Vue.jsのフォーム入力バインディングを使って、入力した内容を簡単に出力しています。
Vue.jsのドキュメント

<input v-model="name" placeholder="おなまえをおしえてください" size="30">
<p>おななえ: {{name}}</p>

リアルタイム処理をしたいので3秒間隔で判断しています。

 setInterval(interval, 3000); // 3秒ごとに処理

さいごに

実装していて、色々なアイディアが出てきました。

また、顔の表情を認識して、眠そうであれば楽しそうな音楽を流す等反応するAIも面白いと思いました。ただ、表情のサンプルを子供から撮るのが難しくて失敗。

その他にも、百人一首の正誤判定する音声認識も企画しましたが、2秒しか音声サンプル入力できないので、出だしの「ありあけの~」で終わってしまうので、これも失敗。

結果として、今回は手を挙げているか挙げていないかだったので、高確率で判断してくれる機械学習を体験する事が出来ました。ポーズを使うと骨格が取れるので、より高度に認識できるみたいです。
機械学習を使って、一方通行のオンライン配信授業でも授業に参加しているような感覚を体験する事で、オンライン授業がより充実したものになっていくのではないかな~と思いました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vue.js】v-onを使ってカウントアップする【初心者向け】

はじめに

Vue.jsを使うと、簡単に動的なサイトを作れるようになります。
ここでは、v-onというVue.jsの基本構文を使って、クリックで数字をカウントアップさせるサイトを作成していきます。

この記事が役立つ方

・Vue.jsを学ぼうか迷っている人
・Vue.jsを学び始めた人

この記事のメリット

・Vue.jsでどんなことができるのか、知ることができる
・Vue.jsで使えるv-onに関する基本構文を知ることができる

環境

・MacOS Catalina 10.15.7
・vue.js 2.6.12

完成形

ボタンを押すと数字がカウントされるビュー。

countup2 (1).gif

v-onとは?

(例)
・マウスをクリックした
・ボタンをクリックした
・マウスが動いた

という『瞬間』に動作を発火させたいときに使う。
今回は、ボタンをクリックするたびに数字を増やす『v-on:click』で作成。

基本構文

index.html
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>

<div id="app">
 <p>現在{{ number }}回クリックされています</p>
  <button>カウントアップ</button>
</div>
vue.js
new Vue({
 el: '#app',
  data: {
   number: 0
 }
})

このままでは動きません・・・。

countup1.gif

index.html
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>

<div id="app">
 <p>現在{{ number }}回クリックされています</p>
<!-- 以後ここから -->
  <button v-on:click="countUp">カウントアップ</button>
<!-- ここまでで記載 -->
</div>
vue.js
new Vue({
 el: '#app',
  data: {
   number: 0
},
<!-- 以後ここから -->
methods: {
 countUp: function() {
  this.number += 1
  }
 }
<!-- ここまでで記載 -->

})

無事、カウントアップされるようになりました!

countup2 (1).gif

おわりに

Vue.jsを使うと、HTMLやCSSだけでは表現できないことも行えるようになります。
最初はとっつきづらいかもしれませんが、実際に動作させていくと、楽しみを覚えると思います!

参考

『超Vue.js 2 完全パック - もう他の教材は買わなくてOK! (Vue Router, Vuex含む)』
https://www.udemy.com/course/vue-js-complete-guide/
(動画教材は非常に分かりやすいので、オススメです!)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ~Vue.js × axios編~

制作環境

Windows 10
Laravel : 6.18.35
Laravel/ui : 1.0
Laravel-mix : 5.0.1
Bootstrap : 4.0.0
axios : 0.19
Vue : 2.5.17
XAMPP
PHP : 7.4.3
Visual Studio Code

はじめに

この記事はプログラミングをはじめたばかりの素人が、できたことをメモするのに利用しています。
内容には誤りがあるかもしれません。

前回のつづきになります。

関連記事

Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ~事前準備編~
Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ~JavaScript編~
Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ~jQuery編~
Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ~JavaScript × axios編~
Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ~jQuery × axios編~
Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ~JavaScript × FetchAPI編~
Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ~jQuery × FetchAPI編~

今回作成するもの

Vue.jsとaxiosを利用し非同期通信を行い、自動で仕入れ先が入力される機能を実装します。

以下作成条件

  • Vue.jsを使用し通信にはaxiosを使用します。
  • 数字が4桁入力されたら自動で仕入れ先を検索し、反映します。
  • 検索するのにクリック操作を必要としません。inputに入力されたら検索します。
  • スクリプトの読み込みにはLaravel-mixを使用します。
  • 前回作成したtest.jsは使用しません。

app.jsの編集

今まで使用してきたtest.jsは今回使用しません。

resources>js内のapp.jsを開き、読み込みがされないように以下の内容をコメントアウトするか、削除してください。

app.js
require('./test');

続けてVue.jsの記述を行います。
app.jsの下の部分に記載があるconst app = new Vueを以下の用に修正します。

app.js
// 変数appにVueクラスをインスタンス化(実体化)して代入します
// その際引数で初期設定を渡します
const app = new Vue({
    // id="app"のDOM要素に対しVueインスタンスを与えます
    // このidをもつ要素の範囲がVue.jsが使える範囲(仮想DOM)になります
    el: '#app',

    // キーと値の初期値を設定します
    data() {
        return {
            code: '',
            supplier: '',
        }
    },
    // メソッド(機能)を作成します
    methods: {
        // 新たにgetSupplierというメソッドを作成し、処理を記述します
        getSupplier() {

            // bladeテンプレートipnutの値をtraderCodeに代入します
            let traderCode = this.code

            // 業者コードが4桁未満の場合は検索させないようにします
            if (traderCode.length < 4) {
                return
            }

            // アクセス先のURLを作成し、urlに代入します
            let url = '/form_search?trader_code=' + traderCode

            // 次の処理の中ではthis.supplierのように、thisを使えないため
            // 任意の変数に代入することで使えるようにします
            var that = this

            // axiosで指定したURLにGETでアクセスします
            // .thenで通信に成功した場合の処理を記述します
            // 引数に変数をいれることで、コントローラからのデータ(検索結果)を受け取れます
            // ここでは変数responseでデータを受け取っています
            axios.get(url).then(function(response) {
                // 受け取ったデータから必要なものだけ取り出し変数に代入します
                let data = response.data
                // 受け取ったデータ(検索結果)が仕入れ先のvalueに反映されるよう
                // supplierに値を代入します
                that.supplier = data[0].trader_name
            })

        }
    }
});

コンパイル

ターミナルを起動し、以下を実行してください。
※node.jsが必要です。インストールされていない方は、インストールを行ってください。

node.js
https://nodejs.org/ja/

npm run dev

ビューの修正

resources>views内のindex.blade.phpを開き、以下の部分だけ修正します。

index.blade.php
<div>
    <label>業者コード: <input type="text" id="code" v-model="code" @input="getSupplier()"></label>
    <label>仕入れ先: <input type="text" id="supplier" name="supplier" v-model="supplier"></label>
</div>

v-model

v-modelを記述するだけで、双方向データバインディング(Two-way Data Binding)を実装できます。

以前記事を投稿しているので、詳しくはこちらを確認してください。
https://qiita.com/Charry/items/a1e6a93f05c7f686b505

@input

@inputv-on:inputの省略型です。
今回は業者コードが入力されたら検索処理を行うので、@input="getSupplier()"とすることでgetSupplierメソッドを呼び出しています。

Vue.jsの場合データの受け渡し方法がわかっていないと、ちょっとわかりづらいですね。

以上で終了です。
お疲れさまでした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む