SVG.js (1)

まず重大な注意:

  • npm i svg.js と npm i @svgdotjs/svg.js では違うものがインストールされる。
 Plumb > npm list
+-- @svgdotjs/svg.js@3.1.2
+-- @types/jest@28.1.4
+-- @types/node@18.0.3
`-- svg.js@2.7.1
  • svg.js は開発が止まっているかも知れない。@svgdotjs/svg.js が現行バージョン。
  • jsPlumb も同じことがあって、jsplumb と @jsplumb/browser-ui があって、jsplumb は開発止まっていた。

graphics.js も悪くないのだが、d.ts ファイルが存在しないようなので svg.js にした。d.tsファイルは以下に貼ってある。

その他色々:

  1. <script src="https://cdn.jsdelivr.net/npm/@svgdotjs/svg.js@3.0/dist/svg.min.js"></script> でブラウザに読み込める。最近は楽だなー。
  2. ブラウザでは、SVGオブジェクト(the global SVG object)が作られて、その名前空間の下に諸々が配置される。
  3. ESM方式であれば、import { SVG } from '@svgdotjs/svg.js' でSVGオブジェクトが作れる。
  4. 名前 'SVG' は、名前空間名であると同時に関数名なので呼び出せる。
  5. SVG() 呼び出しで an SVG document を作れる。要素ではなくて文書ノードが返る。一応、XMLのハイブリッド文書アーキテクチャに沿っている。SVGは別ボキャブラリだから透過的なDOMツリーではない。
  6. var svgDoc = SVG(); svgDoc.addTo('body') で、HTMLツリーのbodyの所にSVG文書ノードを接ぎ木する。おそらく last sibling として入るのだろう。
  7. var svgContainer = svgDoc.addTo('body'); svgContainer.size(300, 300) で描画領域サイズが設定される。
  8. 結局、HTMLツリーに接ぎ木〈マウント〉されたSVG文書のコンテナ要素を得るには、var svgContainer = SVG().addTo('body').size(300, 300)
  9. 上記のことをタグで記述すれば、<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" height="300"></svg>
  10. svgContainer を draw という呼び名で呼ぶのがコンベンションらしいので従う。
  11. drawのメソッド呼び出し draw.rect(100, 100) などでdraw配下の図形オブジェクトを生成できる。
  12. var rect = draw.rect(100, 100).attr({ fill: '#f06' }) のようなメソッドチェーン記法も使える。
  13. 上記のことをタグで記述すれれば、<svg> のなかに <rect width="100" height="100" fill="#f06"></rect> を挿入したことになる。
  14. var draw = SVG().addTo('#someElementId').size('100%', '100%') のような呼び出しも出来る。
  15. DOMツリー構築完了後の初期化処理は SVG.on(document, 'DOMContentLoaded', ()=> {var draw = SVG().addTo('body')} ) だが、bodyの最後にスクリプトを直書きすれば関係ない。
  16. jQueryの悪しき伝統にしたがって、SVG() 関数は、引数が文字列だとノード検索関数になる。邪悪多相性と呼んでおこう。下に仕様あり。
  17. 邪悪多相性のディスパッチは:
    1. 引数なし ファクトリメソッド
    2. セレクター文字列 または HTMLテキスト文字列 (パーズして挙動が変わる)
    3. DOM要素ノード型オブジェクト
    4. その他の型
  18. The main SVG.js initializer function とは、関数 SVG() のこと。
  19. SVG() 呼び出しの結果、プログラムには SVG.Svg オブジェクト(クラスのインスタンス)が返される。これはDOM要素ノードではなくて、SVG.js としてのオブジェクト。
  20. APIドックの編成がちょっと変わっている。ひょっとしてjQueryの影響かも知れないが、クラスやインターフェイスのような構造より、何をしたいか/どんな操作がしたいかにより組織化されている。「構造よりは要求」という方針。

邪悪多相性の仕様:

function SVG(): Svg;
function SVG(selector: QuerySelector): Element;
function SVG<T>(el: T): SVGTypeMapping<T>
function SVG(domElement: HTMLElement): Element;

クラスSvgの宣言は:

class Svg extends Container {
        constructor(svgElement?: SVGSVGElement);
        constructor(id: string);
        node: SVGSVGElement;
        namespace(): this;
        defs(): Defs;
        remove(): this;
        isRoot(): boolean;
    }

class Container extends Element {
        circle(size?: NumberAlias): Circle;
        circle(size: number, unit: number): Circle;
        clip(): ClipPath;
        ellipse(width?: number, height?: number): Ellipse;
        flatten(parent: Dom, depth?: number): this;
        foreignObject(width: number, height: number) : ForeignObject
        gradient(type: string, block?: (stop: Gradient) => void): Gradient;
        group(): G;

        image(): Image;
        image(href?: string, callback?: (e: Event) => void): Image;
        line(points?: PointArrayAlias): Line;
        line(x1: number, y1: number, x2: number, y2: number): Line;
        link(url: string): A;
        marker(width?: number, height?: number, block?: (marker: Marker) => void): Marker
        mask(): Mask;
        nested(): Svg;
        path(): Path;
        path(d: PathArrayAlias): Path;
        pattern(width?: number, height?: number, block?: (pattern: Pattern) => void): Pattern
        plain(text: string): Text;
        polygon(points?: PointArrayAlias): Polygon;
        polyline(points?: PointArrayAlias): Polyline;
        rect(width?: number, height?: number): Rect;
        style(): Style;
        text(block: (tspan: Tspan) => void): Text;
        text(text: string): Text;
        ungroup(parent: Dom, depth?: number): this;
        use(element: Element | string, file?: string): Use;
        viewbox(): Box;
        viewbox(viewbox: ViewBoxLike | string): this;
        viewbox(x: number, y: number, width: number, height: number): this;
        textPath(text: string | Text, path: string | Path): TextPath
        symbol(): Symbol
        zoom(): number
        zoom(level: NumberAlias, point?: Point): this;
    }

コンテナは、図形の容れ物という意味だけでなくてメソッドのコンテナ(APIプロバイダ)にもなっているオブジェクトのこと。