やなぎにっき

学んだことの記録

RubyKaigi 2025 in 松山に参加した

松山で行われた RubyKaigi 2025 に参加してきた。

RubyKaigiは津・松本ときて今回で3回目。 会期中と移動日の前後日含め、いろんな人からとても刺激を貰った5日間だった。

今回も会社の業務扱いとして参加させてもらい、チケット代と旅費も経費としてもらいました。会期中の業務を担当してもらった同僚も本当にありがとうございます。

セッションの内容は相変わらず自分には難しいけど、よく見るコミッターや登壇者がどのあたりの分野に関心があるのか・得意なのかが分かっても面白さが違うことがわかった。 また、去年のKaigi on Railsの登壇をしてみて、発表という形式は文字と比べて熱量を乗せやすいことに気づき、今回は聞く側として発表者の熱量を感じることを意識した。どの発表も熱量高く取り組んでいて本当にかっこいい。この熱量を浴びるだけで自分も明日から頑張ろう、という気持ちになる。

今回は前回と比べて人との関わりが増やせたのがよかった。 松本までは自分が在籍していたフィヨルドブートキャンプ関連の知り合いと話すことが多かったけど、今年はそこからさらに広がって - Rubyのコミュニティで知り合った人 - ドリンクアップやオフィシャルパーティーで知り合った人 - 廊下で立ち話していた知り合いの知り合い

などと色々な人と話したりSNSで繋がることができた。

元同僚のRubyistにドリンクアップで知り合ったRubyistを紹介しようとしたら、すでにあるコミュニティ繋がりの知り合いだった、というように知り合い同士がまた別の知り合いだったことも何度もあった。ノード間が様々なエッジで繋がっている。

session

Day 1

Ruby Taught Me About Encoding Under the Hood

rubykaigi.org

松山出身のima1zumiさんのKeynote

  • この話を聞くために松山に来たようなもので、この話を聞いた後、松山に来てよかったと思った。
  • 「文字を符号化する」技術が狼煙やモールス信号と地続きに文字コードがあるという話、おおっとなった。確かにやっていることは同じだ。
  • irbで家族の絵文字🧑‍🧑‍🧒 (当時はMac上だと人間が4人いた)を消した時に家族が離散したことに気づいた話。
    • フィヨルドの質問タイム(当時Discordで行われていた)でigaigaさんにアドバイスをもらった話、記憶が正しければ私もその時同席していた。こういった人のひとつの分岐点に立ち会えて、Keynoteでこの話が聞けて嬉しかった。
  • ima1zumiさんがこうしてirb/relineやRubyのコミッターとして文字コード関連に関わるようになったのも、興味のあることを深掘りしていった結果で、「好奇心を刺激する、ワクワクするものを見つけて欲しい」と話していたのが印象的だった。
    • これから少し興味のあることに出会った時、この話を思い出していつもよりもう少し深掘りしてみようと思った。

TRICK 2025: Episode I

rubykaigi.org

  • 前回と違って「これから理解できない話が始まるぞ」と身構えて挑んだのに、それでも理解できない超絶技巧のコードが飛び交っていた。
  • beta_chelseaさんの文字によって花の形が変わるコードが素敵だった。コード眺めてみたい。

Day 2

How to make the Groovebox

rubykaigi.org

  • RubyGrooveboxを実装するという話。
  • Rubyで音が鳴らせるんだ!という感動があった。
    • この後LTでも音を流す系の話が2つほどあり、RubyKaigi 2025は実質音楽フェスだった。
  • デモの音楽を流して、そのままエンディングのまとめに入るところがドラマチックだった。
  • 創作意欲が湧くトークだった。音に限らず自分が欲しいツールをRubyで作りたくなった。

Speeding up Class#new

rubykaigi.org

  • 「大人気メソッド」ことClass#newを早くしたというアーロンさんの発表。
  • Ruby本体の話なので見る前は分かるか不安だったけど、図解と説明が分かりやすくて感動した。資料と動画が挙がったらもう一度見たい。
  • この画像、何度見ても元気出る。

Making TCPSocket.new "Happy"!

rubykaigi.org

  • Socket.tcp と TCPSocket.new に Happy Eyeballs Version 2 (HEv2)を導入した話。
  • この発表を聞くにあたって予習をしてきたのだけど、その予習としてTokyoWomen.rbでしおいさんが招待講演をされたたのしいSocketのしくみがとても参考になった。
    • しおいさんの発表でしおいさんの発表の予習をした。
  • 塩井さんの発表、構成がうまくて引き込まれてしまう。
  • どのスピーカーやコミッターもそうだけど、仕事とは別に個人プロジェクトとして本気で取り組んでいて、本当にかっこいい…… 。

Day 3

Ruby Committers and the World

rubykaigi.org

  • オレンジのTシャツを着たコミッターが横に並んでいる図、圧巻すぎる。
  • コミッター、特にこの人はこの分野が得意、この分野に注力している、ということが一昨年のRubyKaigiの時より分かるようになったのが嬉しかった。
  • コミットメッセージをAIに書かせるのは効率化する一方、人によって個性が出るので残して欲しいという意見。
    • 「叙情的なコミットメッセージ」読んでみたい。
    • ちゃんと内容は分からなくてもRuby自体のリポジトリや気になっているgemのPR内容やコミットメッセージを眺めてみるのやってみたくなった。フォローをして眺めるやつ、やるぞ。

Matz Keynote

rubykaigi.org

  • AIに何を任せるか・任せないか、AIのために働くことになってしまうのではないか?を危惧しているという話。

    • 普段自分はAI技術のおかげで仕事も効率化できている部分はあるものの、自分は業務の中で一番楽しいと感じているコーディングという一番楽しい部分を奪われるようなもやもやした気持ちもあった。
    • Matzの話を聞いてじゃあこうやってAIと向き合っていこう、みたいな答えは出せていないけど、やっぱり「自分が楽しいか」を主軸にAIとも向き合っていきたい。
  • 数式が登場したことで、自然言語よりも理解しやすくなり、数学が発展したという話。

    • 数式があることが当たり前だと思っていたけど、そうではない。
    • ima1zumiさんの「文字を符号化する」技術が狼煙やモールス信号と地続きに文字コードがあるという話といい、自分は技術的な歴史の話が好きそう、と気づきがあった。(学校の歴史は学科の中で一番苦手意識があった)
  • 「コミッターと観客席の間は思っているより広くない」「自分が興味が持てるものがあれば簡単にこちらにくることができる」という話。

    • Ruby Committers and the World でも思ったけど、コミッター顔ぶれがだんだんわかってくると、得意分野・守備範囲をメインでやっている人が多いことに気づく。コミッターやスピーカーすべての人がみんなが技術の分野すべてに精通しているわけではなく、興味のあるものを突き詰めて行った結果、コミッターやスピーカーになっているのだなと改めて思った。(こう書いてみるとそれはそうという話だけど)
    • imaizumiさんのキーノートにもあった「好奇心を刺激する、ワクワクするものを見つけて欲しい」という話もここでまた思い出した。

本屋

本屋で何冊か本を買った。 島田さんの本を島田さんに会計してもらい、そのままサインをもらったりした。Kaigi on Rails 2024の島田さんのキーノートを見てから島田さんの本を読みたいと思っていたので読んでKaifi Effectに繋げていきたい。

伝わるコードレビューとRubyでつくるRubyにも著者からサインをいただきました。神イベすぎる……。

Drink up

Day0からDay3まで、毎日どこかしらのドリンクアップやオフィシャルパーティーに参加させてもらいました。ドリンクアップで知り合った人と翌日以降に会場でまた会えるのが嬉しい。

RubyMusicMixinと川

Day3の最後、ピクシブさんが主催しているRubyMusicMixinに参加した。 フィヨルドブートキャンプ在籍時に一緒に読書会をしていた友達の obregonia さんのDJがはじめて生で見れて嬉しかった。場を沸かしていた。

mixin会場付近の川も楽しかった。 よくいろいろなRubyistから聞いていた「川」を目の当たり(?)にできたので、これが「川」か、という感動があった。

mixinや川、関係値バグが発生して気軽に色々な人と話せるのがよいですね。

松山観光

去年の沖縄のRubyKaigiは行かなかったのだけど、その時SNS上でRubyistが沖縄で楽しそうにしているのが本当に羨ましく、でも後から沖縄にいってもそれはまったくの別の体験になることに気づいた。

今回RubyKaigiで「Rubyistのいる松山」を楽しめて本当によかった。夜の大街道を歩いていると全員Rubyistに見えるし、Day3の翌日に松山観光をしていたらあちこちRubyistに遭遇したりした。松本城に登る時間と体力がなかったのでまた行きたい。 すっかり愛媛や松山のことが好きになり、スーパーで柑橘類を買うときは愛媛県産を選ぶみたいなことをしている。

RubyKaigi前の土日に岐阜の音楽フェスに行っており、岐阜から東京に帰ってきた翌日に松山に行って4泊するという超アクロバットな1週間だったけど多少無理して松山に行ってよかった。1週間乗り切れたな、と思ったところで疲労で体調を崩し、戻るまでに2週間かかったけど。

来年開催は函館ですね。「Rubyistのいる函館」を今年よりももっと楽しむために日々の研鑽・体力づくり・生活をやっていくぞ。

2024年買ってよかったもの4つ

思い出せばもっとあるはずだけど、どうしても書いておきたい4つだけ紹介。

HOKA BONDI8

https://www.hoka.com/jp/bondi-8/1127952.html

オモコロチャンネルで原宿さんがおすすめしていてHOKAを知った。

それなりの値段したけど、歩いてる間「ふかふかして歩くのおもしれ〜」と思いながら履いてるのでいい買い物だった。

2月に右足を骨折してから完治した後も扁平足ぎみだったけど、この靴で散歩してたらかなり改善された。

ホカは他の靴に比べて幅が狭いので多少面倒でも通販より店舗に行って試した方がよさそう。

ソックウェルの靴下

sockwell.jp

メリノウール素材の着圧靴下。 素材のおかげか汗で冷えにくい。暖かさより冷えない方が大事。 そして着圧がちょうど良く、歩いていても疲れにくい。 一足4500円くらいと靴下にしては本当に高いのだけど、家でも外でも・夏でも冬でも履けるので値段の価値がある。 今年初めて買って以来、4,5足買ってソックウェルだけで靴下を回している。

ホカの靴とソックウェルの靴下のおかげで今年は歩くのが楽しくなった。

ホットクック

jp.sharp

買ってよかったものというより借りてよかったもの。 ずっと気になっていたけど置き場所と値段で踏みとどまっていたところ、レンティオで月1000円程度でレンタルできるとのことで借りた。 結果的にもうほとんどIHコンロを使わなくなったほどホットクックを使っている。

主に蒸し野菜、パルシステムのミールキット、パスタ、豚汁などを手動モードで作ることが多い。 あとは鍋とかとりむねの低温調理とかホットケーキとか。 特にパルシステムのミールキットは具材が切った状態になっているので、袋を開けてホットクックに入れてスイッチオンにするだけでおかずできるので、週2の頻度で平日の晩御飯にしている。

火を通す間に別の部屋にいてもいいし、散歩に行ってもいいのがこんなに楽だとは。 冷凍肉をそのまま使っても冷凍感が残らないのも嬉しい。

ホットクックが気になったきっかけは勝間和代さんのブログだった。その勝間和代さん著書の勝間式超ロジカル料理をレンタルしてすぐに読んだことでよりスムーズに活用できた。

https://www.amazon.co.jp/dp/4866430656

塩分を総重量の0.6%の量で入れる(味噌は6%)と味が決まる、ということを知れただけでも味付けがかなり楽になった。味噌汁を作るときに味噌の量でもう悩まない。

今もレンタルで使ってるけど、フル機能の新機種が出たら購入したい。

メディネック

mytrex.jp

首を温めて牽引して電気を流すやつ。

togetter.com

を見て気になりこちらもレンタルして使っている。

ストレートネック(自己診断)のせいか最初は牽引も電気も慣れていなくて15分苦痛だったけど、1ヶ月ほど使い続けたいまや首が改善されたのか牽引されても何も感じなくなった。 肩こりもしにくくなり、心なしか低気圧による頭痛の影響も少なくなった気がする。

乗っているだけ・充電しておく必要なしなので始めるハードルが低くて続けられている。

当分必要ないかなと思ってサボったあとに久しぶりにやるとストレートネックがぶり返すのか牽引がまた苦痛になるのでまだしばらく続けてみる。

編み物をしながら耳で読書するのが楽しい

これはminneアドベントカレンダー2024の記事です。

今月から編み物を始めたところ、予想以上に楽しく夢中になってしまい、さらに耳で読書もできるということに気づいた話をします。

編み物を始めたきっかけ

そもそも編み物を始めたきっかけは、前から編み物をいずれは出来るようになってみたいとなんとなく思っていたことに加え、

など、いろんな動機が重なってふつふつと編み物をしたい気持ちが出てきたところで「編み物って糸と針さえあれば始められるじゃん」ということに気づき、その日に100円ショップで毛糸とかぎ針を買い、帰ってすぐネットなどで編み方を調べて編み始めたという流れでした。

編み物の楽しさ

Kindle Unlimitedでかぎ針編みの入門の本を何冊か借りて読み、簡単なものなら編み図を読んで編めるようになりました。

一作目(with ワドルディ

そこからもともと棒針編みができるようになりたかったので、今は棒針編みの入門の本を読みながら簡単な編み方を練習しているところです。糸のテンションを合わせるのが難しい。

100円ショップで毛糸とかぎ針を買ってから日から今日まで、時間さえあればひたすら編み続けています。手が痛くなるまで、休みも挟まず編んでしまう……。

そこまで夢中になる理由を考えてみるとこの3つが大きいように思います。

上達を実感しやすい

最初は一目一目編むのも時間がかかっていたし編み目もいびつだったけど、編み続けるという反復練習を続けていくうちに要領を得てだんだん綺麗な編み目を作れるようになっていくし、だんだん編む速度早くなる。いろんな編み方があるので、編み方を挑戦する→できるようになるのサイクルが回しやすい。

成果が目に見える

編み続けていたら、糸という一次元的なものが布という二次元・三次元的なものになっているのが面白い。「ずいぶん遠いところまできたものだ」みたいな気持ちになる。小学生の時にやっていたリリアンの面白さを思い出す。

没入できる

上達とか成果とか抜きに、単純に淡々と同じ作業をするのは没頭できて落ち着くし楽しい。スマホSNSYouTubeを目的なく眺める時間もだいぶ減った。

また、何をつくるのかKindle Unlimitedでいろんな編み物の本を片っ端から借りたり、InstagramYouTubeで編んでみたいものを探すのも楽しくて時間があっという間に過ぎます。

今までで一番Kindle Unlimitedを使い込んでいる

私は今のところ編むこと自体が楽しいので、今の技量で・短時間で作れそうなものを選んで編んで(というより練習に近い)ますが、いつか自分が気に入ったデザインのニットなどの大物も作ってみたいです。あと英文パターンが読めるようになりたいし、自分で編み図を考えるのもやってみたい。

編み物と耳でする読書は相性がいい

編み物は、編み物自体の面白さはもちろん、編み物をしている時に耳からの情報がよく入ってくるのも良いところです。 もともと好きなVTuberなどのラジオやゲーム実況などの配信を見るのが好きで流しながら編んでいたのですが、インターネットやゲームをしながら聞くのに比べてよく耳からの情報が入ってきやすいので、せっかくなら積読書を消化する時間にもしたいと思い、Audibleなども聞くようになりました。最近は「好き」を言語化する技術を聞いています。

Audibleを聴くタイミングって電車移動や散歩中、家事をするくらいだと思っていたのですが、そこに編み物が加わってきたので、聞く時間が増えました。

ただ、読みたい本がAudibleにもあるとは限らず、KindleEPUB、PDF形式で買った本をどうにか耳で聞きたくて試しているところです。 iPhoneの自動読み上げやKindleのアシストリーダーも試してみたんですが、機械音声っぽくて耳だけだと頭に入りにくい。(機能自体は目で読みながら音声を流すのに使うこともある)

AI読み上げ機能アプリやツールをいろいろ試しているんですが、著作権的な問題ないもの、例えばデータをクラウド上にあげないで利用するようなものでとなると今のところ選択肢が狭そうです。自分の端末で読み上げられるようなツールを探してみようと思います。(読み上げ系のライブラリ使って簡易的なツールつくるが早いのかもしれない)

おすすめの関連コンテンツ

今回の話に関連しておすすめしたい動画と本をひとつずつ紹介します。

編幸心 - YouTube

ken_c_loさんがやんちゃクラブ Advent Calendar 2024で動画で編み物の楽しさ(編幸心)について、編みながら話されている動画。

おそらく私とほぼ同時期に編み物を始めているのですが、編み物の楽しさについて全部分かる〜〜と思いながら聴いていました。脳内物質が出ている感覚、ある。

(やんちゃクラブ Advent Calendar 2024、どれもいい。文章とはまた違う良さがある。)

www.shinchosha.co.jp 編み物作家である三國万里子さんの「編めば編むほどわたしはわたしになっていった」というエッセイ本。 このエッセイが好きで何度か読んでいるのですが、編み物を知った今、また読み直したくなっています。Audibleに来て欲しい!

やりすぎは良くない

編み物に夢中になりすぎて2,3時間ぶっ続けで作業してしまうことも多く、そのせいなのか始めて2週間したタイミングでぎっくり腰になりました。丸2日間くらいまともに動けなかった……。

どんな座り作業でも言えることですがこまめな休憩をとり、十分なストレッチをしたほうがいい。腰痛は忘れた頃に突然くる。

野菜ガチャで散歩を習慣化する

この記事は、意識低いトレーニング部のアドベントカレンダーの19日目の記事です。

私の唯一身体を動かす趣味が散歩です。 野菜の無人販売所で野菜を買う(私は野菜ガチャと呼んでいる)ために散歩の頻度が上がった話をします。

私が住んでいる練馬区では都内23区と思えないくらい農業が盛んで、畑や野菜の無人販売所が至る所にあります。野菜は大体の場所が無人販売所の近くの畑で採れた新鮮なものです。

練馬区の野菜販売所おでかけマップ完全版【127ヶ所】 | 練馬区のonlineタウン誌「ネリマンタイムス」ローカルニュース より。多すぎ

練馬に引っ越してくるまでは無人販売所というと小さいテントに野菜と集金箱が置いてあるものというイメージだったのですが、マップを見てもらうと分かる通り練馬付近ではコインロッカー形式のものも多いです。 100円を入れるとドアが開き、野菜がもらえるシステムです。

私はよく平日の在宅勤務のお昼休みにご飯を食べた後、徒歩で往復30分以内で行けるコインロッカー式の無人販売所に行き、その日置いてあった野菜の中から欲しかった・気になる野菜を100円・200円で買い、たまに欲しい野菜がなければ他の無人販売所に行くのがルーティンになっています。 買った野菜から今晩の献立を考えて、退勤後に作る(主にホットクックが)までがセットです。

鍋セット

当たりのスイカ。この夏1回しか見なかったのでSSR

150円の場合は100円玉2枚で買っておつりで50円が付いてくる

今井真実さんレシピの柿モッツァレラ春菊。春菊をサラダで食べるのにハマっている
夏は焼き浸しばかり作っていた。(直売所以外で買った野菜もある)

ただ目的や理由もなくする散歩も好きなのですが、この野菜ガチャのおかげで散歩をする頻度が上がりました。

  • 報酬がある(新鮮な野菜を安く手に入れることができる)
  • ガチャ要素(その日行くまで何があるか分からない)
  • 習慣化しやすい(スケジュールが昼ごはんを食べた後)

という点が自分が楽しく習慣化するのに合っていたんだと思います。

散歩もできるし野菜を取る量も増えてお得。

スーパーではなかなか見ない野菜もあって挑戦しやすいのも楽しいです。 たまにその場で立ち会った方と「この野菜どうやって使うの?」みたいな会話も生まれることもあります。

悲しいことにもうすぐ引っ越す予定で、引越し先には無人販売所があまりなさそうなのでこの野菜ガチャ散歩ができるのも残りわずかなのが残念です。引越し先は近くに公園や図書館があるので、お気に入りの散歩コースを見つけたいです。

OCRとLeafletでイベント会場の目的地が一目で分かるマップを作った

この記事は、「「GMOペパボ エンジニア Advent Calendar 2024」の13日目の記事です🎄

私が所属しているminneが主催するハンドメイドイベント「minneのハンドメイドマーケット2024(通称ハンマケ)」のLPサイトに出展者のブースの位置が分かるマップ機能を作りました。

私はハンマケの他にも、過去にデザフェスや同人イベントのようなたくさんの出展者ブースが並んでいるイベントに行ったことがあるのですが、お目当てのブースをに行こうとして迷った経験が何度もあります。イベントは購入品(紙は重い)を背負い、固くて疲れやすく広い会場の床を人ごみの中歩きまわるので、なんとかスムーズにお目当てのブースに行きたいものです。

そんな悩みを解決するような機能がこのマップ機能です。

ハンマケのLPサイトでは出展者の個別ページに表示しました。

マップ機能がリリースされるまで

  • イデアの発端はpplogさん
  • senさんが地図を作る
  • miyakeyさんにOCR情報を出力する
  • yanagiがOCR情報を元にピンの配置などの地図を実装
  • きでりんさんにスタイルをあてる

という豪華メンバーによる素晴らしい連携プレイでリリースされました。

今回は地図の実装について書きます。

実装

OCR出力については今回割愛します。

PythonのライブラリやGoogle Cloud Vision APIなどで実現できそうです。miyakeyさんの出力コードを見る限り、誤検出を防いだりちょうどいい位置に調整するのにコツが必要そうでした。

利用したライブラリ

  • React
  • Leaflet
  • Leaflet React

サンプルコード

import leaflet, { CRS } from 'leaflet'
import 'leaflet/dist/leaflet.css'
import { ImageOverlay, MapContainer, Marker, Rectangle, Tooltip } from 'react-leaflet'
leaflet.Icon.Default.imagePath = 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/'

const Map = () => {
  // マップ画像のサイズ
  const imgWidth = 5591
  const imgHeight = 3237
  // 地図の範囲
  const bounds = new leaflet.LatLngBounds([0, 0], [imgHeight, imgWidth])
  // ブースのx,y座標
  const markerPosition = [2188, 1736]
  // 矩形の位置
  const rectangle = new leaflet.LatLngBounds(
    [markerPosition[0], markerPosition[1]],
    [imgHeight, imgWidth]
  )

  return (
    <div>
      {/* 地図 */}
      <MapContainer
        center={bounds.getCenter()}
        zoom={-1} // デフォルトの縮尺
        minZoom={-5} // 最小縮尺
        crs={CRS.Simple} // 緯度経度をシンプルなxy座標にする
        maxBounds={[
          [0, 0],
          [imgHeight, imgWidth]
        ]} // 地図の範囲
      >
        {/* 画像をオーバーレイ */}
        <ImageOverlay
          url={'http://example.com/map.jpg'} // マップ画像のURL
          bounds={bounds}
        />
        {/* マーカー */}
        <Marker position={[markerPosition[0] + 20, markerPosition[1]]} />
        {/* 矩形 */}
        <Rectangle bounds={rectangle} pathOptions={{ color: 'red' }} />
        {/* ツールチップ */}
        <Rectangle bounds={rectangle} pathOptions={{ color: 'black' }}>
          <Tooltip direction="bottom" offset={[0, 20]} opacity={1} permanent>
            ブース番号
          </Tooltip>
        </Rectangle>
      </MapContainer>
    </div>
  )
}

export default Map

Leafletという地図のライブラリを使います。

元々は地図を表示するライブラリなんですが、画像をオーバーレイ+座標系をxyにすることでやりたいことが実現できました。

画像をオーバーレイはreact-leafletだとmageOverlayで行います。

{/* 地図 */}
<MapContainer
  center={bounds.getCenter()}
  zoom={-1} // デフォルトの縮尺
  minZoom={-5} // 最小縮尺
  crs={CRS.Simple} // 緯度経度をシンプルなxy座標にする
  maxBounds={[
    [0, 0],
    [imgHeight, imgWidth]
  ]} // 地図の範囲
>
  {/* 画像をオーバーレイ */}
  <ImageOverlay
    url={'http://example.com/map.jpg'} // マップ画像のURL
    bounds={bounds}
  />

ピンを置く

ピンや範囲を指定した図、Tooltipなどを好きに置くことができます。

{/* マーカー */}
<Marker position={[markerPosition[0] + 20, markerPosition[1]]} />
{/* 矩形 */}
<Rectangle bounds={rectangle} pathOptions={{ color: 'red' }} />
{/* ツールチップ */}
<Rectangle bounds={rectangle} pathOptions={{ color: 'black' }}>
  <Tooltip direction="bottom" offset={[0, 20]} opacity={1} permanent>
    ブース番号
  </Tooltip>

補足

今回正確にはNext.jsで実装したのですが、react-leafletはwindowオブジェクトを使用するため、ssr: falseを指定してdynamic importする必要がありました。

感想など

実装してみた感想

最初はJSとCSSで1から実装しようとも考えたんですが、Leafletで簡単にGoogle Mapライクのように好きに動かしたり拡大が実装できました。イベントでは基本スマホで利用するので見やすさ・動かしやすさは大事ですね。

当日私はイベントスタッフとしてインフォブースにいたんですが、あるブースを探している来場者にこのページの地図を使って説明できたのがよかったです。自分が実装した機能をユーザーに使ってもらう様子を直接見るというのは開発者として本当に嬉しい体験でした!

フォローしているユーザーマップ

これは自分が欲しいと言って作ったのですが、出展者ページだけではなく、フォローしているユーザーを一つのマップで見れるようにもしてみました。パーソナライズされたマップです。

minneは作家のお気に入り機能があり、また出展者情報とminneのアカウントで紐づいているので実現できました。

他のイベントでも使いたい

ハンマケは全て通番なので番号だけで一意に識別ができるんですが、コミケコミティア、デザフェスを見た感じA001、B001……のように英字+1から採番で、かつ地図には数字しか表示されないのでOCRで数値を抽出できてもブースを一意に識別できないことに気づきました。

引用: https://designfesta.com/about-map/

画像にA001のように数字の前に英字をつけるなにがしを実装する→今回と同じようにOCR出力をするみたいにやるといいのかな。

参考

React-Leafletで地図の代わりに画像を使う - write ahead log

OCRとLeafletでイベント会場の目的地が一目で分かるマップを作った

この記事は、「「GMOペパボ エンジニア Advent Calendar 2024」の13日目の記事です🎄

私が所属しているminneが主催するハンドメイドイベント「minneのハンドメイドマーケット2024(通称ハンマケ)」のLPサイトに出展者のブースの位置が分かるマップ機能を作りました。

私はハンマケの他にも、過去にデザフェスや同人イベントのようなたくさんの出展者ブースが並んでいるイベントに行ったことがあるのですが、お目当てのブースをに行こうとして迷った経験が何度もあります。イベントは購入品(紙は重い)を背負い、固くて疲れやすく広い会場の床を人ごみの中歩きまわるので、なんとかスムーズにお目当てのブースに行きたいものです。

そんな悩みを解決するような機能がこのマップ機能です。

ハンマケのLPサイトでは出展者の個別ページに表示しました。

マップ機能を作った流れ

  • イデアの発端はpplogさん
  • senさんが地図を作る
  • miyakeyさんにOCR情報を出力する
  • yanagiがOCR情報を元にピンの配置などの地図を実装
  • きでりんさんにスタイルをあてる

という豪華メンバーによる素晴らしい連携プレイでリリースされました。

今回は地図の実装について書きます。

実装

OCR出力については今回割愛します。

PythonのライブラリやGoogle Cloud Vision APIなどで実現できそうです。miyakeyさんの出力コードを見る限り、誤検出を防いだりちょうどいい位置に調整するのにコツが必要そうでした。

地図の実装

利用したライブラリ

  • React
  • Leaflet
  • Leaflet React

サンプルコード

import leaflet, { CRS } from 'leaflet'
import 'leaflet/dist/leaflet.css'
import { ImageOverlay, MapContainer, Marker, Rectangle, Tooltip } from 'react-leaflet'
leaflet.Icon.Default.imagePath = 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/'

const Map = () => {
  // マップ画像のサイズ
  const imgWidth = 5591
  const imgHeight = 3237
  // 地図の範囲
  const bounds = new leaflet.LatLngBounds([0, 0], [imgHeight, imgWidth])
  // ブースのx,y座標
  const markerPosition = [2188, 1736]
  // 矩形の位置
  const rectangle = new leaflet.LatLngBounds(
    [markerPosition[0], markerPosition[1]],
    [imgHeight, imgWidth]
  )

  return (
    <div>
      {/* 地図 */}
      <MapContainer
        center={bounds.getCenter()}
        zoom={-1} // デフォルトの縮尺
        minZoom={-5} // 最小縮尺
        crs={CRS.Simple} // 緯度経度をシンプルなxy座標にする
        maxBounds={[
          [0, 0],
          [imgHeight, imgWidth]
        ]} // 地図の範囲
      >
        {/* 画像をオーバーレイ */}
        <ImageOverlay
          url={'http://example.com/map.jpg'} // マップ画像のURL
          bounds={bounds}
        />
        {/* マーカー */}
        <Marker position={[markerPosition[0] + 20, markerPosition[1]]} />
        {/* 矩形 */}
        <Rectangle bounds={rectangle} pathOptions={{ color: 'red' }} />
        {/* ツールチップ */}
        <Rectangle bounds={rectangle} pathOptions={{ color: 'black' }}>
          <Tooltip direction="bottom" offset={[0, 20]} opacity={1} permanent>
            ブース番号
          </Tooltip>
        </Rectangle>
      </MapContainer>
    </div>
  )
}

export default Map

Leafletという地図のライブラリを使います。

元々は地図を表示するライブラリなんですが、画像をオーバーレイ+座標系をxyにすることでやりたいことが実現できました。

画像をオーバーレイはreact-leafletだとmageOverlayで行います。

{/* 地図 */}
<MapContainer
  center={bounds.getCenter()}
  zoom={-1} // デフォルトの縮尺
  minZoom={-5} // 最小縮尺
  crs={CRS.Simple} // 緯度経度をシンプルなxy座標にする
  maxBounds={[
    [0, 0],
    [imgHeight, imgWidth]
  ]} // 地図の範囲
>
  {/* 画像をオーバーレイ */}
  <ImageOverlay
    url={'http://example.com/map.jpg'} // マップ画像のURL
    bounds={bounds}
  />

ピンを置く

ピンや範囲を指定した図、Tooltipなどを好きに置くことができます。

{/* マーカー */}
<Marker position={[markerPosition[0] + 20, markerPosition[1]]} />
{/* 矩形 */}
<Rectangle bounds={rectangle} pathOptions={{ color: 'red' }} />
{/* ツールチップ */}
<Rectangle bounds={rectangle} pathOptions={{ color: 'black' }}>
  <Tooltip direction="bottom" offset={[0, 20]} opacity={1} permanent>
    ブース番号
  </Tooltip>

補足

今回正確にはNext.jsで実装したのですが、react-leafletはwindowオブジェクトを使用するため、ssr: falseを指定してdynamic importする必要がありました。

感想など

実装してみた感想

最初はJSとCSSで1から実装しようとも考えたんですが、Leafletで簡単にGoogle Mapライクのように好きに動かしたり拡大が実装できました。イベントでは基本スマホで利用するので見やすさ・動かしやすさは大事ですね。

当日私はイベントスタッフとしてインフォブースにいたんですが、あるブースを探している来場者にこのページの地図を使って説明できたのがよかったです。自分が実装した機能をユーザーに使ってもらう様子に立ち会えるのは開発者として本当に嬉しい体験でした!

フォローしているユーザーマップ

これは自分が欲しいと言って(半ば勝手に)作ったのですが、出展者ページだけではなく、フォローしているユーザーを一つのマップで見れるようにもしてみました。

minneは作家のお気に入り機能があり、また出展者情報とminneのアカウントで紐づいているので実現できました。

他のイベントでも使いたい

ハンマケは全て通番なので番号だけで一意に識別ができるんですが、コミケコミティア、デザフェスを見た感じA001、B001……のように英字+1から採番で、かつ地図には数字しか表示されないのでOCRで数値を抽出できてもブースを一意に識別できないことに気づきました。

引用: https://designfesta.com/about-map/

画像にA001のように数字の前に英字をつけるなにがしを実装する→今回と同じようにOCR出力をするみたいにやるといいのかな。

参考

React-Leafletで地図の代わりに画像を使う - write ahead log

#minneで買ってよかったもの 2023

この記事は #minneで買ってよかったもの Advent Calendar 2023 の25日目の記事です🎅

adventar.org

minneでエンジニアをしているyanagiです。minneの色々な思い出と共に買ってよかったものを紹介していきます 🙌

minneのハンドメイドマーケット2023 で買ったもの

💫 leapさんの流れ星のフォークリング

minne.com

leapさんは元々好きな作家さんで、minneでも購入していました。懐かしいようで新しいような、落ち着いているようでキラキラしているような雰囲気がとても好きです。

当日は作家さん本人に対応していただいたのですが、すごく良くしていただいて楽しい時間だったな〜と今でも指輪をつけるたびに思い出したりします。サイズの調整もその場でしていただいたりと、対面ならではのよさを感じたお買い物でした。

🌷 haru さんの チューリップ ハンカチ

minne.com

アナログで描いた絵をイラレで取り込んで加工しているらしく、アナログとデジタルが融合されている感じが好きです。それをさらに綿に印刷しているのがまた素敵。

🤜 ol さんのバングル

minne.com

(minneではバングルは取り扱っていない模様)

ブースのテーブルの代わりに買い物カゴを使っていたり(ちゃんとメタルラック的な棒で固定されていた)作品のコンセプトが一貫されていて、作品・ブースの雰囲気が素敵でファンになってしまいました。このバングルはステンレスを加工して作っているものとのこと。

リリース記念で買ったもの

🍪 atelier Claire さんのクッキー缶

minne.com

入社して初めての深夜メンテ明けに動作確認という名目で購入。何を食べても美味しい。ココナッツが好きなのでココナッツの塊のようなクッキーが一番好きでした。

🐈 Zacchino!さんの スマホ用壁紙「こねこ」

minne.com

こちらは物品ではなくダウンロード販売の壁紙。

ダウンロード販売のリリースに関わっていたのですが、こちらはリリースした後に購入した思い出深い作品です。手持ちのiPhone壁紙にしているのですが、同僚や友人に「かわいいね!」とよく褒められます。

minneとものづくりとで紹介したもの

🌿 刺繍・布小物 emuさん のクリスマス 刺繍リース

minne.com

厳密には今年ではなく去年の12月に買ったもの。クリスマス用のリースとして探していたのですが、どの季節でも馴染むのでクリスマス以外の季節でも飾っています。

minneとものづくりとでも取り上げていただきました。

minne.com

来年もたくさんお買い物するぞ 🤘