Vue.jsでアバター作成

# 0. はじめに
- [MYJLab Advent Calendar 2019](https://qiita.com/advent-calendar/2019/myjlab) 7日目の記事です。
- Vue.jsとCodeSandboxでアバター(のようなもの)が作成できるツールを作成しました。
![vue.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484145/8e3d0f96-f8d1-c629-fc38-53a22c1543e9.gif)

- 顔、髪、眉、目、鼻、口の形をそれぞれ6種類から選択することができ、位置や大きさ、角度を変更することができます。
- デモページは[こちら](https://jysze.csb.app/)

# 1. 実行環境
エディタ : CodeSandbox

## CodeSandbox
- https://codesandbox.io/
- オンラインコードエディター
- Vue.jsのフレームワークを簡単に使うことができる。
- ライブラリやコンポーネントの追加も簡単に行うことができる。

### CodeSandboxでVue.jsのプロジェクトを立ち上げる方法

1. [CodeSandbox](https://codesandbox.io/)を開く。
2. 右上の Sign In をクリックする。 <img width="1440" alt="codesandbox1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484145/a0b36cd8-3550-f01d-eca5-70290dd6c861.png">
3. GitHubアカウントでサインインする。アカウントがない場合は Create an account からアカウントを作成する。<img width="1440" alt="codesandbox2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484145/1cd1cfb7-3c9a-4ac3-b68f-077980a40945.png">
4. Authorize codesandbox をクリックする。サインインが終了する。<img width="1440" alt="codesandbox3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484145/86f125fc-e8fb-8bb1-21d0-9eb4f06b2177.png">
5. 右上の検索部分でvueを検索する。<img width="1440" alt="codesandbox4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484145/f68ba321-17d3-1d8e-f1d1-e51359c3d1c1.png">
6. 画像と同じものをクリックする。<img width="1440" alt="codesandbox5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484145/fa0e41c3-f953-8a43-4c78-1a8c3c0b19f0.png">
7. 右上のForkをクリックする。<img width="1440" alt="codesandbox6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484145/8c2dc0e2-1b91-871e-055a-24bbe7dff0b3.png">
8. Vue.jsのプロジェクトの立ち上げが完了した。

# 2. プロジェクト概要
- [Vue.js+SVGで自由にCSSアニメーションしたい人のための完全解説（ソース付き）](https://qiita.com/yuneco/items/1f31418269f9df15cf9f)を参考にさせていただいています。

### 用意したもの
- 画像48枚
  - ヘッダー用の画像(顔、髪、眉、目、鼻、口)：6枚
  - 顔、髪、眉、目、鼻、口の形を選択する用の画像それぞれ6枚ずつ：36枚
  - 大きさ、位置、角度変更用の矢印の画像：6枚<br>
（せっかく作ったので、GitHubにあげたりしてここにアップロードしたい。。。）

### はじめに
- publicフォルダ内にimgフォルダを作成し、上記の画像48枚をアップロードする。

- components内のHelloWorld.vueをFace.vueに名称変更する。

### フォルダ構成
> ├ public/
> │ 　├ img/
> │ 　│　└ face.pngなど48枚
> │ 　├ favicon.ico
> │ 　└ index.html
> ├　src/
> │　 ├ assets/
> │ 　│　└ logo.png
> │ 　├ components
> │ 　│　└ Face.vue
> │ 　├ App.vue
> │ 　└ main.js
> └ package.json

### ファイルの中身
#### App.vue
```Javascript:App.vue
<template>
 <div id="app">
  <header>
    <div id="parts">
      <ul>
        <li @click="status='face'">
          <img src="/img/face.png" height="70px;">
        </li>
        <li @click="status='hair'">
          <img src="/img/hair.png" height="70px;">
        </li>
        <li @click="status='eyebrow'">
          <img src="/img/eyebrow.png" height="70px;">
        </li>
        <li @click="status='eye'">
          <img src="/img/eye.png" height="70px;">
        </li>
        <li @click="status='nose'">
          <img src="/img/nose.png" height="70px;">
        </li>
        <li @click="status='mouth'">
          <img src="/img/mouth.png" height="70px;">
        </li>
      </ul>
    </div>
    
    <div id="form">
      <ul v-for="index of 6" :key="index">
        <li @click="isClick(index)">
          <img :src="getImgUrl(index)" height="70px;">
        </li>
      </ul>
    </div>
  </header>
  <body>
    <Face :isFace="isFace" :isHair="isHair" :isEyebrow="isEyebrow" :isEye="isEye" :isNose="isNose" :isMouth="isMouth" />
  </body>
 </div>
</template>

<script>
import Face from "./components/Face.vue";

export default {
  name: "app",
  components: {
    Face,
  },
  data() {
    return {
      status: "face",
      isFace:"/img/face1.png",
      isHair:"/img/hair1.png",
      isEyebrow:"/img/eyebrow1.png",
      isEye:"/img/eye1.png",
      isNose:"/img/nose1.png",
      isMouth:"/img/mouth1.png"
    };
  },
  methods: {
    getImgUrl(index) {
      var images = "/img/" + this.status + index + ".png";
      return images;
    },
      isClick(index) {
      var images = "/img/" + this.status + index + ".png";
        if(this.status === "face"){
          this.isFace = images
          return this.isFace;
        } else if(this.status === "hair"){
          this.isHair = images
          return this.isHair;
        }else if(this.status === "eyebrow"){
          this.isEyebrow = images
          return this.isEyebrow;
        }else if(this.status === "eye"){
          this.isEye = images
          return this.isEye;
        }else if(this.status === "nose"){
          this.isNose = images
          return this.isNose;
        }else{
          this.isMouth = images
          return this.isMouth;
        }
    },
  }
};
</script>

<style scoped>
html,
body {
  margin: 0;
  padding: 0;
}
body {
  position: relative;
  height: 100%;
}
#parts {
  padding: 3px;
  background-color: #000000;
}
#parts ul {
  padding: 0px;
  margin: 0px;
}
#parts ul li {
  display: inline;
  margin-left: 1em;
}
#form {
  padding: 3px;
  background-color: #c0c0c0;
}
#form ul {
  display: inline;
  padding: 0px;
  margin: 0px;
}
#form ul li {
  display: inline;
  margin-left: 1em;
}
</style>
```
#### Face.vue
```JavaScript:Face.vue
<template>
  <div id="app">
    <div>
      <img
        class="arrangement"
        :src="isFace"
        alt="顔"
        :style="{
      transform: `translate(${faceX}px, ${faceY}px) scale(${faceScaleX}, ${faceScaleY}) rotate(${faceRotate}deg)`
    }"
      >
      <img
        class="arrangement"
        :src="isEyebrow"
        alt="左眉"
        :style="{
      transform: `translate(${lefteyebrowX}px, ${lefteyebrowY}px) scale(${eyebrowScaleX}, ${eyebrowScaleY}) rotate(${lefteyebrowRotate}deg)`
    }"
      >
      <img
        class="arrangement"
        :src="isEyebrow"
        alt="右眉"
        :style="{
      transform: `translate(${righteyebrowX}px, ${righteyebrowY}px) scale(-${eyebrowScaleX}, ${eyebrowScaleY}) rotate(${righteyebrowRotate}deg)`
    }"
      >
      <img
        class="arrangement"
        :src="isEye"
        alt="左目"
        :style="{
      transform: `translate(${lefteyeX}px, ${lefteyeY}px) scale(${eyeScaleX}, ${eyeScaleY}) rotate(${lefteyeRotate}deg)`
    }"
      >
      <img
        class="arrangement"
        :src="isEye"
        alt="右目"
        :style="{
      transform: `translate(${righteyeX}px, ${righteyeY}px) scale(-${eyeScaleX}, ${eyeScaleY}) rotate(${righteyeRotate}deg)`
    }"
      >
      <img
        class="arrangement"
        :src="isNose"
        alt="鼻"
        :style="{
      transform: `translate(${noseX}px, ${noseY}px) scale(${noseScaleX}, ${noseScaleY}) rotate(${noseRotate}deg)`
    }"
      >
      <img
        class="arrangement"
        :src="isMouth"
        alt="口"
        :style="{
      transform: `translate(${mouthX}px, ${mouthY}px) scale(${mouthScaleX}, ${mouthScaleY}) rotate(${mouthRotate}deg)`
    }"
      >
      <img
        class="arrangement"
        :src="isHair"
        alt="髪"
        :style="{
      transform: `translate(${hairX}px, ${hairY}px) scale(${hairScaleX}, ${hairScaleY}) rotate(${hairRotate}deg)`
    }"
      >
    </div>
    <div id="leftContents">
      <h3>顔</h3>
      <p>
        位置　：
        <img src="/img/arrow1.png" width="25px;" @click="faceY=faceY-10">
        <img src="/img/arrow1.png" width="25px;" class="rotate180" @click="faceY=faceY+10">
        <img src="/img/arrow1.png" width="25px;" class="rotate270" @click="faceX=faceX-10">
        <img src="/img/arrow1.png" width="25px;" class="rotate90" @click="faceX=faceX+10">
      </p>
      <p>
        サイズ：
        <img src="/img/arrow2.png" width="25px;" @click="faceScaleY=faceScaleY+0.1">
        <img
          src="/img/arrow2.png"
          width="25px;"
          class="rotate90"
          @click="faceScaleX=faceScaleX+0.1"
        >
        <img src="/img/arrow3.png" width="25px;" @click="faceScaleY=faceScaleY-0.1">
        <img
          src="/img/arrow3.png"
          width="25px;"
          class="rotate90"
          @click="faceScaleX=faceScaleX-0.1"
        >
      </p>
      <p>
        回転　：
        <img
          src="/img/arrow4.png"
          width="25px;"
          style="transform: scale(-1, 1);"
          @click="faceRotate=faceRotate-1"
        >
        <img src="/img/arrow4.png" width="25px;" @click="faceRotate=faceRotate+1">
      </p>
      <h3>髪</h3>
      <p>
        位置　：
        <img src="/img/arrow1.png" width="25px;" @click="hairY=hairY-10">
        <img src="/img/arrow1.png" width="25px;" class="rotate180" @click="hairY=hairY+10">
        <img src="/img/arrow1.png" width="25px;" class="rotate270" @click="hairX=hairX-10">
        <img src="/img/arrow1.png" width="25px;" class="rotate90" @click="hairX=hairX+10">
      </p>
      <p>
        サイズ：
        <img src="/img/arrow2.png" width="25px;" @click="hairScaleY=hairScaleY+0.1">
        <img
          src="/img/arrow2.png"
          width="25px;"
          class="rotate90"
          @click="hairScaleX=hairScaleX+0.1"
        >
        <img src="/img/arrow3.png" width="25px;" @click="hairScaleY=hairScaleY-0.1">
        <img
          src="/img/arrow3.png"
          width="25px;"
          class="rotate90"
          @click="hairScaleX=hairScaleX-0.1"
        >
      </p>
      <p>
        回転　：
        <img
          src="/img/arrow4.png"
          width="25px;"
          style="transform: scale(-1, 1);"
          @click="hairRotate=hairRotate-1"
        >
        <img src="/img/arrow4.png" width="25px;" @click="hairRotate=hairRotate+1">
      </p>
            <h3>眉</h3>
          <p>
        位置　：
        <img
          src="/img/arrow1.png"
          width="25px;"
          @click="lefteyebrowY=lefteyebrowY-2; righteyebrowY=righteyebrowY-2;"
        >
        <img
          src="/img/arrow1.png"
          width="25px;"
          class="rotate180"
          @click="lefteyebrowY=lefteyebrowY+2; righteyebrowY=righteyebrowY+2;"
        >
        <img
          src="/img/arrow1.png"
          width="25px;"
          class="rotate270"
          @click="lefteyebrowX=lefteyebrowX-2; righteyebrowX=righteyebrowX-2;"
        >
        <img
          src="/img/arrow1.png"
          width="25px;"
          class="rotate90"
          @click="lefteyebrowX=lefteyebrowX+2; righteyebrowX=righteyebrowX+2;"
        >
        <img
          src="/img/arrow2.png"
          width="25px;"
          class="rotate90"
          @click="lefteyebrowX=lefteyebrowX+2; righteyebrowX=righteyebrowX-2;"
        >
        <img
          src="/img/arrow3.png"
          width="25px;"
          class="rotate90"
          @click="lefteyebrowX=lefteyebrowX-2; righteyebrowX=righteyebrowX+2;"
        >
      </p>
      <p>
        サイズ：
        <img src="/img/arrow2.png" width="25px;" @click="eyebrowScaleY=eyebrowScaleY+0.02">
        <img src="/img/arrow2.png" width="25px;" class="rotate90" @click="eyebrowScaleX=eyebrowScaleX+0.02">
        <img src="/img/arrow3.png" width="25px;" @click="eyebrowScaleY=eyebrowScaleY-0.02">
        <img src="/img/arrow3.png" width="25px;" class="rotate90" @click="eyebrowScaleX=eyebrowScaleX-0.02">
      </p>
      <p>
        回転　：
        <img src="/img/arrow5.png" width="25px;" @click="lefteyebrowRotate=lefteyebrowRotate+1; righteyebrowRotate=righteyebrowRotate+1;">
        <img src="/img/arrow6.png" width="25px;" @click="lefteyebrowRotate=lefteyebrowRotate-1; righteyebrowRotate=righteyebrowRotate-1;">
      </p>
    </div>
    <div id="rightContents">
    <h3>目</h3>
          <p>
        位置：
        <img
          src="/img/arrow1.png"
          width="25px;"
          @click="lefteyeY=lefteyeY-2; righteyeY=righteyeY-2;"
        >
        <img
          src="/img/arrow1.png"
          width="25px;"
          class="rotate180"
          @click="lefteyeY=lefteyeY+2; righteyeY=righteyeY+2;"
        >
        <img
          src="/img/arrow1.png"
          width="25px;"
          class="rotate270"
          @click="lefteyeX=lefteyeX-2; righteyeX=righteyeX-2;"
        >
        <img
          src="/img/arrow1.png"
          width="25px;"
          class="rotate90"
          @click="lefteyeX=lefteyeX+2; righteyeX=righteyeX+2;"
        >
        <img
          src="/img/arrow2.png"
          width="25px;"
          class="rotate90"
          @click="lefteyeX=lefteyeX+2; righteyeX=righteyeX-2;"
        >
        <img
          src="/img/arrow3.png"
          width="25px;"
          class="rotate90"
          @click="lefteyeX=lefteyeX-2; righteyeX=righteyeX+2;"
        >
      </p>
      <p>
        サイズ：
        <img src="/img/arrow2.png" width="25px;" @click="eyeScaleY=eyeScaleY+0.02">
        <img src="/img/arrow2.png" width="25px;" class="rotate90" @click="eyeScaleX=eyeScaleX+0.02">
        <img src="/img/arrow3.png" width="25px;" @click="eyeScaleY=eyeScaleY-0.02">
        <img src="/img/arrow3.png" width="25px;" class="rotate90" @click="eyeScaleX=eyeScaleX-0.02">
      </p>
      <p>
        回転　：
        <img src="/img/arrow5.png" width="25px;" @click="lefteyeRotate=lefteyeRotate+1; righteyeRotate=righteyeRotate+1;">
        <img src="/img/arrow6.png" width="25px;" @click="lefteyeRotate=lefteyeRotate-1; righteyeRotate=righteyeRotate-1;">
      </p>

      <h3>鼻</h3>
      <p>
        位置　：
        <img src="/img/arrow1.png" width="25px;" @click="noseY=noseY-2">
        <img src="/img/arrow1.png" width="25px;" class="rotate180" @click="noseY=noseY+2">
        <img src="/img/arrow1.png" width="25px;" class="rotate270" @click="noseX=noseX-2">
        <img src="/img/arrow1.png" width="25px;" class="rotate90" @click="noseX=noseX+2">
      </p>
      <p>
        サイズ：
        <img src="/img/arrow2.png" width="25px;" @click="noseScaleY=noseScaleY+0.02">
        <img
          src="/img/arrow2.png"
          width="25px;"
          class="rotate90"
          @click="noseScaleX=noseScaleX+0.02"
        >
        <img src="/img/arrow3.png" width="25px;" @click="noseScaleY=noseScaleY-0.02">
        <img
          src="/img/arrow3.png"
          width="25px;"
          class="rotate90"
          @click="noseScaleX=noseScaleX-0.02"
        >
      </p>
      <p>
        回転　：
        <img
          src="/img/arrow4.png"
          width="25px;"
          style="transform: scale(-1, 1);"
          @click="noseRotate=noseRotate-1"
        >
        <img src="/img/arrow4.png" width="25px;" @click="noseRotate=noseRotate+1">
      </p>

      <h3>口</h3>
      <p>
        位置　：
        <img src="/img/arrow1.png" width="25px;" @click="mouthY=mouthY-2">
        <img src="/img/arrow1.png" width="25px;" class="rotate180" @click="mouthY=mouthY+2">
        <img src="/img/arrow1.png" width="25px;" class="rotate270" @click="mouthX=mouthX-2">
        <img src="/img/arrow1.png" width="25px;" class="rotate90" @click="mouthX=mouthX+2">
      </p>
      <p>
        サイズ：
        <img src="/img/arrow2.png" width="25px;" @click="mouthScaleY=mouthScaleY+0.02">
        <img
          src="/img/arrow2.png"
          width="25px;"
          class="rotate90"
          @click="mouthScaleX=mouthScaleX+0.02"
        >
        <img src="/img/arrow3.png" width="25px;" @click="mouthScaleY=mouthScaleY-0.02">
        <img
          src="/img/arrow3.png"
          width="25px;"
          class="rotate90"
          @click="mouthScaleX=mouthScaleX-0.02"
        >
      </p>
      <p>
        回転　：
        <img
          src="/img/arrow4.png"
          width="25px;"
          style="transform: scale(-1, 1);"
          @click="mouthRotate=mouthRotate-1"
        >
        <img src="/img/arrow4.png" width="25px;" @click="mouthRotate=mouthRotate+1">
      </p>

    </div>
  </div>
</template>

<script>
export default {
  name: "Face",
  props: {
    isFace: { type: String, default: "/img/face1.png" },
    isHair: { type: String, default: "/img/hair1.png" },
    isEyebrow: { type: String, default: "/img/eyebrow1.png" },
    isEye: { type: String, default: "/img/eye1.png" },
    isNose: { type: String, default: "/img/nose1.png" },
    isMouth: { type: String, default: "/img/mouth1.png" },
  },
  data() {
    return {
      faceX: 100,
      faceY: 100,
      faceScaleX: 1,
      faceScaleY: 1,
      faceRotate: 0,
      hairX: 100,
      hairY: 100,
      hairScaleX: 1,
      hairScaleY: 1,
      hairRotate: 0,
      lefteyebrowX: 250,
      lefteyebrowY: -100,
      lefteyebrowRotate: 0,
      righteyebrowX: 170,
      righteyebrowY: -100,
      righteyebrowRotate: 0,
      eyebrowScaleX: 0.2,
      eyebrowScaleY: 0.2,
      lefteyeX: 250,
      lefteyeY: -60,
      lefteyeRotate: 0,
      righteyeX: 170,
      righteyeY: -60,
      righteyeRotate: 0,
      eyeScaleX: 0.2,
      eyeScaleY: 0.2,
      noseX: 190,
      noseY: 0,
      noseScaleX: 0.2,
      noseScaleY: 0.2,
      noseRotate: 0,
      mouthX: 190,
      mouthY: 50,
      mouthScaleX: 0.2,
      mouthScaleY: 0.2,
      mouthRotate: 0
    };
  }
};
</script>

<style scoped>
#app {
  width: 100%;
  display: flex;
}
#leftContents {
  padding-left: 600px;
}
#rightContents {
  padding-left: 100px;
}
.arrangement {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: 90px 100%;
}
.rotate90 {
  -webkit-transform: rotate(90deg);
  -moz-transform: rotate(90deg);
  -o-transform: rotate(90deg);
  -ms-transform: rotate(90deg);
  transform: rotate(90deg);
}
.rotate180 {
  -webkit-transform: rotate(180deg);
  -moz-transform: rotate(180deg);
  -o-transform: rotate(180deg);
  -ms-transform: rotate(180deg);
  transform: rotate(180deg);
}
.rotate270 {
  -webkit-transform: rotate(270deg);
  -moz-transform: rotate(270deg);
  -o-transform: rotate(270deg);
  -ms-transform: rotate(270deg);
  transform: rotate(270deg);
}
h3 {
  position: relative;
  padding: 10px 0 0 25px;
}
h3:before {
  position: absolute;
  content: '';
  bottom: -3px;
  left: 0;
  width: 0;
  height: 0;
  border: none;
  border-left: solid 15px transparent;
  border-bottom: solid 15px rgb(119, 195, 223);
}
h3:after {
  position: absolute;
  content: '';
  bottom: -3px;
  left: 10px;
  width: 100%;
  border-bottom: solid 3px rgb(119, 195, 223);
}
</style>
```

- プロジェクトの中身は[こちら](https://codesandbox.io/s/boring-spence-jysze?fontsize=14&hidenavigation=1&theme=dark)からも確認できます。

# 3. プロジェクト解説

### 部位選択
<img width="1440" alt="vue1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484145/d24b19b8-0d56-1b12-13d6-3ee49d380284.png">

```Javascript:App.vue
<template>
  <div id="parts">
    <header>
      <ul>
        <li @click="status='face'">
          <img src="/img/face.png" height="70px;">
        </li>
        <li @click="status='hair'">
          <img src="/img/hair.png" height="70px;">
        </li>
        <li @click="status='eyebrow'">
          <img src="/img/eyebrow.png" height="70px;">
        </li>
        <li @click="status='eye'">
          <img src="/img/eye.png" height="70px;">
        </li>
        <li @click="status='nose'">
          <img src="/img/nose.png" height="70px;">
        </li>
        <li @click="status='mouth'">
          <img src="/img/mouth.png" height="70px;">
        </li>
      </ul>
    </header>
  </div>
</template>

<script>
export default {
  data() {
    return {
      status: "face",
    };
  }
};
</script>

<style scoped>
#parts {
  padding: 3px;
  background-color: #000000;
}
#parts ul {
  padding: 0px;
  margin: 0px;
}
#parts ul li {
  display: inline;
  margin-left: 1em;
}
```

- 顔、髪、眉、目、鼻、口の画像をリストを使って表示する。
- クリックされると`status`に対応した値が入る。初期値は`face`。

```JavaScript
<ul>
  <li @click="status='face'"> //@clickでクリックされた時の処理
     <img src="/img/face.png" height="70px;"> //顔の画像を表示
  </li>
  <li @click="status='hair'">
     <img src="/img/hair.png" height="70px;">
   </li>
...
</ul>
```
<hr>
### 形選択
<img width="1440" alt="vue2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484145/3680d788-fe3a-e5fd-ce08-f483f26d36a9.png">

```JavaScript:App.vue
<template>
  <header>
    <div id="form">
      <ul v-for="index of 6" :key="index">
        <li @click="isClick(index)">
          <img :src="getImgUrl(index)" height="70px;">
        </li>
      </ul>
    </div>
  </header>
</template>

<script>
export default {
  data() {
    return {
      isFace:"/img/face1.png",
      isHair:"/img/hair1.png",
      isEyebrow:"/img/eyebrow1.png",
      isEye:"/img/eye1.png",
      isNose:"/img/nose1.png",
      isMouth:"/img/mouth1.png",
    };
  },
  methods: {
    getImgUrl(index) {
      var images = "/img/" + this.status + index + ".png";
      return images;
    },
    isClick(index) {
      var images = "/img/" + this.status + index + ".png";
        if(this.status === "face"){
          this.isFace = images
          return this.isFace;
        } else if(this.status === "hair"){
          this.isHair = images
          return this.isHair;
        }else if(this.status === "eyebrow"){
          this.isEyebrow = images
          return this.isEyebrow;
        }else if(this.status === "eye"){
          this.isEye = images
          return this.isEye;
        }else if(this.status === "nose"){
          this.isNose = images
          return this.isNose;
        }else{
          this.isMouth = images
          return this.isMouth;
        }
    }
  }
};
</script>

<style scoped>
#form {
  padding: 3px;
  background-color: #c0c0c0;
}
#form ul {
  display: inline;
  padding: 0px;
  margin: 0px;
}
#form ul li {
  display: inline;
  margin-left: 1em;
}
</style>
```
- `status`の値に応じて画像が変化する。
  - 上の画像では`status === 'face'`なので、顔の画像が表示されている。
- それぞれ画像を6枚ずつ用意しているので、`v-for="index of 6"`で6枚の画像を表示する。

```JavaScript
<ul v-for="index of 6" :key="index">
  <li @click="isClick(index)">
     <img :src="getImgUrl(index)" height="70px;">
   </li>
</ul>
```

- `getImgUrl(index)`ではファイルの参照先を返している。
  - 画像名は`face1.png, face2.png ... mouth5.png, mouth6.png`となっているので、`status + index + ".png"`で参照先が示せる。

```JavaScript
getImgUrl(index) {
   var images = "/img/" + this.status + index + ".png";
   return images;
}
```
- `isClick(index)` では子コンポーネント(Face.vue)にクリックした画像の情報を送る。
  - 変数：`isFace、isHair、isEyebrow、isEye、isNose、isMouth`にクリックしたファイルの参照先を保持している。

```JavaScript
isClick(index) {
  var images = "/img/" + this.status + index + ".png";
  if(this.status === "face"){             //faceがクリックされたら顔を変更
    this.isFace = images
    return this.isFace;
  } else if(this.status === "hair") {     //hairがクリックされたら髪を変更
    this.isHair = images
    return this.isHair;
  } ...
}
```

<hr>
### アバターとパーツの移動、大きさ・角度変更
<img width="1440" alt="vue3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484145/f5a1a52a-02d6-bc33-cb1b-f250102f33b5.png">

(初期の顔が一番面白い気がする。。。)

```JavaScript:App.vue
<template>
  <body>
    <Face :isFace="isFace" :isHair="isHair" :isEyebrow="isEyebrow" :isEye="isEye" :isNose="isNose" :isMouth="isMouth" />
  </body>
</template>

<script>
import Face from "./components/Face.vue";

export default {
  components: {
    Face,
  },
  data() {
    return {
      isFace:"/img/face1.png",
      isHair:"/img/hair1.png",
      isEyebrow:"/img/eyebrow1.png",
      isEye:"/img/eye1.png",
      isNose:"/img/nose1.png",
      isMouth:"/img/mouth1.png",
    };
  },
};
</script>
```
- Face.vueをインポートして呼び出す。

```JavaScript
import Face from "./components/Face.vue";

export default {
  components: {
    Face,
  },
...
```
- 先ほどの変数：`isFace ... isMouth`を受け渡すために`:isFace="isFace"...`を`<Face>`タグ内に記入する。

```JavaScript
<Face :isFace="isFace" :isHair="isHair" :isEyebrow="isEyebrow" :isEye="isEye" :isNose="isNose" :isMouth="isMouth" />
// 親から子に変数を渡す時は :変数名 = "渡したい値"  
```

```JavaScript:Face.vue

<template>
    <div>
      <img
        class="arrangement"
        :src="isFace"
        alt="顔"
        :style="{
      transform: `translate(${faceX}px, ${faceY}px) scale(${faceScaleX}, ${faceScaleY}) rotate(${faceRotate}deg)`
    }"
      >
  
    <div id="leftContents">
      <h3>顔</h3>
      <p>
        位置　：
        <img src="/img/arrow1.png" width="25px;" @click="faceY=faceY-10">
        <img src="/img/arrow1.png" width="25px;" class="rotate180" @click="faceY=faceY+10">
        <img src="/img/arrow1.png" width="25px;" class="rotate270" @click="faceX=faceX-10">
        <img src="/img/arrow1.png" width="25px;" class="rotate90" @click="faceX=faceX+10">
      </p>
      <p>
        サイズ：
        <img src="/img/arrow2.png" width="25px;" @click="faceScaleY=faceScaleY+0.1">
        <img
          src="/img/arrow2.png"
          width="25px;"
          class="rotate90"
          @click="faceScaleX=faceScaleX+0.1"
        >
        <img src="/img/arrow3.png" width="25px;" @click="faceScaleY=faceScaleY-0.1">
        <img
          src="/img/arrow3.png"
          width="25px;"
          class="rotate90"
          @click="faceScaleX=faceScaleX-0.1"
        >
      </p>
      <p>
        回転　：
        <img
          src="/img/arrow4.png"
          width="25px;"
          style="transform: scale(-1, 1);"
          @click="faceRotate=faceRotate-1"
        >
        <img src="/img/arrow4.png" width="25px;" @click="faceRotate=faceRotate+1">
      </p>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    isFace: { type: String, default: "/img/face1.png" },
  },
  data() {
    return {
      faceX: 100,
      faceY: 100,
      faceScaleX: 1,
      faceScaleY: 1,
      faceRotate: 0
    };
  }
};
</script>

<style scoped>
#app {
  width: 100%;
  display: flex;
}
#leftContents {
  padding-left: 600px;
}
.arrangement {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: 90px 100%;
  /* transform: translate(200px, 100px); */
}
.rotate90 {
  -webkit-transform: rotate(90deg);
  -moz-transform: rotate(90deg);
  -o-transform: rotate(90deg);
  -ms-transform: rotate(90deg);
  transform: rotate(90deg);
}
.rotate180 {
  -webkit-transform: rotate(180deg);
  -moz-transform: rotate(180deg);
  -o-transform: rotate(180deg);
  -ms-transform: rotate(180deg);
  transform: rotate(180deg);
}
.rotate270 {
  -webkit-transform: rotate(270deg);
  -moz-transform: rotate(270deg);
  -o-transform: rotate(270deg);
  -ms-transform: rotate(270deg);
  transform: rotate(270deg);
}
h3 {
  position: relative;
  padding: 10px 0 0 25px;
}
h3:before {
  position: absolute;
  content: '';
  bottom: -3px;
  left: 0;
  width: 0;
  height: 0;
  border: none;
  border-left: solid 15px transparent;
  border-bottom: solid 15px rgb(119, 195, 223);
}
h3:after {
  position: absolute;
  content: '';
  bottom: -3px;
  left: 10px;
  width: 100%;
  border-bottom: solid 3px rgb(119, 195, 223);
}
</style>
```

- 親コンポーネント(App.vue)から`props`で`isFace`(クリックされた顔の形の画像の参照先)を受け取り、選択された画像表示する。

```JavaScript
  props: {
    isFace: { type: String, default: "/img/face1.png" },
  }
```
- `translate(${faceX}px, ${faceY}px)`が位置を、`scale(${faceScaleX}, ${faceScaleY}) `が大きさを、`rotate(${faceRotate}deg)`が角度を表している。

```JavaScript
<img class="arrangement"
     :src="isFace" //親から受け取った画像の参照先にある画像を表示
     alt="顔"
     :style="{
       transform: `translate(${faceX}px, ${faceY}px) scale(${faceScaleX}, 
       ${faceScaleY}) rotate(${faceRotate}deg)`
     }"
>
```
- data()で`faceX、faceY、faceScaleX、faceScaleY、faceRotate`の初期値を定義しておく。
  
```JavaScript
data() {
    return {
      faceX: 100,
      faceY: 100,
      faceScaleX: 1,
      faceScaleY: 1,
      faceRotate: 0
    };
```
- 矢印を押すことで、`faceX、faceY、faceScaleX、faceScaleY、faceRotate`の値を変更するため、位置、大きさ、角度が変更される。
  -  例えば、位置の左矢印はクリックされるごとに`faceX`の値が10ずつ減少していき、顔の画像が左に移動していく。

```JavaScript
 <img src="/img/arrow1.png" width="25px;" class="rotate270" @click="faceX=faceX-10">
```
- 髪、眉、目、鼻、口も同様になっている。

# 4. おわりに
### 反省点
- cssが適当すぎる。
- 組み合わせ次第では髪から顔がはみ出し、面白いことになってしまう。
- もう少し画像を増やしたい。
- 眼鏡とか髭とかほくろとかも追加したかった。

### そのほか
- CodeSandboxがいつの間にか登録しないと使えなくなっていた、、、
- 顔のパーツの素材を見つけられなくて苦労してしまった。
- コンポーネント間の値の受け渡しやスタイルのバインディングの復習になりました。