웹에서 PDF 파일을 생성하는 것은 클라이언트가 서버에 PDF 파일 생성을 요청하고 서버측에서 생성한 PDF 파일을 클라이언트에서는 다운로드 하는 방식으로 이루어졌다. 하지만 서버의 기술 없이도 클라이언트에서 PDF 파일을 생성해 내려받을 수 있는데, 이를 ol의 지도를 PDF 파일로 생성하는 것을 토대로 정리해 본다.
웹에서 JS만으로 PDF를 생성하는 API로 많이 사용되는 jspdf.js 라이브러리가 있는데 이를 이용한다.
먼저 index.html에 UI 요소에 대한 코드를 다음처럼 작성한다.
OpenLayers
jspdf.js 스크립트에 대한 추가와 DOM 요소로써 PDF로 출력할 지도에 대한 DIV 및 PDF 출력을 위한 버튼이 보인다. index.js에 JS 코드를 작성할 것인데, 하나씩 살펴보자.
먼저 필요한 모듈을 추가한다.
import 'ol/ol.css'; import Map from 'ol/Map.js'; import View from 'ol/View.js'; import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer.js'; import {OSM, Vector as VectorSource} from 'ol/source.js';
다음은 출력할 지도 객체에 대한 코드이다.
var map = new Map({ layers: [ new TileLayer({ source: new OSM() }) ], target: 'map', view: new View({ center: [0, 0], zoom: 2 }) });
이제 버튼을 클릭하면 해당 지도의 내용이 PDF로 출력되는데, 이를 위해 필요한 변수이다.
var format = 'a4'; /* Unit : mm A0: [1189, 841] A1: [841, 594] A2: [594, 420] A3: [420, 297] A4: [297, 210] A5: [210, 148] */ var dim = [297, 210]; var resolution = 150; //dpi (Unit: inch)
지도를 A4 용지 크기로 PDF 출력할 것이고, A4 용지의 크기는 397mm x 210mm 라는 점. 그리고 출력 DPI 해상도는 150으로 지정했는데, 이를 높이면 그만큼 출력 품질은 올라가지만 더 많은 CPU와 메모리 자원을 사용하고 생성하는 시간도 상당이 길어진다. 다음은 출력 버튼의 클릭 이벤트에 대한 코드이다.
var btn = document.querySelector('#btn'); btn.addEventListener('click', function() { btn.disabled = true; document.body.style.cursor = 'progress'; var width = Math.round(dim[0] * resolution / 25.4); // 1in = 25.4mm var height = Math.round(dim[1] * resolution / 25.4); var size = /** @type {module:ol/size~Size} */ (map.getSize()); var extent = map.getView().calculateExtent(size); map.once('rendercomplete', function(event) { var canvas = event.context.canvas; var data = canvas.toDataURL('image/jpeg'); var pdf = new jsPDF({ orientation: 'landscape', unit: 'mm', format: format }); pdf.addImage(data, 'JPEG', 0, 0, dim[0], dim[1]); pdf.save('map.pdf'); // Reset original map size map.setSize(size); map.getView().fit(extent, {size: size}); btn.disabled = false; document.body.style.cursor = 'auto'; }); // Set print size var printSize = [width, height]; map.setSize(printSize); map.getView().fit(extent, {size: printSize}); }, false);
위의 코드를 이해하기 위해서는 먼저 jspdf.js 라이브러리의 사용법을 익히는게 필요하다. 중요한 부분만을 언급하면 7~10번은 앞서 A4 용지 크기만큼 지도를 출력하기 위해서는 A4 용지의 크기만큼 지도를 다시 그려줘야하는데 그려줄 영역의 크기를 계산하고 이 크기를 33~35번 코드처럼 지도 객체에 설정하게 되면 지도가 그려지게 시작하면서 다 그려지면 rendercomplete 이벤트가 발생한다. 이 이벤트에 대한 호출 함수는 12번에서 정의되어 있는데 여기서 jsPDF 라이브러리를 사용하는 코드가 보인다. jsPDF를 통해 PDF 출력이 끝나면 다시 지도를 원래의 크기로 되돌리기 위해 25~26번 코드의 호출이 필요하다.