祖父との思い出。
特に理由があるわけではないけれど、なんとなく書いておこうと思う。
母方の祖父について。
今、祖父の通夜、葬式のために地元に向かっている。
片道6時間の長い旅路。
新しい会社に入ったばかりなのに早速、慶弔休暇を取得することになった。
通夜は明日、2019/03/25、式は明後日2019/03/26。
この記事を書くことは先日から決めていた。今、思い出せることや考えていことのログを残したいと思った。
久しぶりの文章なので、まるでまとまっていないけれど、とりとめのない形でもいつか自分がまた読み返したときに、祖父のことを思いだすきっかけになればいい。
訃報を聞いたとき、仕事の上司には近日中にそういうことがあるかもしれないということを伝えた日だった。
思ったより早いなと思った。夕方だった。
どうしようと思った。帰らなきゃという思いがあるくせに仕事のことを考えたりしていた。もう少ししたら帰ろうとか、そんなことを考えていた。
2019/03/22。とりあえず何をすればいいかわからなかった。変に仕事のことを考えたり、コードを眺めたりしたが、何も頭に入ってこなかった。
前日飲んでいたせいかもしれないし、覚悟していたとはいえ、思った以上にショックを受けたのかもしれない。
帰宅可能時間なので、とりあえず帰った。帰りながら、ちゃんとパソコンをしまったかどうかがやたら気になった。
最初に容態が良くないという連絡を聞いたのは先週の土曜日だった。その日は先輩が出演するノイズイベントを見に行く予定だった。
友達との待ち合わせのときに、親から電話があり、体調がずいぶん悪いことを知った。おそらく長くないだろう、それもかなり早いはずだ、要約するとそんな内容だった。
僕は今年のGWの10連休を帰省に当てるつもりだったので、それまで持ちそうか聞いた。わからないと答えた。恐らく無理だな、と言った。
祖父との思い出は多い。幼いとき共働きの親の預け先だったこともあるし、両親と母方の実家は仲が良かったので、頻繁に遊びに行っていた。
完全におじいちゃん子だった。僕も、おそらく妹も。
母の妹の子も、祖父の家によくいた。また、それらも例外なくおじいちゃん子だったように思う。
祖母は癖が強い。癖が強いが今になってはそれが面白い。
だが、それ故に祖父への思いが募りやすかったのかもしれないが。
祖母は色んな所へ出たがった。外交的な性格だ。だけど祖父は家にずっといた。ほとんど一緒には行かなかった。
それがなぜなのか僕にはわからなかった。今こうして思い返してみると、祖父がなんの仕事をしていたのかも知らないし、実は祖父のことを何も知らなかったなと思う。
——
なんとなく、この文章を書こうと思ったのは、僕が知っている祖父の情報と、祖父との今思い出せる限りの思い出を列挙しておきたいと思ったからだ。今しなければ、思い出せなくなることも多いと思うし、僕は祖父を覚えていたい。
祖父がしらない、パソコンというものを使って、祖父のことを記録するこの作業は、少し不思議な気がするけれど、自分のために、この作業しておきたい。
そういうわけで、以下。
- 祖父は禿げていた
- 頭頂部から進行するタイプで、ザビエルのようだった。
- それを気にしていたのかは知らないが、いつも帽子をかぶっていた。
- 水色の帽子。
- 釣りが好きだった。
- 好きとはいっても川で釣るという感じだった。
- 一緒に行ったことがあるような気がするが、ないような気もする
- 移動手段は自転車だった。
- 後ろに乗せてもらって、スーパー(近くの原信、前は違う名前のスーパーだった気がする。丸井だったか。)によく行った。
- ただ、後に足をわるくして乗れなくなった。
- 10年以内の出来事だ。
- 後ろに乗せてもらって、スーパー(近くの原信、前は違う名前のスーパーだった気がする。丸井だったか。)によく行った。
- 野球が好きだった。
- 多分。行くと僕たちがテレビを占領してしまう。
- 夏に行くと甲子園をよく見ていた。
- 新潟勢は以前は弱かったため、早く負けるとお金がかからなくて良いと言っていた。
- 字がうまかった。年齢を重ねた人は、基本字がうまい。
- 煙草を吸っていた。
- 酒をよく飲んでいた。
- 糖尿もやっていたが、致命的ではなかったようだ。
- 入院して、でてきて酒を飲んで転んでまた病院に行くという事があったと思う。
- よく兄弟だというタケオおじさんも来て、飲んでいた。
- タケオおじさんは頭にイボがある人だった。
- ガンでなくなった
- なくなる少し前、酔って高校生になった久しぶりの僕をみて、でかくなったな、抱っこさせてくれと行って無理やり膝の上に座らされた。
- その後、誰だお前は、と言われた。
- いい音のおならをしていた
- それが面白くて、子供の頃よく笑った。
- 寝転んで、新聞やらテレビを見ていた。
- 方言がかなり強かった。
- 今では若干わからないこともある
- 料理がうまかった。
- エビフライや鮭の焼いたやつがいつも作られていた。
- 子供の頃はそれに飽きていたが、今年久しぶりに食べたらすごく美味しかった。もっと食べればよかった。
- 椎茸の煮付けを僕が好きだったのでよく作ってくれた。
- スクランブルエッグがすごく美味しかった
- この記憶があるのは何故か僕だけみたいなので、妄想かもしれない
- カレイの煮つけがとにかく最高だった。
- これを食べられなくなることは、本当に悲しいことだ。
- エビフライや鮭の焼いたやつがいつも作られていた。
- 昔一緒に海に行った
- 手指の準備運動をしていた。
- 横泳ぎが得意だった。(イカ泳ぎと言っていた気もする)
- 祖父の家に行くと食べ物が死ぬほど出された
- 寿司、刺し身、うなぎと得意料理が山のようにあった。
- うなぎのありがたみがわからなくて、当時あまり好きでなくなった。
- 年末に帰ると狂った量の寿司が振る舞われた。それを食べると年をこすという気持ちになる。
- 寿司、刺し身、うなぎと得意料理が山のようにあった。
- 大学に入って帰ってきたくらいの頃に、一瞬政治の話になった。僕は割と当時右傾化した考えを持っていたが、祖父は共産党支持者だった。僕とそんな話ができて嬉しいと言って笑ってた。
- 途中白内障をやったことがあった。心配した。
- 最後までしっかりした人だった。
- 祖母には異常に厳しかった。
- 祖母はただ、癖がかなり強いのでわからなくもないが、厳しいなと思うことも多かった。
- 僕たちをきちんと叱ってくれた。
- 大きくて、どっしりとした人だった。
- 将棋を教えてくれた。
- 毎回お小遣いをくれた。
- 祖父の自転車の後ろに乗ってスーパーに行く道中に、朽木があったので、クワガタの幼虫がいないか、寄らせてもらった。
- 珍しく弥彦神社で行われた菊展かなにかに祖父もいった。その時みんなで撮った写真がカレンダーになっていて、しばらくかけてあった。
- 高校生の頃、友達と原チャで会いにいた。
- 小さい頃泊まったときに布団の中で聞く、台所で片付けをしながら歌う祖父の鼻歌が妙に落ち着いた。
- ストーブの上のヤカンとお餅。
- 朝起きると寒くて、急いでストーブの前で着替えた。
- 近くで火事があって一緒に見に行った。
- ゴミ収集車を祖父に抱っこされながら見た。
- 電車を見に連れて行ってくれた。
すべて思い出。本当かどうかもわからない。 きっともっといっぱい無数にあるはずなのに、これしか今、思い浮かばない。
酒が好きだった。物心つくと祖父と親父が大量に酒を飲んで、親父が前後不覚になることが多かった。祖父が酩酊してるのはあまり記憶にない。僕が将棋を覚えた頃、酔った祖父と将棋をした記憶がある。親父ともした。
親父も祖父もすごく楽しそうだった。僕は妹や母たちとあそぶなり、絵本を読むなり、テレビを見るなりしていた。
今ならわかるが、たくさんの孫に囲まれて飲む酒は最高に美味しかったろうと思う。
僕は18で家を出た。出てから年に多くても2、3度の帰省、その度に会いに行ったということもないので、それからは、数えるほどしかあってない。
でも年末に帰ったときは必ず行っていた。そこで食べ切れない量のお寿司を食べた。だけど、なんとなく気恥ずかしくて、僕はお酒をあまり飲まなかった。その後友達と会うからとかなんとか言って、あまり飲まなかった。
それを今、一番後悔している。
小さい頃、消防車のおもちゃを買ってもらった帰りに、近くにある大きな神社によった。そこで何か大きな石(狛犬のようなもの)に僕が腰掛けて、祖父にむかってその消防車を放った。祖父は困った顔していた。
結婚することを報告できたことはよかった。ひ孫にも会ってもらえた。
嫁と二人、祖父母の家を訪ねた。その時どんな会話をするべきかわからないなと、不安になったことが悲しかった。
ひ孫が最初会いに行ったときは病院だった。その時は胃潰瘍か何かであまり良くない状態だった。ひ孫は病院が嫌いなもので大泣きして吐いた(よく吐くのだ)。祖父はすぐに慣れる。慣れれば大丈夫なんだと言った。そうだろう。僕たちのことをみんな面倒見てきたんだ。
もう、舌が変になっていて、料理もできないのではないかとも聞いた。
今年の正月、じいちゃんは家にいた。歩行が難しくなったが、それでも元気そうだった。今年3歳になる息子の機嫌があまり芳しくなかったことや、サイズの合ってない入れ歯を、はめたりとったりするばあちゃんがグイグイくるのが怖かったからなのか、とにかく泣いた。泣いて吐いた。びっくりしたの、びっくりしたの、と言って泣いた。僕は悲しかった。じいちゃんに可愛い息子を見せたかったのだ。僕の大事なじいちゃんに、僕の可愛い息子を見せたかった。
泣いて吐いても、ばあちゃんはグイグイ来た。それもあって事態が好転するのに時間がかかった。びっくりしたの、と泣くので、じいちゃんはあまり、息子を見ないようにしていた。ごめん、と思った。
結局、クレーンのようなおもちゃで気を持ち直した。
テーブルの上にエビフライが置いてあった。キレイにまっすぐ伸びたエビフライが20本近く皿に積まれている。小腹がすいていたので、何本か食べ始めた。美味しかった。
それにつられて息子も食べた。今までエビフライなんか食べようともしなかったくせに、美味しい美味しいと何本も食べた。嬉しかった。親子3代にわたって同じものを食べたんだ。
じいちゃんは嬉しそうに、毎週エビフライは揚げているんだと言った。うまいだろ、と得意そうだった。もう食べれないと思ってたじいちゃんの手料理は、全然まだまだ美味しかった。
また、回復してもっといろんな料理が食べれるんだと思った。
じいちゃんは1/13で90歳になるとその時聞いた。息子は同日生誕1000日目だ。そんなちっぽけな偶然が何故かすごく嬉しかった。
ノイズイベントは楽しかった。なんとなくふわふわとした気持ちだった。気持ちがそこにあるようなないようなそんな気持ち
ノイズイベントの最後の演者が鳴らす音を聞きながら、祖父のことを考えていた。爆音と狂ったノイズのなかで、意識が外界から遮断されるような感覚があって、目をつぶって、なんか変なのって思った。祖父が想像さえしないであろう、わけの分からない音の中で、祖父のことを考えている。
3/21。休みだったので家にいた。親からビデオ通話の着信があった。めったにビデオ通話なんかかけてこないので、何かあったかと思った。
電話の向こうには病院で、母親と祖母、祖父がいた。
祖父は酸素マスクをつけて、口を明けて眠っていた。ひどく痩せていた。頭蓋骨の形を薄っすらと浮かび上がらせているような、そんな痩せ方をしていた。近いなと思った。
息子は無邪気になぜ病院なのか、なぜ寝ているのか、何をつけているのか聞いた。祖母はビデオ通話に映る嫁を見て、可愛いと褒めた。僕は、その祖父が、かつて見てきた死の近い人達にすごくにている気がして、目を背けたくなった。
変に息子が怖がらないかということが気になった。
また、同時になんとなく、少し落ち着いているように見えて、わずかばかり安心した。
正月に祖父の家に遊びに行ったとき、こんな場所だったかと思った。
人がいなかったからかもしれない。 しばらくぶりだったからかもしれない。 足が祖父も祖母も悪いので、片付けがうまくできないからかもしれない。 祖母が家のことを得意でないからかもしれない。 荒れているということもないはずだが、生活が行われているはずなのに、生活が行われていないような雑然とし感覚があった。 二階はどうなっているのだろう。子供の頃行って以来、もうずっと見ていない。
ただ、一つわかることは、以前のあの賑やかな、おじいちゃんち、というのは二度と再現されないということだ。
僕には曾祖母の記憶がある。 あまり印象が良いものではないけれど。
僕の息子は、この祖父のことを覚えているだろうか。
僕たちの代が全部死んだときに、この世に祖父がいたということ事実が、どこにも存在しなくなるんだな、となんとなく思った。そうして、みんな忘れられていくし、忘れられたんだと思った。
それに、今、こうして文字を書いているが、父方の祖父や祖母がなくなったとき、何もしなかった。確かに物心ついてからは疎遠だったが、小さい頃従兄弟と一緒にあんなに面倒見てもらっておきながら。
だけど、そのことを思い出せないのだから残酷だと思う。
妹によると、妹が最近籍を入れた夫を連れて、祖父に紹介した二日後になくなったらしい。母親が駆けつけてすぐに息を引き取ったそうだ。
なくなる日の午前は、起きて普通に話していたりしたが、午後に突然体調が崩れてそのままということになってしまった。
紹介に行ったとき、祖父はかなり弱っていて、途中何度か息が止まって、その度にペチペチ叩いて起こしたと言って笑っていた。
もう死なせてくれといっていたという。
少し早いよ。GWまで待ってくれよ。
平成の次の元号が気になるだろう?
訃報を受けた日、よくわからない気持ちで家にとりあえず向かった。
悲しいのか。泣けるのか。パソコンはちゃんと片付けたのか?休みを取るのか?手続きは?
すべて大したことない気もしたし、重要なことにも思えた。
なんとなく帰りたくなかったし、立ち読みでもしようかとさえ思った。
玄関のドアを開けるとパジャマ姿の息子が走って寄ってきた。
歌を携帯から流してほしいらしい。
テレビでは「めばえ」という息子のお気に入りの番組が流れていた。 拙い歌声で息子が歌っている
誕生日のことは
覚えていますか
番組が終わり次第、主題歌を流してやった。
ありがとう 理由は何もないんだよ あなたという人がいることでいいんだよ (熊木杏里/誕生日)
泣きそうになって、笑った
背景の中で何種類かのパターンを繰り返して表示する
背景の中で何種類かのパターンを繰り返して表示する
全然書かなくなるということになったので、たまたま業務でやったやつを残しておく。
表題がめちゃくちゃわかりにくいけど、要はこんな感じのやつ。
例えば500 * 1000のパターンを4種類繰り返して表示するみたいなこと。
実装
CSSではできないのでcanvas
を背面に敷きましょう。
HTML & CSS
<div class="wrapper" id="js-wrapper"> <canvas id="c"></canvas> <div class="contents"> ここに内容を書く </div> </div>
.wrapper { position: relative } canvas { position: absolute; top: 0; left: 0 } .contents { position: relative }
そういうわけでcanvasです。
const c = document.getElementById('c'); const ctx = c.getContext('2d'); const PATTERN_HEIGHT = 1000; let w; let h; // 描画のサイズが知りたいので親要素も取得する。 const wrapper = document.getElementById('js-wrapper'); const init = () => { w = c.width = wrapper.offsetWidth; h = c.height = wrapper.offsetHeight; } init(); // パターン画像の種類 const PATTERN_1 = 'PATTERN_1'; const PATTERN_2 = 'PATTERN_2'; const PATTERN_3 = 'PATTERN_3'; // パターンのサイズを柔軟にしたいのでpatternObj.imgにはimgではなくcanvasを格納する const patternSource = [ { name: PATTERN_1, url: '/assets/img/pattern_1.png', img: document.createElement('canvas') }, { name: PATTERN_2, url: '/assets/img/pattern_2.png', img: document.createElement('canvas') }, { name: PATTERN_3, url: '/assets/img/pattern_3.png', img: document.createElement('canvas') }, ]; // パターンの順番 const patternOrder = [ PATTERN_2, PATTERN_3, PATTERN_2, PATTERN_1, ]; // イメージをロードする const loadImage = patternObj => new Promise(resolve => { const img = new Image(); img.src = patternObj.url; img.onload = () => { // canvasにimgを任意のサイズで描画する。 const imgWidth = patternObj.img.width = img.width; const imgHeight = patternObj.img.height = img.height; const imgCtx = patternObj.img.getContext('2d'); imgCtx.drawImage(img, 0, 0, imgWidth, imgHeight); resolve() } }); // imageリソースを全て取得してからコールバックを実行 const loadImages = async (patternSource, callback) => { await Promise.all( patternSource.map( pattern => loadImage(pattern) ) ) callback(); }; const drawPattern = ( ctx, startX, startY, width, height, maxY, patternSource, patternOrder ) => { let i = 0; let drawHeight = startY; while(drawHeight < maxY) { const source = patternSource.filter(source => source.name === patternOrder[i % patternOrder.length])[0].img; const pattern = ctx.createPattern(source, 'repeat'); ctx.fillStyle = pattern; ctx.fillRect(startX, startY + height * i, width, height); i++; drawHeight += height; } } const draw = () => { init(); ctx.clearRect(0, 0, w, h); // 左右ハーフステップで繰り返させる drawPattern( ctx, 0, 0, w / 2, PATTERN_HEIGHT, h, patternSource, patternOrder ) drawPattern( ctx, w / 2, -PATTERN_HEIGHT / 2, w / 2, PATTERN_HEIGHT, h, patternSource, patternOrder ) } ctx.beginPath() loadImages(patternSource, draw)
だるい
はい。
CSSの `pointer-events: none` が便利
CSSの pointer-events: none
が便利
早速書かなくなっているので、小さいことでも書いていこうという気持ちを見せてる💪
サイト作ったりしてて、ディレクターに確認出したりするとたまーに「ここなんかクリックできないんだけど」みたいなことを言われることある。ちょっとややこしいデザインのサイトとかだと割とありがち。
それを聞くと「はーん、レイヤーの順番問題だな」というふうになって、position: relative
かけたりz-index
いじったりすることになるわけなんだけど、pointer-events: none
を利用すれば解消される。
あるいはハンバーガーメニューかなんかで、クリックすると画面全体を覆うようなレイヤーが登場するような場合も使える。
opacity: 0
だけだと、透明になってるだけなのでレイヤーがそこに存在し続けて、普通にクリックできる状態になってしまうため、今まではvisibility: hidden
で存在を消してやってたのだけど、アニメーションかける時にちょっとこのプロパティを気遣ってやる必要があって、まぁまぁめんどくさいなと思ってたら、それもpointer-events: none
でいける。
なんで今まで知らんかったんやろうという気持ち。
そういうわけでDEMOです。
See the Pen pointer event test by bom_phage (@bom_phage) on CodePen.
はい。
小ネタでした。
ちょいちょい触って感じたsin/cosの便利なところ
ちょいちょい触って感じたsin/cosの便利なところ
canvasとかその辺触るとだいたいsin/cosが出てきて、数学嫌いな僕みたいなのはそれだけで😇ってなりがち。だけどちょっと触ってみると全然複雑なものでもない。
ポイントは2点で
- sin/cosに同一の値(角度)を与え、x座表に起点+cos、y座標に起点+sinを与えると円を描く
- 必ず-1〜1までの値を返す(その値間を反復する)
1. 円を描く
1.
については以下の記事に非常に分かりやすく載ってる。
単位円を用いた三角比の定義
正直結構理解するのに苦しんでたけど、これを読んでなるほど!!ってなった。
実際にコード(JavaScript)で示すと、
// この値をいじることでアニメーションなりなんなりさせる let angle = 0; // JSでは基本ラジアンという単位を使うので変換用 const radian = angle => angle * Math.PI / 180; // 起点座標(300なのは適当) const BASE_X = 300; const BASE_Y = 300; // 半径のサイズ const SIZE_RADIUS = 200 // 起点座標を中心にしたx/y座標 let x = Math.cos(radian(angle)) * SIZE_RADIUS + BASE_X; let y = Math.sin(radian(angle)) * SIZE_RADIUS + BASE_Y;
この座標を元に位置だったりを計算してやれば円形にものを配置したり、円形に動かしたりできる。
x座標を直線的な動きにするといわゆるsin curveになる。
それ以外にもsinやcosの値を重ねたりなんだりすると面白い動きになったりする。
See the Pen sin/cos by bom_phage (@bom_phage) on CodePen.
2. 反復する値を使う
実際円を描く機会というのもそんなにあるかと言われればないわけで(そもそもこういうtipsが役に立つ機会はない)、もう一方の-1から1の間の値を必ず返すという方が使い勝手がいい気がする。
しかも、何より素晴らしいのはsinとcosで同じ値を入れても別々の値を返してくれるということだ。要件にもよるけど、割と嬉しい。
そのまま使うのもいいし、正規化して使うとさらに使い良いこともある
-1 〜 1
の範囲だとちょっと使いにくいよねという場合は0 〜 1
に正規化*wikipediaしてしまえばいい。
それはそんなに面倒なことでもなくコード(JavaScript)なら
const normalizeSin = angle => (Math.sin(radian(angle)) + 1) * 0.5; const normalizeCos = angle => (Math.cos(radian(angle)) + 1) * 0.5;
で0 〜 1
の範囲を返すようにできる。
何に使う?
ある範囲を反復するので、繰り返すようなアニメーションの処理に使う。というかtransform
のプロパティに使えば、なんかガチャガチャ動くものになるし、例えばopacity
の値に使うとかhsl
の値に使うとか色々ある。
あと特徴としてはsin curveの形で増減するのでeasing
にもつかえる。
というか色々数字いじると楽しいし、意外な形になるので触ってみて遊ぶのが一番良さそう😘
See the Pen sin/cos2 by bom_phage (@bom_phage) on CodePen.
はい。
そういうわけで、なんとなく書いておきました。
source要素のmedia属性について
source要素のmediaについて
ウェッブサイトを制作する上で、スマホ用とPC用で画像を切り替えたいみたいなことってかなりあると思う。画像はなんやかんやとファイルサイズ食うものでもあるし、PCの方ではガツンとでかいやつ使いたいけど、それさすがにスマホで読ませるのキツイよねって言う時とか、単純にそれぞれで最適化した画像を見せたいみたいなことはざらにある。
そういう時は僕は<picture>
タグを使うことにしている。
それぞれの画像に対してmediaQuery
で切り分けてdisplay: none
をかけるみたいなことでも実現できるけど、その場合、display: none
になってる画像のリソースも読みに行ってしまう。表示させないのに読み込ませるのはどうなの?みたいな気持ちがあるが、<picture>
タグはその心配がないし、それであれば使わない理由もない。
ちなみに背景画像をmediaQuery
で切り分けて読み込ませた場合は、読んでない方は読み込まれない。<picture>
もコレと一緒。そういうわけでサンプルも用意してみた。開発者ツールのNetwork
> img
で読んでるリソースの確認ができる。
See the Pen mediaQuery test by bom_phage (@bom_phage) on CodePen.
display: none
のものも読み込まれてるのがわかると思う。
本題
ところで、このsourceタグのmedia
要素だけど、書き方としてはCSSと一緒。僕はCSSのメディアクエリに関してはem
で記述することにしていて、ほんならこの属性値もem
でいったろかいって思ったけど、それがなかなかうまくいかなかった👶🏻
ちなみにメディアクエリをem
で指定することに関しては下記の記事を読んで、そうかと思ったからだ
。
[CSS]Media Queriesで使う単位はpx, em, remのどれが適しているか検証 -px指定は注意が必要
とりあえずem
で指定するとこんな感じ。768px未満でスマホ、以上でPCのイメージ。
<picture> <source media="(max-width:47.9375em)" srcset="img-sp.jpg"> <source media="(min-width:48em)" srcset="img-pc.jpg"> <img src="img-pc.jpg" alt=""><!-- IE用 --> </picture>
全くダメというわけではない。なんなら普通にいけてるやんと思ってて気づかなかった。
ランドスケープの時に崩れるやんけ🧠🧠🧠
ランドスケープ(横向き)にした時、横幅は768未満のはずなのに、なぜか以上で読み込んで欲しい画像が読み込まれとる👴🏻
Safariだけでない、Chromeも、、、
この件について、明確な原因はわかってないし、調べ方がわかんなかった。エミュレータならいけるっぽい。
ランドスケープ時にはルートのフォントサイズが変わるってことなんだろうな、とか思ってた。だけど実はrem
は問題なく動く。これは一体、、、
まぁそういうわけで、とりあえずpx
を使っとこうぜという話でした。
<picture> <source media="(max-width:767px)" srcset="img-sp.jpg"> <source media="(min-width:768px)" srcset="img-pc.jpg"> <img src="img-pc.jpg" alt=""><!-- IE用 --> </picture>
はい。
2Dのメタボール(Metaball)理解した
2Dのメタボール(metaball)について理解した。
メタボールっつーのは何かと言うとこれです。写経したやつだけど。
(PCで見てくれよな!)
See the Pen metaball canvas by bom_phage (@bom_phage) on CodePen.
メタボールというか、こういう滑らかにくっつく表現やりたいなーと思っていて、調べてたけどどうにもよくわからないでいた。特によく出てくるのはSVG filter使うやつ。liquid
みたいな言葉で検索するとよく出てくるけど、とにかくパフォーマンスが悪い。ほんでSVG filterに対する知識があんまりないので、???みたいな気持ちになってた。
ちょっと間忘れてたけど、思い出してふとやってみるかということになって写経したところ、ばっちり理解した。
原理
上述のcodepenのやつだと若干実装が違うんだけど、ポイントは
- 不透明度の円形グラデーションを複数用意する(中心は不透明度が高く、外側に行くにつれて透明)
- ある値(
閾値
)以下の不透明度の場合は不透明度を0にする(透明にする)
の2つ。これをやるとメタボールみたいに境界がぬるっとした感じの描画になる。
例えば、中心から外側にrgba(0, 0, 0, 1)
=> rgba(0, 0, 0, 0)
というグラデを作って、描画時に不透明度0.95以下の部分は rgba(0, 0, 0, 0)
にしちゃう感じ。
そうすると不透明度1 〜 0.95の部分だけの円ができる。
これが複数個集まると、重なる部分は不透明度が足し算されて、円と円の間の部分に不透明度0.95を超える部分が出てきて境界が滑らかなる。 => メタボール!という感じ:sun_with_face:
まぁそれはそうだがそれはどんな風に実装すんねんっていうのを下に書いとく。
実際触ると一目瞭然だと思うし、canvas
とcssのfilter
で実装したやつを用意している。
実装
canvas
canvas
の場合は、表示用と描画用の二種類のcanvas
が必要になる。描画用の方にradialGradient
でぼかした円を描画して、その内容を表示用のカンバスにコピーする。そのときに不透明度が閾値より低い部分は透明にすることで、メタボールが描画できる。
この実装ではTHRESHOLD
という定数が閾値(初期値210※1)になってるのでここを10とかにしてもらうとボケた円がでてくる。
※1 canvasの場合透明度の範囲も0〜255
See the Pen metaball canvas2 by bom_phage (@bom_phage) on CodePen.
◆前述の実装との違い
実装見てもらったら話は早いけど、描画用のcanvas
からgetImageData
で全ピクセルの情報を取得している。その時、ピクセルのデータは1pxずつrgba
という順番で配列に格納されている。
前述の実装の場合はコピー時にその全データに対して、閾値より低い場合に0
を与えている。これだとr
もg
もb
も閾値以上でないといけなくなってしまう。それだと色に限りがでてしまって困る。
そういうわけでa
の値のみ評価するようにしたのが後述の方。そっちのがforが回る回数も少なくて済むし、いろんな色がいけるぞ。
CSS filter
cssでもやってること一緒。円にblur
をかけて、描画領域のcontrast
を上げることで、不透明度の低い(コントラストが低い)部分を飛ばしている感じです。でもCSSだとcontrast
をあげる都合上、パキパキしたのしかできないし、色の自由度が著しく低いと思う(解決方法がわからん)。
しかもcssのfilter
めっちゃ重い!!
See the Pen metaball by bom_phage (@bom_phage) on CodePen.
はい
そういうわけで実装するならcanvas
でやりましょう!原理がわかれば無限に応用効くと思うし、いろいろできそうでワクワクするぞ!!
3Dも理解できるように頑張るぞ!
See the Pen metaball particles by bom_phage (@bom_phage) on CodePen.
PIXI.jsであそんでる
PIXI.jsであそんでる。
個人プロジェクトで使おうという意図もあるので、別に遊んでるわけではないけど、割と気に入って最近よく試している。何が気に入っているかと言われると、非常に簡単な点と、パフォーマンスがいいことかなー。
canvasでやっていき問題
僕としては2Dの表現をもっといろいろやりたいなーみたいなのがあって、canvasをやり始めた。端的に言うとパーティクルとか、画像をうねつかせるようなのとか、そういうのまずできるようになりたいな、みたいな。なので、ゲームを作りたいとかそういうのはあんまりない。今もそんなに興味はない。
ただ、キャラクターを動かすとかはちょっとやってみたい思いがあるけど、素材を用意するのが面倒だなというので尻込みしてる。
それで結局canvasでgetContext('2d')
して愚直にやってたんだけど、どうもパフォーマンスがあんまりだし、それ用のライブラリというものが世の中にはあって、触らないのもどうなんだとおもってCreate.jsとPIXI.jsを試してみた。
実際、書き方的には2Dを弄る分にはcanvasだろうとcreate.jsだろうとPIXI.jsだろうとあんまり変わらんなという印象。ただ、PIXIはデフォルトでWebGL使ってくれるのでパフォーマンスがいいし、カスタムフィルターみたいなのが用意されてて、できることも多い。
というか、canvasである程度アニメーションの書き方がわかってなかったら、どっちにせよで全然わかんなかっただろうなとも思う。
PIXI.js
そういうわけで今はPIXIにはまってちょっと触ってみてる。自分で作る時も次はPIXI入れるだろうなと思う。
パーティクル
See the Pen PARTICLE PIXI by bom_phage (@bom_phage) on CodePen.
パーティクルをマスクしたやつ
See the Pen PARTICLE PIXI LINES MASK by bom_phage (@bom_phage) on CodePen.
結局z軸問題がある
今の所z軸をいい感じに弄る方法がわかってないので、んーっていうところもある。three.jsももっと触ってみたいなと思うのと、シェーダーをちゃんとやりたいなと思う。