4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

vue.jsのhooperでスライドを実装する

Last updated at Posted at 2020-04-11

vue.jsでスライドを実装するにはhooperというlibraryが便利でした。

前提

今回使用するのは、vue-cli4とhooperです。

まず、vue-cli4を使えるようにします。最新を入れればいいですが、この情報が古くなった場合、4です。次に、hooperをpackage.jsonに追加します。

$ yarn global add @vue/cli
$ vue create sample-vue-project
$ cd sample-vue-project
$ yarn add hooper

$ cat package.json

package.jsonはこんな感じです。コピーして、yarn installしてもいいです。これでyarn installとかすると、依存関係がインストールできます。

package.json
{
  "name": "sample-vue-project",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^3.6.4",
    "hooper": "^0.3.4",
    "vue": "^2.6.11"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.3.0",
    "@vue/cli-plugin-eslint": "~4.3.0",
    "@vue/cli-service": "~4.3.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^6.2.2",
    "vue-template-compiler": "^2.6.11"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}

vue

まず、vue.jsの使い方を簡単に説明します。

vueはsrc/main.jssrc/App.vue,src/index.htmlなどを書いてbuildします。

$ yarn serve
$ yarn build

デフォルトでは、distにファイルが置かれます。なお、root pathはpublicになっています。例えば、https://example.com/path/to/img.pngを使いたければ、public/path/to/img.pngにファイルを置いて、App.vueには/path/to/img.pngと記述します。

次に、vue-cliですが、env(環境変数)を使う際は、.envVUE_APP_XXX=10などと書いて、App.vueなどにはprocess.env.VUE_APP_XXXとすることで環境変数を使えます。

hooper

docsのexampleがわかりやすいですね。最小構成は以下です。大体わかると思いますが、オプションなども用意されていますので、そのあたりは後述します。

src/App.vue
// https://baianat.github.io/hooper/examples.html#default-example
<template>
  <hooper>
    <slide>
      slide 1
    </slide>
    <slide>
      slide 2
    </slide>
    <hooper-navigation slot="hooper-addons"></hooper-navigation>
  </hooper>
</template>

<script>
import {
  Hooper,
  Slide,
  Navigation as HooperNavigation
  } from 'hooper';

export default {
  components: {
    Hooper,
    Slide,
    HooperNavigation
  }
}
</script>
src/mani.js
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App)
}).$mount('#app')

hooperでの実装例

私の場合は、画像をスライドさせているので以下のような感じになりました。後で個別に解説します。

src/App.vue
<template>
  <hooper :settings="hooperSettings">
    <slide v-for="(n,index) of products" :key="n">
     <img :src="'/manga/'+ (index) +'.png'" />
     <div class="page_n">{{ n }}</div>
    </slide>
    <hooper-navigation slot="hooper-addons"></hooper-navigation>
    <hooper-pagination slot="hooper-addons"></hooper-pagination>
    <hooper-progress slot="hooper-addons"></hooper-progress>
  </hooper>
</template>

<script>
import {
  Hooper,
  Slide,
  Progress as HooperProgress,
  Pagination as HooperPagination,
  Navigation as HooperNavigation
} from 'hooper';

import 'hooper/dist/hooper.css';

export default {
  name: 'App',
  components: {
    Hooper,
    Slide,
    HooperProgress,
    HooperPagination,
    HooperNavigation
  },
  data() {
    return {
      products: [...Array(Number(process.env.VUE_APP_PAGE)).keys()],
      hooperSettings: {
        itemsToShow: 1,
        centerMode: true
      }
    };
  }
};
</script>

<style>
.hooper {
	height: 100%;
}
button.hooper-indicator {
	background-color: #000;
}
img {
	width:640px;
}
.page_n {
	text-align: center;
	height: 50px;
}
</style>

hooperのslideをloopで書く

わざわざslideを一つずつ用意するのは面倒ですので、通常はfor,bindなどでloop処理を書くことになると思います。あるいは配列を持ってくるなど。以下は必要な部分の記述です。

src/App.vue
<template>
  <hooper :settings="hooperSettings">
    <slide v-for="(n,index) of products" :key="n">
     <img :src="'/manga/'+ (index) +'.png'" />
     <div class="page_n">{{ n }}</div>
    </slide>
  </hooper>
</template>

export default {
  name: 'App',
  components: {
    Hooper
  },
  data() {
    return {
      products: [...Array(Number(process.env.VUE_APP_PAGE)).keys()]
    };
  }
};

何をしているのかというと、環境変数のVUE_APP_PAGEからdata{products}にページ数を入れます。文字列なので数字に変換、それをslideにてループ。

スライドするのは、対応した画像ファイル、/manga/0.png,/manga/1.pngなどを順番にスライドさせます。画像ファイルは、/public/manga/0.pngなどの場所に置きます。

v-forは(n,index) of productsのように書きますが、(n,index)の部分は、n of productsでもいいです。indexにも数が入ってます。ここでn,に続く記述はvueのオプション(vueが用意する変数)のようなものです。

hooperのoption

hooperには様々なbarなどが用意されています。基本的にはこんな感じで使います。

src/App.vue
<template>
  <hooper :settings="hooperSettings">
    // 上の全体位置を示すバー
    <hooper-navigation slot="hooper-addons"></hooper-navigation>
    // ページ、戻る、進むのボタン
    <hooper-pagination slot="hooper-addons"></hooper-pagination>
    // 下の全体位置を示す個別ボタン
    <hooper-progress slot="hooper-addons"></hooper-progress>
  </hooper>
</template>

import {
  Hooper,
  Slide,
  Progress as HooperProgress,
  Pagination as HooperPagination,
  Navigation as HooperNavigation
} from 'hooper';

hooperのslideにて指定コンテンツを使う

この場合のスライド出力は、0 - Foo, 1 - Barとなります。data{items}を変更すればいいでしょう。vueのexampleを参考にしましょう。

App.vue
<template>
  <hooper :settings="hooperSettings">
    <slide v-for="(item, index) in items">
    {{ index }} - {{ item.message }}
    </slide>
  </hooper>
</template>

<script>
import {
  Hooper,
  Slide
} from 'hooper';

import 'hooper/dist/hooper.css';

export default {
  name: 'App',
  components: {
    Hooper,
    Slide
  },
  data() {
    return {
      items: [
      { message: 'Foo' },
      { message: 'Bar' }
    	]
    };
  }
};
</script>

gh-pages + hugoとの連携

build後のファイルはデフォルトでハッシュ値をつけるので、vue.config.jsで固定したあとに、gh-actionsを書いていきます。

vue.config.js
module.exports = {
  configureWebpack: {
    output: {
      filename: '[name].js',
      chunkFilename: '[name].js'
    }
  },
  css: {
    extract: {
      filename: '[name].css',
      chunkFilename: '[name].css'
    },
  },
}

私の場合は、非常にシンプルに、こんな感じになります。これはhugoを使っている場合で少し特殊ですが、ようは、VUE_APP_XXXに自動で画像ファイル数を入れる処理を書いて、build後に出力される必要なファイルを必要な場所にコピーしています。もちろん、buildオプションを指定して直接置くようにしてもいいです。その場合、コピー処理は不要です。

.github/workflows/gh-pages.yml
      run: |
           echo VUE_APP_PAGE=`ls ./static/manga/*.png|wc -l` > .env
           yarn build
           cp -rf ./dist/*.js ./static/manga
           cp -rf ./dist/*.css ./static/manga
           cp -rf ./dist/*.map ./static/manga

私は、hugoを使っているので、以下のように構成しています。

content/manga.md
---
title: "yui | MANGA"
type: manga
page_image : "https://syui.cf/icon/ai.png"
description: "惑星で暮らすドラゴンと少女のお話"
---

<div id=app></div>
<script src=/manga/chunk-vendors.js></script>
<script src=/manga/app.js></script>
layouts/manga/single.html
{{ partial "head-blog.html" . }}
{{ partial "header.html" . }}
{{ partial "manga-css.html" . }}
		<main>
		{{ .Content }}
		</main>
		</div>
		{{ partial "footer.html" . }}
	</body>
</html>
layouts/partials/manga-css.html
<link href=/manga/app.css rel=preload as=style>
<link href=/manga/app.js rel=preload as=script>
<link href=/manga/chunk-vendors.css rel=preload as=style>
<link href=/manga/chunk-vendors.js rel=preload as=script>
<link href=/manga/chunk-vendors.css rel=stylesheet>
<link href=/manga/app.css rel=stylesheet>

つまり、yarn buildしてできたdist/index.htmlの内容をhugoの必要な場所に置き換えます。dist/index.htmlは通常、buildしても内容が変わるものではありません。よって、hugoのほうに記述しても問題ないのです。

4
0
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
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?