본문 바로가기
웹/오픈레이어스

오픈레이어스 이미지 저장 및 프린트

by 아카이sun 2022. 2. 15.

오픈레이어스의 이미지 저장 및 프린트를 하기 위해서는 별도의 코드 구현이 필요하다.

구글 검색을 해보면 여러 케이스가 나오지만 제대로 작동되지 않는 코드가 많이 있었다.

공식 홈페이지에서 정상작동하는 코드를 확인할 수 있다.

현재시간 기준으로 6.5.0 버전에서 정상작동하는 코드를 정리하였다.

 

- 이미지 저장

map.once('rendercomplete', function(event) {
    const mapCanvas = document.createElement("canvas");
    const size = map.getSize();
    mapCanvas.width = size[0];
    mapCanvas.height = size[1];
    const mapContext = mapCanvas.getContext("2d");

    Array.prototype.forEach.call(
    	map.getViewport().querySelectorAll('.ol-layer canvas, canvas.ol-layer'),
        canvas => {
            if (canvas.width > 0) {
                let matrix;
                const transform = canvas.style.transform;
                if (transform) {
                    matrix = transform
                        .match(/^matrix\(([^\(]*)\)$/)[1]
                        .split(',')
                        .map(Number);
                } else {
                    matrix = [
                        parseFloat(canvas.style.width) / canvas.width,
                        0,
                        0,
                        parseFloat(canvas.style.height) / canvas.height,
                        0,
                        0,
                    ];
                }
                CanvasRenderingContext2D.prototype.setTransform.apply(mapContext, matrix);
                mapContext.drawImage(canvas, 0, 0);
            }
        }
    );

    if (navigator.msSaveBlob) {
        navigator.msSaveBlob(mapCanvas.msToBlob(), 'map.png');
    } else {
        const link = document.getElementById('image-download');
        link.href = mapContext.canvas.toDataURL("image/jpeg");
        link.click();
    }
});
map.renderSync();

 

- 프린트

map.once('rendercomplete', function(event) {
    const mapCanvas = document.createElement("canvas");
    const size = map.getSize();
    mapCanvas.width = size[0];
    mapCanvas.height = size[1];
    const mapContext = mapCanvas.getContext("2d");

    Array.prototype.forEach.call(
    	map.getViewport().querySelectorAll('.ol-layer canvas, canvas.ol-layer'),
        canvas => {
            if (canvas.width > 0) {
                let matrix;
                const transform = canvas.style.transform;
                if (transform) {
                    matrix = transform
                        .match(/^matrix\(([^\(]*)\)$/)[1]
                        .split(',')
                        .map(Number);
                } else {
                    matrix = [
                        parseFloat(canvas.style.width) / canvas.width,
                        0,
                        0,
                        parseFloat(canvas.style.height) / canvas.height,
                        0,
                        0,
                    ];
                }
                CanvasRenderingContext2D.prototype.setTransform.apply(mapContext, matrix);
                mapContext.drawImage(canvas, 0, 0);
            }
        }
    );

    let windowContent = `<img src="${mapContext.canvas.toDataURL("image/jpeg")}">`;
    const printWin = window.open('', '', `width=${screen.availWidth},height=${screen.availHeight}`);
    printWin.document.open();
    printWin.document.write(windowContent);

    printWin.document.addEventListener('load', function() {
        printWin.focus();
        printWin.print();
        printWin.document.close();
        printWin.close();
    }, true);
});
map.renderSync();

 

 

- 이미지 저장 및 프린트 함수 구현

/**
     * image save & print
     * @param sx start x
     * @param sy start y
     * @param dw width
     * @param dh height
     * @param isPrint
     */
export = (sx, sy, dw, dh, isPrint = false) => {
        const map = this.map;
        map.once('rendercomplete', (evt) => {
            const mapCanvas = document.createElement("canvas");
            
            mapCanvas.width = dw;
            mapCanvas.height = dh;
            const mapContext = mapCanvas.getContext("2d");

            Array.prototype.forEach.call(
                map.getViewport().querySelectorAll('.ol-layer canvas, canvas.ol-layer'),
                canvas => {
                    if (canvas.width > 0) {
                        let matrix;
                        const transform = canvas.style.transform;
                        if (transform) {
                            matrix = transform
                                .match(/^matrix\(([^\(]*)\)$/)[1]
                                .split(',')
                                .map(Number);
                        } else {
                            matrix = [
                                parseFloat(canvas.style.width) / canvas.width,
                                0,
                                0,
                                parseFloat(canvas.style.height) / canvas.height,
                                0,
                                0,
                            ];
                        }
                        CanvasRenderingContext2D.prototype.setTransform.apply(mapContext, matrix);
                        mapContext.drawImage(canvas, 0, 0);
                    }
                }
            );

            if(isPrint) {
                let windowContent = `<img src="${mapContext.canvas.toDataURL("image/jpeg")}">`;
                const printWin = window.open('', '', `width=${screen.availWidth},height=${screen.availHeight}`);
                printWin.document.open();
                printWin.document.write(windowContent);

                printWin.document.addEventListener('load', function() {
                    printWin.focus();
                    printWin.print();
                    printWin.document.close();
                    printWin.close();
                }, true);
            } else {
                if (navigator.msSaveBlob) {
                    navigator.msSaveBlob(mapCanvas.msToBlob(), 'map.png');
                } else {
                    const link = document.getElementById('image-download');
                    link.href = mapContext.canvas.toDataURL("image/jpeg");
                    link.click();
                }
            }
        });
        map.renderSync();
    }

 


주의할 점 !!

아래와 같이 클릭 가능한 범위안에 download 링크를 같이 넣게 되면 rendercomplete가 무한으로 재 호출되는 현상을 보게 될 것이다.

<span onclick="saveImage();">
    <i class="icon icon-export-save"></i>
    <a id="image-download" download="map.png"></a>
</span>

따라서 a태그는 클릭 범위 밖으로 이동시켜야 한다.

a태그를 이동시키고 테스트 해보니 여러번 호출되던 현상이 사라졌다.

<span onclick="saveImage();">
    <i class="icon icon-export-save"></i>
</span>
<a id="image-download" download="map.png"></a>

' > 오픈레이어스' 카테고리의 다른 글

오픈레이어스 카카오맵(타일) 사용하기  (0) 2023.01.19
오픈레이어스 버전 확인  (0) 2022.02.15

댓글