HTMLCanvasElements를 이미지로 저장

24618 단어 chartjstypescript

소개



이번에는 Chart.js로 그린 차트를 이미지로 저장하고 싶습니다.
  • Chart.js

  • 이를 위해 HTMLCanvasElement를 이미지로 저장해 보겠습니다.

    이번에는 샘플을 사용하여 Chart.js를 사용합니다.
    다음에 Chart.js를 사용해 보겠습니다.

    환경


  • Node.js 버전 15.0.0

  • 패키지.json




    {
        "browserslist": [
            "last 2 version"
        ],
        "scripts": {
            "css": "npx postcss postcss -c postcss.config.js -d wwwroot/css -w"
        },
        "dependencies": {
            "autoprefixer": "^10.0.1",
            "chart.js": "^2.9.4",
            "postcss": "^8.1.2",
            "postcss-cli": "^8.1.0",
            "postcss-import": "^13.0.0",
            "precss": "^4.0.0",
            "ts-loader": "^8.0.6",
            "tsc": "^1.20150623.0",
            "typescript": "^4.0.3",
            "webpack": "^5.2.0",
            "webpack-cli": "^4.1.0"
        },
        "devDependencies": {
            "@types/chart.js": "^2.9.27",
            "whatwg-fetch": "^3.4.1"
        }
    }
    


    기본 프로젝트



    ChartPage.html




    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <link rel="stylesheet" type="text/css" href="../css/chart_page.css" >
        </head>
        <body>
            <div id="outside">
                <h1>Chart</h1>
                <div class="chart_area">
                    <canvas id="chart_1" class="chart_canvas"></canvas>
                </div>
            </div>
            <button onclick="Page.save()">Save</button>
            <script src="../js/chartPage.bundle.js"></script>
            <script>
                (function() {
                    Page.init();
                })();
            </script>
        </body>
    </html>
    


    chart_page.css




    .chart_area{
        background-color: white;
        border: solid black 1px;
        display: flex;
        align-items: center;
        justify-content: center;
        height: 300px;
        width: 300px;
    }
    .chart_canvas {
    }
    


    차트 샘플 그리기



    이번에는 Chart.js 문서의 차트 샘플을 사용합니다.
  • Introduction · Chart.js documentation

  • chart.page.ts




    import { SampleDrawer } from "./charts/sample-drawer";
    
    export function init() {
        const target = document.getElementById('chart_1');
        if (target == null)
        {
            return;
        }
        const drawer = new SampleDrawer();
        drawer.draw(target as HTMLCanvasElement);
    }
    


    샘플 서랍.ts




    import Chart from "chart.js";
    
    export class SampleDrawer {
        public draw(canvas: HTMLCanvasElement) {
            const context = canvas.getContext('2d');
            if (context == null) {
                console.error('failed getting context');
                return;
            }
            this.drawSample(canvas);
        }
        private drawSample(canvas: HTMLCanvasElement) {
            const chart = new Chart(canvas, {
                // as same as the sample script at "Creating a Chart"
            });
        }
    }
    


    결과





    차트 크기는 상위 요소(
    )의 너비 또는 높이에서 가져옵니다.
    차트 인스턴스를 인스턴스화하기 전에 캔버스 크기, 배경색 등을 변경하더라도 무시됩니다.

    이미지로 저장



    HTMLCanvasElement는 Blob 또는 Base64 문자열을 생성할 수 있으며 이를 사용하여 이미지를 만들 수 있습니다.
    서버 응용 프로그램으로 이미지를 저장하는 경우 "toDataURL"을 사용하고 Base64 문자열을 서버로 보내는 것을 선호합니다.
  • HTMLCanvasElement.toDataURL() - Web APIs | MDN

  • 하지만 이번에는 "toBlob()"을 사용하여 TypeScript로 다운로드합니다.
  • HTMLCanvasElement.toBlob() - Web APIs | MDN

  • chart.page.ts




    ...
    export function save() {
        const target = document.getElementById('chart_1');
        if (target == null)
        {
            console.error('chart_1 was not found');
            return;
        }
        const targetCanvas = target as HTMLCanvasElement;
        targetCanvas.toBlob((blob) => downloadImageBlob(blob), 'image/jpeg', 1);
    }
    function downloadImageBlob(blob: Blob|null) {
        if(blob == null){
            console.error('Failed getting image blob');
            return;
        }
        if (navigator.msSaveBlob == null) {
            if (navigator.msSaveBlob == null) {
            const linkElement = document.getElementById('download_link') as HTMLAnchorElement;
            linkElement.href = window.URL.createObjectURL(blob);
            linkElement.download = 'sample_file.jpg';
            linkElement.click();
            return;
        }
        // for IE
        window.navigator.msSaveBlob(blob, 'sample_file.jpg');
    }
    


    ChartPage.html




    ...
            <button onclick="Page.save()">Save</button>
            <a id="download_link"></a>
            <script src="../js/polyfill/toBlob.js"></script>
            <script src="../js/chartPage.bundle.js"></script>
    ...
    


    생성된 이미지를 다운로드하기 위해 AnchorElement를 추가합니다.
  • javascript - Fetch API Download File - Stack Overflow

  • 그리고 IE의 경우 polyfill 파일을 추가합니다.
  • HTMLCanvasElement.toBlob() - Web APIs | MDN

  • 결과





    배경색은 어디에서 왔습니까?
    차트에 배경색이 없어서 Jpeg 이미지(투명도 없음)로 저장했습니다.

    그래서 배경색을 설정해야 합니다.
    그러나 캔버스 배경색은 무시합니다.

    배경색 설정



    배경색을 설정하기 위해 Chart.js의 플러그인을 사용합니다.
  • Plugins · Chart.js documentation

  • 샘플 서랍.ts




        public draw(canvas: HTMLCanvasElement) {
            const context = canvas.getContext('2d');
            if (context == null) {
                return;
            }
            this.drawBackground();
            this.drawSample(canvas);
        }
        private drawBackground() {
            Chart.pluginService.register({
                beforeDraw: c => {
                    const ctx = c.ctx;
                    if (ctx == null){
                        return;
                    }
                    const canvas = c.canvas;
                    if (canvas == null) {
                        return;
                    }
                    ctx.fillStyle = 'rgba(255, 255, 255, 1)';                
                    ctx.fillRect(0, 0, canvas.width, canvas.height);
                }
            });
        }
    ...
    


    결과





    차트 숨기기 및 이미지 저장



    차트에서 동적으로 생성된 이미지만 표시하고 차트는 숨길 수 있습니까?

    디스플레이:없음; (실패한)



    chart_page.css




    #outside{
        display: none;
    }
    ...
    


    "toBlob()"으로 얼룩을 가져올 수 없습니다.

    가시성: 숨김; (성공)



    chart_page.css




    #outside{
        visibility: hidden;
    }
    ...
    


    외부 그리기(성공)




    #outside{
    }
    .chart_area{
    ...
        height: 1024px;
        width: 1024px;
        position: absolute;
        top: -2000px;
        left: -2000px;
    }
    ...
    

    좋은 웹페이지 즐겨찾기