Chart.js를 서버 측에서 사용하는 방법

Chart.js은 JavaScript에서 사용할 수있는 주요 차트 (그래프) 그리기 라이브러리 중 하나이지만 HTML DOM,보다 정확하게 말하면 HTML5 Canvas API에 의존하기 때문에 Node.js 환경에서는 작동하지 않습니다. .

그러나 Canvas 이외의 종속성은 거의 없기 때문에 Canvas API만 준비하면 서버 측 렌더링 (SSR)이 가능합니다.

이번에는 내가 직접 만든 Canvas API 호환 라이브러리 red-agate-svg-canvas을 사용하여 Node.js에서 SVG로 렌더링하고 싶습니다.

이번 모든 소스는 여기에 있습니다.

추가 (2018/9/18)



이번에 설명하는 것 외에 chartjs-node 등의 패키지를 사용해도 서버 측에서 Chart.js를 사용할 수 있습니다.
chartjs-node의 장점은 jpeg와 png와 같은 래스터 이미지, svg, 심지어 pdf 출력에도 대응하고 있지만, 이것을 실현하기 위해 cairo 설정은 조금 번거로움입니다.

해설


import { SvgCanvas,
         Rect2D,
         SvgCanvas2DGradient } from 'red-agate-svg-canvas/modules';
import * as ChartJs            from 'chart.js';

// グローバルスコープを取得します。
// もし、Node.jsで動作してるならば、 "g" は "global" オブジェクトになります。
// ブラウザー上ならば、 "g" は "window" オブジェクトになります。
const g = Function('return this')();

// グラフの描画オプションです。
// https://www.chartjs.org/docs/latest/getting-started/usage.html
const opts: any = { /* 中略 */ };


function main() {
    // SvgCanvas は "CanvasRenderingContext2D" と互換のインターフェイスを持っています。
    const ctx = new SvgCanvas();

    // しかしながら、 SvgCanvas には canvas プロパティーがありません。
    // canvas プロパティーには本来、このコンテキストの親となる HTMLCanvasElement が設定されています。
    // Chart.js では、以下のプロパティーのみ存在すれば問題ありません。
    (ctx as any).canvas = {
        width: 800,
        height: 400,
        style: {
            width: '800px',
            height: '400px',
        },
    };

    // SvgCanvas の実装は、ホスト環境のフォント(グリフ)情報にアクセスしません。
    // 文字列のピクセルでの幅を求められるようにするために、フォントの縦横比を手動で設定します。
    ctx.fontHeightRatio = 2;

    // Chart.js には "HTMLCanvasElement" と互換のインターフェイスを持つオブジェクトを渡す必要があります。
    // そのオブジェクトは、"getContext()" メソッドのみを持っていれば問題ありません。
    // "getContext()" は "CanvasRenderingContext2D" と互換のインターフェイスを持つオブジェクトを返さなければなりません。
    const el = { getContext: () => ctx };

    // もし、描画オプションに "devicePixelRatio" を設定しないと、
    // Chart.js は devicePixelRatio を "window" オブジェクトから取得しようとします。
    // その場合、 node.js では window オブジェクトが存在しないため、エラーとなってしまいます。
    opts.options.devicePixelRatio = 1;

    // アニメーションを無効にします。
    opts.options.animation = false;
    opts.options.events = [];
    opts.options.responsive = false;

    // Chart.js は描画設定によっては、グローバルスコープの "CanvasGradient" を参照しようとします。
    // エラーを防ぐために、 SvgCanvas のグラデーションオブジェクトをグローバルスコープに設定します。
    const savedGradient = g.CanvasGradient;
    g.CanvasGradient = SvgCanvas2DGradient;
    try {
        const chart = new ChartJs.Chart(el as any, opts);
    } finally {
        // グローバルスコープを元に戻します。
        if (savedGradient) {
            g.CanvasGradient = savedGradient;
        }
    }

    // SVGとして描画します。
    const svgString = ctx.render(new Rect2D(0, 0 , 800, 400), 'px');
    console.log(svgString);
}

렌더링 결과 (Chrome의 표시 결과)


  • SVG 이미지는 Qiita 편집기에서 업로드되지 않으므로 Chrome에서 보고 캡처했습니다.
  • 실제 SVG는 여기입니다.






  • 도넛





    라인





    지역





    비고


  • 현재 빌드에는 Webpack과 babel이 필요합니다.


  • 사이고에게



    위의 차트, UML, 바코드, 2D 코드를 문서에 통합하여 HTML 및 PDF로 렌더링
    콘솔 앱 Ménneu을 게시했습니다.
    후발의 앱입니다만, 아울러 보실 수 있으면이라고 생각합니다.

    좋은 웹페이지 즐겨찾기