version5系による左右中央寄せ・縦書きカルーセルの実装例JavaScriptVue.js投稿日:2019-12-09最終更新:2020-02-03筆者のブログで記事をみる何の記事?趣味で短歌の投稿サイトをやっていて、それで実装した縦書きのカルーセルの話です。JSfiddletategakibunko/nehan.jsを使ってHTML文字列を差し込んでつくった縦書きのブロック要素をSwiperでカルーセルにしています。こんなものを作ったのでしょう。ようするにこういうUIを作りたかったからなのですが、我ながらもっとやり方があるのではないかと思うところもあります。CSS3の縦書きはとても便利に進化しています。こだわりがないならwriting-modeプロパティを使えばいいと思います。縦書きに関連するCSSプロパティの実装状況にはブラウザによってまだ足並みの揃っていない部分があり、いろいろな環境を用意しつつ実際の表示を確認するのはとても大変です。文芸作品を扱うサイトにとってとりわけ致命的なのが縦中横の表示です。一般にtext-orientationプロパティの指定に関係なく複数の英数字や記号を1文字分に詰めて表示するにはtext-combine-uprightプロパティを個別に指定する必要があります。ふつうに考えると、縦中横にしたい部分にスタイルを当てるためにはいちいちタグで囲む必要があります。3という風な書き方が用意されていますが、これは2019年12月現在でほとんどのブラウザが壊滅的に対応していません。digits自分でHTMLを書くなら縦中横にしたい部分をマークアップすればよいのですが、ユーザーが投稿したコンテンツを差し込む場合にはそうもいきません。いわゆる全角文字は「東アジアの文字」とみなします。英数字、記号、スペースは「東アジア以外の文字」とみなします。#50にて定義されています。全角の疑問符や感嘆符が並ぶ場合や、数字の前後に特定の記号が来る場合の例外もあります。Blogにつらつらと書かれているのを見ると、これを全部自分で書くのはつらいわと思うわけです。技術的にがんばったところnehan.jsの採用例が見つからないnehan.jsはHTMLを縦書きにするためのJSライブラリのひとつです。nehanという名前のライブラリはtategakibunko/nehan.jsとして公開されているversion<=5.系からtategakibunko/nehanとして公開されているversion>6.系へと開発が移行しており、5.系は、まあいい意味に捉えるとstableなライブラリです。minifyされているのにJSファイルだけで236kbもありますが、縦中横から禁則処理までよしなにこなしてくれます。JSDocこそちゃんと見つかるのですが、逆にこれとデモくらいしか情報がなかったので雰囲気で使いました。件の短歌の投稿サイトはNuxt.js+Expressのプロダクトです。nehan.jsによる縦書きのカルーセルを実装するにあたって、まず以下のようなNehanコンポーネントを用意しています。Vanillaに書ける気がしますが、横着なのでjQueryとUnderscoreはすでに読み込んでいる前提です。</style>肝心のnehanオブジェクトはdataのなかに持っています。}のなかで文字列にcoerceしたうえでv-nehanというカスタムディレクティブに渡して描画します。}という無駄っぽい何かを挟んでいるのは、これを書いた当初にitempropsを非同期に差し替えたりしていた名残です。v-nehanディレクティブは、まあ、見たままな感じです。ユーザーが投稿した文字列は当然サーバサイドでサニタイズしていますが、vnode.context.checkHTML(binding.value)でvalidなHTML文字列かどうかを簡単にチェックしています。CSSが気持ち悪い点には眼をつぶっています。SwiperでカルーセルにするSwiperは言わずとしれたリッチなスライダーを設置できるJSライブラリです。SSR対応であり、surmon-china/vue-awesome-swiperといったVueコンポーネントも開発されています。nehan.jsは当然SSR非対応だし、vue-awesome-swiperはスライドそのものがswiperSlideというコンポーネントになっていて、これに自前のコンポーネントをネストするメリットはとくにない気がしたため、今回は生のSwiperを触っています。slideとして登録したのが上のNehanコンポーネントです。</script>mixinは以下のような感じです。今回はslidesの中身が動的に書き換わることはないのですが、slidesを差し替えたりする場合にはそのタイミングでmySwiper(this.slides)を呼んでSwiperインスタンスを更新する必要があります(swiperInstance.destory()してからnewしていますが、ドキュメントを確認したらswiperInstance.update()というメソッドがふつうにあったのでこれを使ったほうがよいかもしれません)。雰囲気的に$data.slidesではなくここで書いた$data.virtualData.slidesのほうをv-forするのが正しい気がしますが、カスタムディレクティブのhookがよくわからなくてv-nehanディレクティブを上手く更新できなかったので$data.slidesをv-forしています。Qrunch.netサーバー提供フィードバックを送信する。