2024年1月1日月曜日

SVG の描画要素を path に変換する shape2path を作った

SVG の描画要素 (rectangle, circle, ellipse, line, polyline, polygon) を path に変換する shape2path を作りました。

shape2path

以下の類似ライブラリが存在することはわかっているのですが、Web 上で動かなかったり、実装不足があったり、XML パーサが巨大すぎるので、依存なしでシンプルに動くものを作りました。 依存がキツかったり fs module 依存が邪魔なときに毎回ゼロから作り直しているのですが、どうするのが良いのかなあ。 たぶんどうしようもないので、Node.js / Deno / Bun に依存するコードはなるべく使わないのが鉄則でしょうね。

ブラウザとオフラインの実装を分けるのが難しい

作っているときにも同じような問題にぶつかって、HTMLElement や HTMLDocument の実装が Deno / Node にはないのでどうするか、となりました。 特に HTMLDocument クラスはどんなライブラリでもブラウザで動かす時とオフラインで動かす時で動作が異なる問題が発生します。 document がある時 (Web) はバンドルサイズを小さくするために import なしでも動くようにしたいものです。 しかし import 処理を分けようとすると、動的 import を使うしかなく、よくわからないことになります。 こういう時に ESM って不思議な力で動いてるんだなと感じたりします。 たぶんブラウザの時だけ import しないようなことって今のところできないよね?

すべてを諦めて DOM を再現するライブラリを使うのが楽ではあるのですが、バンドルサイズは大きくなります。 この路線でいくなら linkeDOM は互換性が高く、速度もまあまあなので良さそうです。 とはいえ 300KB くらい増えてしまうので依存性をゼロにしたいなと思い、HTMLDocument は無理やり使わないようにして、関連するオブジェクトとメソッドを引数で渡す実装にしました。 これなら依存性が引数として与えられる外部の HTMLElement だけになり、かなり動かしやすくなります。 ただこの路線での実装は、ブラウザと完璧な互換性を持っているライブラリがほとんどない問題があります。 たとえば私がよく使っている node-html-parser は HTMLElement.cloneNode() をサポートしていないので、多少ながら違和感が残る実装になりました。 ただこういう違和感はブラウザに慣れ過ぎているからで、ESM 的な観点から考えると普通なのかも知れません。 DOM の API を使ったライブラリは作り方が難しいですね。

円/楕円の変換方式

上述のライブラリでは、どれも円/楕円の変換方式を一つしか用意していません。 しかしそれだと改良が難しいので、困るケースがままあります。 そこで SVG の <circle> を <path> で描く を利用しています。 描画パターンを選択できると嬉しいと思ったので、すべてサポートしています。 私のお気に入りは「8本の2次ベジェ曲線で描画」です。 描画精度は低い反面、応用性が高いです。

0 件のコメント: