原文链接及内容

运行界面

按指定比例打印地图的示例。使用jsPDF库将打印结果导出为PDF。与导出PDF示例不同,屏幕上的地图仅用于设置中心和旋转。打印的范围取决于比例和页面大小。该示例使用html2canvas库来打印比例尺和属性。

main.js代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import Map from 'ol/Map.js';
import TileLayer from 'ol/layer/Tile.js';
import View from 'ol/View.js';
import WMTS, {optionsFromCapabilities} from 'ol/source/WMTS.js';
import WMTSCapabilities from 'ol/format/WMTSCapabilities.js';
import proj4 from 'proj4';
import {ScaleLine, defaults as defaultControls} from 'ol/control.js';
import {getPointResolution, get as getProjection} from 'ol/proj.js';
import {register} from 'ol/proj/proj4.js';

proj4.defs(
'EPSG:27700',
'+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 ' +
'+x_0=400000 +y_0=-100000 +ellps=airy ' +
'+towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 ' +
'+units=m +no_defs'
);

register(proj4);

const proj27700 = getProjection('EPSG:27700');
proj27700.setExtent([0, 0, 700000, 1300000]);

const raster = new TileLayer();

const url =
'https://tiles.arcgis.com/tiles/qHLhLQrcvEnxjtPr/arcgis/rest/services/OS_Open_Raster/MapServer/WMTS';
fetch(url)
.then(function (response) {
return response.text();
})
.then(function (text) {
const result = new WMTSCapabilities().read(text);
const options = optionsFromCapabilities(result, {
layer: 'OS_Open_Raster',
});
options.attributions =
'Contains OS data © Crown Copyright and database right ' +
new Date().getFullYear();
options.crossOrigin = '';
options.projection = proj27700;
options.wrapX = false;
raster.setSource(new WMTS(options));
});

const map = new Map({
layers: [raster],
controls: defaultControls({
attributionOptions: {collapsible: false},
}),
target: 'map',
view: new View({
center: [373500, 436500],
projection: proj27700,
zoom: 7,
}),
});

const scaleLine = new ScaleLine({bar: true, text: true, minWidth: 125});
map.addControl(scaleLine);

const dims = {
a0: [1189, 841],
a1: [841, 594],
a2: [594, 420],
a3: [420, 297],
a4: [297, 210],
a5: [210, 148],
};

// export options for html2canvase.
// See: https://html2canvas.hertzen.com/configuration
const exportOptions = {
useCORS: true,
ignoreElements: function (element) {
const className = element.className || '';
return (
className.includes('ol-control') &&
!className.includes('ol-scale') &&
(!className.includes('ol-attribution') ||
!className.includes('ol-uncollapsible'))
);
},
};

const exportButton = document.getElementById('export-pdf');

exportButton.addEventListener(
'click',
function () {
exportButton.disabled = true;
document.body.style.cursor = 'progress';

const format = document.getElementById('format').value;
const resolution = document.getElementById('resolution').value;
const scale = document.getElementById('scale').value;
const dim = dims[format];
const width = Math.round((dim[0] * resolution) / 25.4);
const height = Math.round((dim[1] * resolution) / 25.4);
const viewResolution = map.getView().getResolution();
const scaleResolution =
scale /
getPointResolution(
map.getView().getProjection(),
resolution / 25.4,
map.getView().getCenter()
);

map.once('rendercomplete', function () {
exportOptions.width = width;
exportOptions.height = height;
html2canvas(map.getViewport(), exportOptions).then(function (canvas) {
const pdf = new jspdf.jsPDF('landscape', undefined, format);
pdf.addImage(
canvas.toDataURL('image/jpeg'),
'JPEG',
0,
0,
dim[0],
dim[1]
);
pdf.save('map.pdf');
// Reset original map size
scaleLine.setDpi();
map.getTargetElement().style.width = '';
map.getTargetElement().style.height = '';
map.updateSize();
map.getView().setResolution(viewResolution);
exportButton.disabled = false;
document.body.style.cursor = 'auto';
});
});

// Set print size
scaleLine.setDpi(resolution);
map.getTargetElement().style.width = width + 'px';
map.getTargetElement().style.height = height + 'px';
map.updateSize();
map.getView().setResolution(scaleResolution);
},
false
);

界面布局文件index.html代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Print to scale example</title>
<link rel="stylesheet" href="node_modules/ol/ol.css">
<style>
.map {
width: 100%;
height: 400px;
}
.wrapper {
max-width: 566px;
width: 100%;
height: 400px;
overflow: hidden;
}
</style>
</head>
<body>
<div class="wrapper">
<div id="map" class="map"></div>
</div>
<form class="form">
<label for="format">Page size </label>
<select id="format">
<option value="a0">A0 (slow)</option>
<option value="a1">A1</option>
<option value="a2">A2</option>
<option value="a3">A3</option>
<option value="a4" selected>A4</option>
<option value="a5">A5 (fast)</option>
</select>
<label for="resolution">Resolution </label>
<select id="resolution">
<option value="72">72 dpi (fast)</option>
<option value="150">150 dpi</option>
<option value="200" selected>200 dpi</option>
<option value="300">300 dpi (slow)</option>
</select>
<label for="scale">Scale </label>
<select id="scale">
<option value="500">1:500000</option>
<option value="250" selected>1:250000</option>
<option value="100">1:100000</option>
<option value="50">1:50000</option>
<option value="25">1:25000</option>
<option value="10">1:10000</option>
</select>
</form>
<button id="export-pdf">Export PDF</button>
<!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
<script src="https://cdn.jsdelivr.net/npm/elm-pep@1.0.6/dist/elm-pep.js"></script>
<script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.3.1/jspdf.umd.min.js"></script>
<script type="module" src="main.js"></script>
</body>
</html>