Storybookを使ってCanvasアニメーションのパラメータを調整する(Vue版)

sample.gif

最近Storybookというコンポーネント単位でデザインの確認などが行えるツールがあることを知りました。このツールをリサーチしてみて、現在開発しているプロジェクトでアニメーションのパラメータなどの設定を調整するのにちょうど良いと思い、サンプルを作ってみました。


Storybookのセットアップとエラー対処

StorybookはVueにも対応していますが、当初はReact向けに作られたようで、Vue向けのガイドラインがあまり充実していない部分もあると感じます。私はこちらの記事を参考にセットアップしました。ただ、記事内のwebpack.config.jsだと私の環境ではうまく動作しなかったため、少し変更しています。おそらくstylus関連だと思います。loadersをごっそり削除したらnpm run storybookでStorybookが起動しました。

Storybookが無事起動できてホッとしていたら、npm run devでエラー。。。

npm ERR! code ELIFECYCLE

npm ERR! errno 1
npm ERR! carousel-motion@1.0.0 dev: `webpack-dev-server --inline --progress --config build/webpack.dev.conf.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the carousel-motion@1.0.0 dev script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

詳しく調べていませんが、storybook/cliのバージョンを落としたら大丈夫でした。

- "@storybook/cli": "^4.1.4",

+ "@storybook/cli": "^3.2.17",


Canvasアニメーション

StorybookではVueのpropsに値を渡してスタイルガイドの変更を行う仕組みになっているので、Canvasアニメーションのスピードやサイズなどの各種パラメーターをこのpropsで管理しておけば、Storybook上で調整できます。


src/stories/index.js

...

storiesOf('CarouselMotion', module)
.addDecorator(withKnobs)
.add('Simple', withNotes(
`
column: レーンの数
lineSpace: 行間
`

)(() => {
const column = number('column', 12)
const lineSpace = number('lineSpace', 5)

return {
components: { CarouselMotion },
template: `<carousel-motion :column="${column}" :lineSpace="${lineSpace}"/>`
}
}))

...



スマートフォン対応

Storybookには様々なaddonがありますが、ViewPortの切り替えにはaddon-viewportというaddonがよく使われているようです。このaddonを入れるだけで、Storybook内にViewPortを切り替えるボタンが出現し、iPhone6やiPhon6 Plusなど各端末サイズやPortrait, Landscapeといった端末の向きを変更することができます。このStorybookの仕組みは、iframe内に自分のVueプロジェクトがhtmlとして埋め込まれる仕組みになっているようです。埋め込まれたプロジェクトのhtmlですが、デフォルトでmargin 8pxがついていて、なおかつスマートフォンモードだとbodyサイズが上手く取得できずレイアウトが崩れてしまいます。調べたところ、.storybookフォルダにpreview-head.htmlというファイルを作成すると、iframeのhtmlのスタイルを変更できるようなので、以下のように設定して解消しました。


.storybook/preview-head.html

<style type="text/css">

body {
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
}
</style>

また、現状だとViewPortを切り替えてもCanvasサイズは自動で変更されないため、デバッグモード時だけViewPortの切り替えをフックして、Canvasサイズを再設定するようにしました。ここで少しハマったのが、iframe内にあるとscreenサイズが正しい値を返してくれず(おそらくPCサイトのサイズになっている)、デバッグモードだけCanvasサイズの設定を変更しています。


Canvasアニメーションのコンポーネント

<template>

<canvas id="world" :width=screenWidth :height=screenHeight></canvas>
</template>

<script>
props: {
...

isDebug: {
type: Boolean,
default: false
}

...
},
computed: {
...

screenWidth () {
return this.isDebug ? window.innerWidth * 2 : window.screen.width * 2
},
screenHeight () {
return this.isDebug ? window.innerHeight * 2 : window.screen.height * 2
}

...
},
mounted () {

...

if (this.isDebug) {
window.addEventListener('resize', this.handleResize)
}

...

},
methods: {
handleResize () {
this.resetCanvasSize ()

// NOTE: Other initialization code here
},
resetCanvasSize () {
const canvas = this.canvas
canvas.width = window.innerWidth * 2
canvas.height = window.innerHeight * 2
canvas.style.width = String(canvas.width / 2) + 'px'
canvas.style.height = String(canvas.height / 2) + 'px'
}
}
</script>


サンプルコードはGitHubに置いてあります。