No Regrets in Bathing

カレーを週に一度食っていく

SVG + Vueで有名なsdrasさんが日本に来るよ、という話

早いもので、Vue Fes Japanまで残すところ2週間程度となりました。

で。

何はおいてもsdrasさんですよ。来日です。

このブログの読者はSVG漬けの毎日を送っていると思うのですが、 SVGアニメーションといえば自分の中ではこの方です。

Sarah Drasner(sdras)さんは、VueConf 2017(katashinさんによるVueConf 2017 参加レポート)のトリでSVGアニメーションのプレゼンを行い、注目を浴びたことが記憶に新しいです。

この方がVue Fes Japan登壇のために来日します。SVG界震撼です。

www.youtube.com

発表では「なぜアニメーションが必要なのか。そしてどのように実装すればいいのか」が楽しく解説されています。 アニメーションの制御にはTweenMaxとVue.jsが利用されています。

私もこの発表に影響されてSVGを始めたので思い入れがあります。皆さんも未見であればぜひスライドだけでも見てください。スライド内のSVGインタラクティブに動かせます。

スライド:slides.com

sdrasさんのCodepenは楽しいぞ

ウォーリーがマウスカーソルを追ってグリグリ動きます。

codepen.io

ホームボタンを押すといい感じのSVGアニメーションが展開されます。

codepen.io

聞くところによるともともとFlasherだったそうで、このへんの作品はFlashっぽいですね。

Vue.js Londonのトップアニメーションもsdrasさん作です。

vuejs.london

sdrasさんのバックグラウンド

sdrasさんのバックグラウンドは「フロントエンドエンジニア」かつ「サイエンスイラストレーター」だそうです。イラストレーターとしての作品は下記サイトで見ることができます。

https://sarahdrasner.com/

どのイラストも緻密で圧倒されます。

もともと数学とアート両方に興味が強かったようで、一旦はアート方面で教鞭をとっていたそうです。

  • San Franciscoの漫画ミュージアムリテラシープログラム(?)を教えていた
  • ギリシャのHellenic International Studies in the Arts(HISA)で絵画・写真・芸術理論を教えていた
  • フィールド自然史博物館のサイエンスイラストレーター(爬虫類と両生類)
  • ビザンティン美術を教えていた

などなど、アートの人という感じですが、その後フロントエンドエンジニアとして働くようになり、現在に至ります。

デザインと実装両面をやっているという点では、Vue.jsの作者のEvanさんと似たものがありますね。(Evanさんも元々デザインを学んでいて、エンジニアとしてGoogleに入っています)

現在の肩書はMicrosoftのDeveloper Advocateです。これはEvangelistに近いものだそうで、アニメーションやサーバレスアーキテクチャ(Azure Functionsなど)を啓蒙する立場です。

Vue.js core teamメンバーとしての活動

sdrasさんはVue.js core teamメンバーでもあります。主にドキュメント周りに貢献されていて、目立ったところでは、公式ドキュメント内の「The Cookbook」をリードしました。

クックブックはExampleよりも実用的な例を提供するためのドキュメントで、今年から導入されたものです。内容は重厚かつ実用的で、一見の価値ありです。

その他の活動

そんなsdrasさん、Vue Fesに登壇します

発表内容はまだ公開されていませんが、近日中には公開されると思います。お楽しみに! (ちなみに私はスタッフなんで、当日見れるとは限らないんですが…)

追記 2018-10-18

発表内容公開されました!「Next-level Vue Animations」ということで、アニメーション絡みの発表になりそうですね!

vuefes.jp

プログラマー絵茶を開催した&リアルタイム共同開発した

f:id:hashrock:20180720124626p:plain

絵茶というのは、お絵かきチャットの略称で、一枚の共有キャンバスにみんなで絵を描くという遊びのこと。

今回は、Twitter上で人を募って2回ほど開催してみたという話。

なぜ開催した

絵を書きたいプログラマーがTL上に増えた気がした(N=2くらい)ので、勢いで開催した。

Twitterにいる人でキャラ絵を描けるようになってみたいって人は結構いるみたいで、そういう人たちをお絵かき勢に引きずり込みたいなぁとも思っていた。

どの絵茶を使うか問題

昔ながらの絵茶はJavaFlashで作られており、最近のブラウザでは動作しづらい。HTML5ベースの絵茶を探す必要があった。

また、人気のある絵茶サービスだった「pixiv chat」は去年終了し、セルシスが提供しているkakooyo!という絵茶サービスは最大4人までの制約があるのと、PCから描くことができないという問題があった。

まず最初に選択肢に上がったのはMagicalDrawで、これはChromeから使うのであれば一番良さそうだった。

MagicalDraw | お絵かきチャットレンタルサービス

しかし最近iPad + Apple Pencilを購入してこれで書きたかったのだが、どうもMagicalDrawはiOS環境だとかなり簡素なUIになってしまうのと、スクロールの挙動が若干怪しかった。

次に見つけたのがDraw.Chatという海外のサービス。

Draw.Chat - Virtual Classroom

これはなんとビデオチャットまでできる優れもの。描いている途中にiPadで文字チャットをするのはかなりだるく、音声チャットできると楽だなと思っていたので、これは良いものだと思う。

f:id:hashrock:20180720123648p:plain

第1回はこれで開催したのだが、問題があって、描画量が多くなるとどんどん重くなっていく。スクロールするだけでリドローが発生する。

あと多機能なせいで、初見の人がUIに戸惑う。興味持って見に来ただけの人がすぐ理解できるUIだったらいいのになぁと思った。

結局自作

第二回をやるにあたって、そもそもシンプルで安定したやつがほしいという思いが出てきてしまい、結局絵茶を自作することにした。

ゼロから作るのはつらいなと思ったので、GitHubからベースにできそうな絵茶実装を探して、下記のプロジェクトを元に作ることにした。

GitHub - romebop/whiteboard: interactive drawing & chatting

f:id:hashrock:20180720124315p:plain

変更点

まずは、描画スペースを広げてスクロール可能にした。

前回開催して思ったのが、絵を描いたことのない訪問者は基本的に見るだけで描かなくなってしまうという点だった。

多分、上手い人がガリガリ描いているスペースに絵を描き入れるのは緊張するのでは、と思ったので、右側にピクトチャットもどきを実装することにした。その結果が下記。

f:id:hashrock:20180720124000p:plain

第二回

自作絵茶を投入して第二回を開催したのだが、同時に試みとして「せっかく自作なんだからリアルタイムに開発する」という企画を行った。VSCode Live Shareという機能を使って、Twitterで相互フォローしてる人なら開発に参加できる体制にした。

これにはkiyopikkoさんが応じてくれて、チャットしている裏でゴリゴリCSSを編集してUIを改善して頂いた。

最初こんなのだったのが

f:id:hashrock:20180720124926p:plain

現在こうなった

f:id:hashrock:20180720124951p:plain

この変更は開催中に本番反映された。

Live Shareでの共同開発は本当に楽しいので、みんな体験した方が良いと思う。

もう一回くらい開催したい

なかなか参加者増えないなぁという感じはあるのだけど、絵茶自体は参加してもらえれば楽しいのがわかってもらえると思うので、もう一回くらいは開催してみてもいいかなと思っている。

興味ある方は@hashedrockをフォローしてください。やるときアナウンスします。やるなら多分7/26の22:00くらいかな。

また、絵茶作成自体に興味がある方は、下記のScrapboxに参加してください。

scrapbox.io

Vue.jsのFAQサイトを作ってみた

scrapbox.io

書いてはみたものの、かなり偏った考えかもしれないので、読むときには多少警戒しながら読んで下さい。あと、色々単純化している説明もあるんですが、まずい説明になっている所もあるかもしれません。こういうの、プルリクとか受け取れればいいんでしょうね。

コンテンツ置き場にはScrapboxを使っています。Scrapboxはどちらかと言うと複数人で書く時に威力を発揮するWikiみたいなものなので、書きたい人がいたらTwitterにリプ下さい。

経緯

  • Rails等のサーバサイドの経験がある人がSPAに初挑戦して、その際にVueを選択して詰まることが増えている模様
  • 考えてみれば、サーバサイドフレームワークからSPAへのスキルセットの移行が結構きつい
    • そこで闇を抱えてSPA嫌いになる人もいるっぽい
  • そういう場合、Vueだけの解説だと足りていなくて、Node.jsやwebpackやSPA等の周辺知識も教える教材かなにか必要なんじゃないか…と思った

のだけど、書いてみてもやっぱり範囲広すぎて書ききれないなぁ、という感じでした。難しいね。

フロントエンドの教材がどこにあるのかまとめがほしい感

あと、フロントエンドの上級者と初心者の乖離が激しいなぁとはずっと思っていて、HTMLを知らない人がフロントエンドの最前線までたどり着くのは相当辛いんじゃないでしょうか。それが専門職と言えばそれまでなんですが。

N高の教材とか、かなりいい教材は点在してるっぽいんですが、フロントエンド上級者の人はちょっと戻ってきて、自分の辿ってきた道に道しるべを置いてもらえると嬉しいです。

Excelシートを憎み、愛した男

Excelシートが憎い。

Excelシートでの書類作業の辛さは言わずもがな。

  • データベースもどき
  • アプリもどき
  • 帳票出力
  • Excelシート上でのコーディング
  • エビデンス作成
  • UMLなど

以上のものについて、すべてExcelでの作成経験がある。あの世にもExcelシートを作らされる地獄がきっと存在するだろう。

Excelシートが憎い。Excelの万能性ゆえ、落とし込まなくていいものまで落とし込まれ、地獄を生み出す。みんなExcelなら慣れてるので、その他の選択肢は選ばれない。何度かMarkdownからExcelにコンバートするようなツールを書いたけれど、書式が変われば捨てざるを得ない。結局今もExcelを書き続けている。辛い。

でも待って欲しい。あれほど一括編集をエレガントにこなせるUIが他にあるだろうか(2大エディタに習熟した場合を除く)。図も書ける。式は素人でも使えるが、プログラミングの一形態ですらある。Excelやっぱり凄いよ。こんな凄いものが存在するなんて信じられない。気がつくとExcelのことばかり考えている。Excelのことが本当は好きなのかも知れない。

だから、SVGExcelスプレッドシートを自作した。車輪の再発明だ。

f:id:hashrock:20180312013009g:plain

DEMOはこちらから

ロゴも作った。

https://user-images.githubusercontent.com/3132889/37255669-e971baf2-2592-11e8-823c-0dcadcb3b772.gif

リポジトリはこちら。

github.com

すでにhandsontableという、実用的なスプレッドシートコンポーネントが存在するため、 フルスクラッチで小さく書くのを目標にしている。

下記の通り、コンポーネントは1ファイルの.vueだけで書かれており、Vue以外への依存はない(…と思ったけど、考えたらrebootに依存してた。そのうちどうにかします)。今の所413行。

vue-spreadsheet-lite/SushiGrid.vue at master · anydown/vue-spreadsheet-lite · GitHub

結構頑張って作ったけど、機能不足やバグが多数あったり、そもそもまだコンポーネント単体としてnpmから使えないとか、いろいろな不備がある。まだ実用は出来ないので、ご容赦願いたい。

SVGとVueで難しいコンポーネントを作ろう

SVGとVue.jsの組み合わせが最高なのは下記の記事でも書いたとおり。身の回りでも多くの人がVue.js + SVG遊びに興じているのを観測している。

hashrock.hatenablog.com

もっと多くの人にVueとSVGを使って欲しいので、今回は複雑なものを作る時のTipsも足しておく。

スプレッドシートを作る手順

最初はまずSVGを手書きし、プロトタイピングするのをおすすめする。

ちょっと思い出しながら書いてるけど、初期のコミットは下記のようなコードだった。

<template>
  <svg width=500>
    <rect x=0 y=0 width=100 height=24>
    <text x=0 y=12 width=100 height=24>hoge</text>
    <rect x=100 y=0 width=100 height=24>
    <text x=100 y=12 width=100 height=24>fuga</text>
  </svg>
</template>
<style>
rect{
  fill: white;
  stroke: #999;
}
</style>
  • vue createで作成されるHello.vueファイルを編集しながら作り始める。
  • この時点でロジックはまったくない。SVGのrectやtextで作りたいものが出来るのかをまず検証する。
  • ある程度要素同士にまとまりが見えてきたら、g要素でグルーピングし、transform="translate(x, y)"の形に書き直す。

それから、Vueのdataに配列を入れて、v-forで要素を生成する。

コツは、やはり見た目から先に作り込むこと。特にSVGにはz-indexが無いため、書いた順に重ね合わせされるなどの罠が存在する。 自分はDIVなどのHTML要素でコンポーネントを作るときも、まずHTMLタグでモックアップを作ってから、後でロジックを差し込む作り方をするほうが多い。

その場編集(In-place editing)

要素をクリックして、その場で文字列を書き換えられるような仕組みをIn-place editingと呼ぶ。

In-place editingは知る限り下記の3つの方法がある。

  • contenteditable属性を使う
  • クリック後、要素の上にテキストフィールドを乗せる
  • 見えないテキストフィールド(opacity=0)を最初からコンポーネント上に置いておき、クリック位置に移動する

今回のスプレッドシートは、任意のタイミングでのキー入力もテキスト入力として扱わないといけないので、3番目の見えないテキストフィールドを採用した。2番目は付箋を作ったときに採用した。

In-place editingを作るときには、特にIMEの取扱に注意が必要で、ラテン語圏のOSSIMEを上手く扱えていないケースが多い。そもそも入力出来なかったり、変換確定のEnterキーで入力が終了してしまったり。 最近は同じくIMEを必要とする中国語圏のユーザがOSSに関わることが多くなったからか、状況は改善している。

選択範囲など

SVGはz-indexによる重なり順の制御が出来ないと書いたが、下記のように分類すれば大抵のケースでうまくいく。

f:id:hashrock:20180312022916p:plain

UIレイヤーは、選択範囲やボタン、ダイアログなどに当たる。ベジェハンドルやバウンディングボックスなどもここ。

コンテンツレイヤーは、編集対象のコンテンツに当たる。今回の場合であればセルの内容。

これら2つのレイヤーを重ね合わせることで、多くの問題が解決できる。具体的にはそれぞれをSVG要素でくくり、position: absoluteで同じ位置に配置してしまう。

UIとコンテンツを同じSFCの中にまとめてしまいがちだが、そうなると表示順の罠を踏むことになってしまう。 UIのような、クリッカブルな要素がコンテンツの下に来ることは、通常ありえないので、コンテンツと完全に分けてしまうという考え方になる。

今後の予定について

Biliでバンドルを作って、npmに公開したいと思っている。機能不足を解決したタイミングで頑張りたい。

github.com

あと、ちょっと作りかけているけど、markdown tableをスプレッドシート / テキストエリアで双方向に編集できるものも作りたい。下記はスペース区切りのもの。

f:id:hashrock:20180312030806g:plain

テキストからヘッダを生成する場合は、ヘッダの幅を自動算出しなくてはならない。ちょっと考えないといけない。

おわりに

Excelを追いかければ追いかけるほど、Excel作った奴らまじで凄いという感想しか出ない。今回作ったものをExcelにするには、複数の選択領域をサポートしたり、セル内の改行や結合セル、罫線、図、数式など、とんでもないカロリーの機能を実装しなくてはならない。

だからこそ、Excelは代替されにくいのだろう。互換ツールを作ることも難しいし、そのメリットも少ない。出来の良いツールが市場に居座ることで、そのツールに依存したエコシステムが形成され、誰も逃げられなくなってしまう。

あと、ツールに対して恨みごとを言いたくなってしまうときは、やはり車輪の再発明をしてみるべきなんだと思う。今回で自分はExcelを作った人に対する敬意が少し増したような気がする。作ってみなきゃ人の苦労は分からない。

まぁ、スプレッドシートの仕事が来たら、こんなんじゃなくて普通にhandsontable使おう。ちょっとでかいけどほんと良く出来てます。

vue-cliでビルドしたプロジェクトをgh-pagesにデプロイする

vue-cliでcreateしたプロジェクトは、そのままビルドすると、出力されたdist/index.html/js/vendor.a58fe84b.jsのように、絶対パスでアセットを読みに行く。

基本的にはこれで構わないケースが大半だけれど、Github Pagesにデプロイしたい場合は例外で、プロジェクト名と同じサブディレクトリ下に配置されてしまう。そうなると絶対パスから見に行くと404になってしまい、ページは動作しない。

相対パスからアセットを読みに行くようにする

こういったケースはbaseUrlオプションを設定することで回避出来る。下記のファイルを作成する。

vue.config.js

module.exports = {
  baseUrl: "./"
};

こうすると、(先の例でいうと)index.htmlが./js/vendor.a58fe84b.jsを読みに行くようになる。

アセットが色々存在するケースでは確認していないので、これではダメなケースもあるかもしれない。

vue.config.jsについては公式のドキュメントを参照のこと。

デプロイ

デプロイはどうするかというと、gh-pagesというツールを入れるのが楽。

#インストール
$ yarn add gh-pages --dev

でインストールした後、package.jsonのscriptsに下記の行を追加する。

"deploy": "gh-pages -d dist"

あとはyarn deployを実行するだけ。

動きとしては、まっさらなgh-pagesブランチを作成して、dist下のファイルをすべて配置するのと同じになる。

Github pagesはmasterやdocsフォルダをそのままWebページとして公開出来るように最近なっているが、ビルド成果物をコミットに含めたくない場合は、firebase hostingのようなホスティングサービスを使うか、旧来のgh-pagesブランチを使う形にするのが良いと思う。ちなみにこのやり方はegoist先生がやってたやり方。

気が散らない作業BGMサービス「#作業してくる」

普段のコーディング中のBGM、基本的にSoundCloudなんだけど、下記が不満だったりする。

  • まず最初に曲を見繕う作業で時間を10分とか使ってしまう
  • ずっと聞いてると気が散るイベントが発生する
    • 全然違うジャンルに飛ばされる
    • 今ひとつ音の合ってないマッシュアップが流れたりする
    • 探し方次第だけど、レーベルの宣伝用ラジオとかも入ってきてしまう事がある
  • DJMIXは気が散りにくくていいけど、なんか気分じゃない時がある
    • 多分踊るにはいいけど、長時間聞くには疲れる

こういう感じで、曲を飛ばす作業が発生してコーディングが中断してしまうということがよくあった。

環境音は猫が最強

で、環境音が良さそうということで、色々試していた。

www.noisli.com

ここがそれなりに良いのだけど、環境音でもイライラしたりすると気が散ることがあった。「何このせせらぎ、オフィスに川なんてねえぞ!イライラしてきた!!!!」みたいな感じで。

で、環境音系で一番使ってたのはここ。

purrli.com

こっちのほうが良いです。猫がゴロゴロ言ってるのを延々と聞ける。youtubeにも似たコンセプトの動画が上がってるけどそれもリアリティがあって良いです。なんか、膝上に猫が来て思う存分くつろいでて、 自分もなんか西日とかで温くなってしまって、やることあるんだけど動けなくて一緒に寝ちゃうみたいな、最高なやつをVR体験出来ます。今思ったけど、膝に何か重いものを置くといいだろうな。

でもこれでリラックス出来るのは猫ユーザーだけだと思う。

「作業してくる」の認知負荷の低さ

しかしメロディが欲しいし、昔のMIDIが恋しいなと思っていた所で、「#作業してくる」というサービスが公開された。(曲提供したのでダイマ気味だけど)

f:id:hashrock:20171211010543p:plain

sitekuru.net

ここ数日使ってるけど良いです。

何が良いかというと、とにかく聞いていて認知負荷が低い。作業してくる自体のことを意識することがほとんどない。

  • 曲数が多くて100曲くらいある
  • 曲の雰囲気やテンポが揃っている
    • 時間帯ごとにテーマが決まっている
    • 激しい曲は深夜など、特定の時間帯に流れるようにまとめられている
  • 全体的に打ち込みっぽくて、ボーカルがない
  • ループがシームレス(WebAudioでループさせているらしい)

特に、曲間の空白が気にならないというのは本当に良い!

全体的にどうぶつの森みたいな、ほっとする感じのゲームBGMっぽいのが多くて、自分は好きな感じの曲が多いかな。 1曲気に入ったらだいたい全部気に入るだろうし、1曲合わなかったらほとんど合わないと思う。 これは、企画時にリファレンス楽曲が提示されていて、雰囲気合わせが上手く行ったということだと思う。

サイトの企画者は「cagpie」さんという人で、わずか1ヶ月の間に100人以上の作曲者を集めて、かなりの曲数が集まった。おそらくその多くが書き下ろしだと思う。 下記の募集告知からどういう企画だったかが窺い知れる。

作業用BGM垂れ流しサイト「#作業してくる」の楽曲募集! - TwiPla

技術的なことに関しては下記に書いてある。

qiita.com

cagpieさんは、picotuneの作者でもあったりと、多才だしこれからが楽しみ。

ちなみに、曲一覧は右下の「配信楽曲一覧」で出せて、そこから曲名直接クリックでも聞ける。

f:id:hashrock:20171211015834p:plain

f:id:hashrock:20171211015916p:plain

今のところ考えた作業BGMの流れ

やっぱり気分に応じて色々使い分けられるようにするのが良さそう。

  • とりあえずやる気が無いときは、SoundCloudのお気に入りとかハードコアテクノとかを流して気付けをする
  • 猫のゴロゴロを徐々にミックスし、落ち着いて資料などを眺めて計画を練る
  • 作業内容が決まったら、作業してくるを立ち上げ、slackの分報チャンネルに作業開始宣言

って感じですかね。あとはamazon musicとかのストリーミングサービスもいいと思う。みんなのおすすめがあればtwitterにリプしてください。

グリグリ動くUIをVueとSVGでサクッと書く

これは Vue.js #3 Advent Calendar 2017 – Qiita 4日目の記事です。

こんにちは。SVGで色々なコンポーネントを作っているものです。最近の作品は下記のような感じです。

f:id:hashrock:20171204200705g:plain

f:id:hashrock:20171204200933g:plain

Webでグリグリ動くUIを作りたい!!という一心でやっています。

これらはほとんどSVGとVueの組み合わせのみで作っています。依存が少ないというのは大事で、ライブラリ間の相性でハマったり、いろんなドキュメント間を往復することがなくなります。

Webでグリグリ動くUIを作るのは基本的にめんどくさいです。jQuery pluginを駆使して作るのも闇が多いですし、divやcanvasをゴリゴリするのも結構手間がかかります。

ですが、最近はSVGで高度なUI実装されることが増えてきた気がします。特に自分が衝撃を受けたのは、CacooがFlashからSVGにスイッチしたことです。

nulab-inc.com

SVGに遅いイメージを持っていた自分にとってこのニュースは衝撃的で、SVGやれば出来るじゃん!と勇気づけられました。というわけで、VueがSVGを標準で扱えることもあって、最近はSVGのポテンシャルを試していたわけです。他にもMSのSarahさんのVueConfでの発表もきっかけの一つでした。

SVGcanvasに比べて出来ることが多いわけではないのですが、だいぶ実装の手数が削減できます。サクッと実装できるかどうかの差は大きく、僕はこれでグラフィカルなUIを書こうというモチベーションが湧いてくるようになりました。 ※個人の感想です

SVGの基本的な使い方&バインディング

で、どのくらいサクッとなのかというと、例えば線を引きたければ、下記のように書くだけです。

<svg viewbox="0 0 300 300" width="300" height="300">
  <line x1=100 y1=100 x2=200 y2=200 stroke="black"></line>
</svg>

f:id:hashrock:20171204203229p:plain

で、canvasとは違って、この線はDOM要素なので、Vue.jsを使うとバインディングが効きます。すなわちこういうことが出来ます。

f:id:hashrock:20171204203728g:plain

コードはこれだけです。

<div id="app">
  <svg viewbox="0 0 300 300" width="300" height="300">
    <line :x1="x1" y1=100 x2=200 y2=200 stroke="black"></line>
  </svg>
  <div>
    <input type="range" v-model="x1">
  </div>
</div>
<script>
  new Vue({
    el: "#app",
    data: {
      x1: 100
    }
  })
</script>

バインディングが出来るフレームワークであれば、VueでなくてもReactでもRiotでもElmでもいいのですが、とにかくSVGバインディングとの相性が良いです。バインディングだらけになるとスパゲッティになる懸念がありますが、コンポーネントに切り分けることである程度防ぐことが出来ます。

SVG要素にイベントリスナをつける

また、SVG要素はイベントリスナをひっつけられます。例えば円をクリックした時にmethodを呼びたければ、これだけで良いです。

<circle @click="myMethod" cx=100 cy=100 r=50></circle>

これを利用して、クリックした時にトグルする何かを作りました。

f:id:hashrock:20171204211409g:plain

<svg viewbox="0 0 300 300" width="300" height="300">
  <circle r=50 cx=150 cy=150 @click="active = !active" :class="{'active': active}"></circle>
</svg>
new Vue({
  el: "#app",
  data: {
    active: false
  }
})
circle{
  fill: #333;
  transition: all 0.4s cubic-bezier(.96,.04,.04,.96);
  stroke: rgb(119, 0, 255);
  stroke-width: 1px;
}
.active{
  fill: white;
  stroke-width: 50px;
}

クリックした時に、active変数をトグルし、連動してclassもトグルさせています。で、切り替わる時にCSSアニメーションさせています。楽しいですね。

2017-12-05追記:IE11ではSVG要素のCSS Transitionは動かないそうなので、プロダクションで使う方はご注意下さい。

更に複雑なUIを作るには

以前書いた記事の中で、ヒントになりそうなものをピックアップしました。どれもVue + SVGでの実装です。

また、SVG要素に精通するのが大事です。MDNのSVG要素リファレンスを熟読しましょう。

  • コンポーネントとしてSVG要素をまとめる際は、groupという要素でラップします。groupにxやyという属性はなく、transform属性で変形する必要があります。
  • SVG子要素でクリック位置を取得する場合は、offsetX / offsetYの解釈がIE+Chrome / Firefoxで異なることに注意する必要があります。offsetX / offsetYは使わないほうが無難です。

終わりに

さて、高度なUIといえばドラッグ&ドロップですが、ざっくり言うとmousedown, mousemove, mouseupを各要素に付けてよしなにします。これに関しては紹介すると長くなるので、またいつかやり方を書こうと思います。

ドラッガブルな要素の実装についてはまだ研究中で、シンプルに書く方法を見いだせていません。ただカスタムディレクティブでさっくり行けるんじゃないかという手応えは感じています。一緒に研究してくれる仲間を募集しています。

おまけ

最後に、この記事を読んでSVGをやってみたくなった人に向けて、雛形HTMLを作ったので置いていきます。

svg-sandbox.html · GitHub

よく使うSVG要素を幾つか表示させているので、属性をいじるなり、Vueとバインドさせるなりさせてみてください。

f:id:hashrock:20171204214411p:plain

上記に表示されている基本図形の組み合わせで表現できるUIを考えて、実装してみるのがおすすめです。

ボツネタ

この記事を書くにあたって、無駄に作りかけてしまったSVGエディタです。何も使ってないじゃん。人間は愚かだ…

f:id:hashrock:20171204214737g:plain