Skip to content

Commit

Permalink
Merge branch 'master' into v2.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Grammostola committed Oct 1, 2021
2 parents 40455df + 609a8f6 commit 0614df0
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 30 deletions.
6 changes: 4 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=Edge;chrome=1">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src *; script-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self'; style-src 'unsafe-inline'; style-src-elem 'self'; base-uri 'self'; form-action 'self';">
<meta name="referrer" content="same-origin">
<!-- On production systems a Content-Security-Policy and referrer meta-tag should be added, see below.
The CSP should be modified with adding specific sources that should be allowed, f.e. connect-src 'self' webanalysis.example.com geospatialdata.example.com; -->
<!-- <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src * data:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self'; style-src 'self' 'unsafe-inline'; style-src-elem 'self' 'unsafe-inline'; base-uri 'self'; form-action 'self';">
<meta name="referrer" content="same-origin"> -->
<title>Origo exempel</title>
<link href="css/style.css" rel="stylesheet">
<link rel="shortcut icon" href="img/png/logo.png">
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"copyfiles": "^2.4.1",
"core-js": "^3.8.2",
"cuid": "^2.1.4",
"dom-to-image-more": "^2.8.0",
"dom-to-image-more": "2.8.0",
"downloadjs": "^1.4.7",
"elm-pep": "^1.0.6",
"html2canvas": "^1.0.0-rc.7",
Expand Down
6 changes: 4 additions & 2 deletions src/controls/print/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ const Print = function Print(options = {}) {
rotationStep = 1,
leftFooterText = '',
filename,
mapInteractionsActive = false
mapInteractionsActive = false,
supressResolutionsRecalculation = false
} = options;
let {
showNorthArrow = true
Expand Down Expand Up @@ -107,7 +108,8 @@ const Print = function Print(options = {}) {
rotation,
rotationStep,
leftFooterText,
mapInteractionsActive
mapInteractionsActive,
supressResolutionsRecalculation
});
if (placement.indexOf('screen') > -1) {
mapTools = `${viewer.getMain().getMapTools().getId()}`;
Expand Down
142 changes: 139 additions & 3 deletions src/controls/print/print-component.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import olAttribution from 'ol/control/Attribution';
import olScaleLine from 'ol/control/ScaleLine';
import { getPointResolution } from 'ol/proj';
import TileImage from 'ol/source/TileImage';
import TileWMSSource from 'ol/source/TileWMS';
import TileGrid from 'ol/tilegrid/TileGrid';
import { Group } from 'ol/layer';
import {
Button, Component, cuid, dom
} from '../../ui';
Expand All @@ -11,6 +15,7 @@ import PrintInteractionToggle from './print-interaction-toggle';
import PrintToolbar from './print-toolbar';
import { downloadPNG, downloadPDF, printToScalePDF } from '../../utils/download';
import { afterRender, beforeRender } from './download-callback';
import maputils from '../../maputils';

const PrintComponent = function PrintComponent(options = {}) {
const {
Expand All @@ -34,13 +39,13 @@ const PrintComponent = function PrintComponent(options = {}) {
sizeCustomMinWidth,
sizeCustomMaxWidth,
resolutions,
scales,
scaleInitial,
createdPrefix,
rotation,
rotationStep,
leftFooterText,
mapInteractionsActive
mapInteractionsActive,
supressResolutionsRecalculation
} = options;

let {
Expand All @@ -51,6 +56,7 @@ const PrintComponent = function PrintComponent(options = {}) {
size,
orientation,
resolution,
scales,
showMargins,
showCreated,
showScale,
Expand All @@ -70,6 +76,111 @@ const PrintComponent = function PrintComponent(options = {}) {
let printScale = 0;
let widthImage = 0;
let heightImage = 0;
const originalResolutions = viewer.getResolutions().map(item => item);
const originalGrids = new Map();

if (!Array.isArray(scales) || scales.length === 0) {
scales = originalResolutions.map(currRes => maputils.resolutionToFormattedScale(currRes, viewer.getProjection()));
}

/**
* Recalulates a resoultions array to reflect dpi changes
* @param {number []} src the array of resolutions
* @returns {number []} A new array with recalculated values
*/
const recalculateResolutionsArray = function recalculateResolutionsArray(src) {
const retval = [];
for (let ix = 0; ix < src.length; ix += 1) {
// Do the calculation the same way as when setting the scale. Otherwise there will be rounding errors and the scale bar will have another scale than selected
// (and probably not an even nice looking number)
const scale = maputils.resolutionToScale(src[ix], viewer.getProjection()) / 1000;
const scaleResolution = scale / getPointResolution(viewer.getProjection(), resolution / 25.4, map.getView().getCenter());
retval.push(scaleResolution);
}
return retval;
};

/**
* Recursively flattens group layers in an array of layers
* @param {any []} layers Array of layers
* @returns {any []} Array of layers with group layers flattened
*/
const flattenLayers = function flattenLayers(layers) {
return layers.reduce((acc, currLayer) => {
if (currLayer instanceof Group) {
// eslint-disable-next-line no-param-reassign
acc = acc.concat(flattenLayers(currLayer.getLayers().getArray()));
} else {
acc.push(currLayer);
}
return acc;
}, []);
};

/** Recalculate the grid of tiled layers when resolution has changed as more tiles may be needed to cover the extent */
const updateTileGrids = function updateTileGrids() {
const layers = flattenLayers(viewer.getLayers());
for (let i = 0; i < layers.length; i += 1) {
const currLayer = layers[i];
if (currLayer.getSource() instanceof TileImage) {
const grid = currLayer.getSource().getTileGrid();
let needNewGrid = false;
// Store original grid if we don't have it already
// Don't always copy as it is only the first time it is original grid
if (!originalGrids.has(currLayer)) {
originalGrids.set(currLayer, grid);
}

// Deep copy grid so we can exchange it without messing with anything else
const newgridOptions = {};
// If layer uses the grid from the viewer, it is a shared instance and has been changed when resolutions were recalculated
// as the grid uses a pointer to resolutions
if (grid === viewer.getTileGrid()) {
// No need for deep copy yet
newgridOptions.resolutions = originalResolutions;
needNewGrid = true;
} else {
// No need for deep copy yet
newgridOptions.resolutions = originalGrids.get(currLayer).getResolutions();
}

// TileWms is actually not a tile service. So we can create a new dynamic grid to create crisp tiles matching the new
// resolutions, it will just cost a few cache misses on the server. All other tile sources are tiled, so we can't assume that there exist tiles for a "random" resolution
// so the new grid is actually the same as before, but it may have been reverted to the resolutions it had before map resolutions was recalculated
// An alternative (better) solution would have been to deep copy resolutions when making the grid in viewer, but that might upset someone else.
// In theory we could have added a flag to which layers should be recalculated. Someone might have multiple grids to support different resolutions.
if (currLayer.getSource() instanceof TileWMSSource) {
// This is actually a deep copy
newgridOptions.resolutions = recalculateResolutionsArray(newgridOptions.resolutions);
needNewGrid = true;
}
// Would be silly to create a deep clone if it is exactly the same.
if (needNewGrid) {
newgridOptions.extent = grid.getExtent();
newgridOptions.minZoom = grid.getMinZoom();
newgridOptions.origin = grid.getOrigin();
newgridOptions.tileSize = grid.getTileSize();
const newGrid = new TileGrid(newgridOptions);
// Set our brand new grid on current layer
currLayer.getSource().tileGrid = newGrid;
}
}
}
};

/** Recalculate the array of allowed zoomlevels to reflect changes in DPI and updates the view */
const updateResolutions = function updateResolutions() {
const viewerResolutions = viewer.getResolutions();
const newResolutions = recalculateResolutionsArray(originalResolutions);
for (let ix = 0; ix < viewerResolutions.length; ix += 1) {
viewerResolutions[ix] = newResolutions[ix];
}
// As we do a "dirty" update of resolutions we have to trigger a re-read of the limits, otherwise the outer limits still apply.
map.getView().setMinZoom(0);
map.getView().setMaxZoom(viewerResolutions.length - 1);
// Have to recalculate tiles extents as well.
updateTileGrids();
};

const setCustomSize = function setCustomSize(sizeObj) {
if ('width' in sizeObj) {
Expand Down Expand Up @@ -157,7 +268,8 @@ const PrintComponent = function PrintComponent(options = {}) {
showScale,
showNorthArrow,
rotation,
rotationStep
rotationStep,
viewerResolutions: originalResolutions
});
const printInteractionToggle = PrintInteractionToggle({ map, target, mapInteractionsActive, pageSettings: viewer.getViewerOptions().pageSettings });
const printToolbar = PrintToolbar();
Expand All @@ -170,6 +282,7 @@ const PrintComponent = function PrintComponent(options = {}) {
name: 'printComponent',
onInit() {
this.on('render', this.onRender);

this.addComponent(printSettings);
this.addComponent(printInteractionToggle);
this.addComponent(printToolbar);
Expand Down Expand Up @@ -246,6 +359,10 @@ const PrintComponent = function PrintComponent(options = {}) {
},
changeResolution(evt) {
resolution = evt.resolution;
if (!supressResolutionsRecalculation) {
updateResolutions();
}

this.updatePageSize();
if (printScale > 0) {
this.changeScale({ scale: printScale });
Expand Down Expand Up @@ -276,6 +393,22 @@ const PrintComponent = function PrintComponent(options = {}) {
printMapComponent.dispatch('change:toggleNorthArrow', { showNorthArrow });
},
close() {
// Restore scales
if (!supressResolutionsRecalculation) {
const viewerResolutions = viewer.getResolutions();
for (let ix = 0; ix < viewerResolutions.length; ix += 1) {
viewerResolutions[ix] = originalResolutions[ix];
}
originalGrids.forEach((value, key) => {
// Sorry, but there is no setter and a map does not allow indexing.
// eslint-disable-next-line no-param-reassign
key.getSource().tileGrid = value;
});
// As we do a "dirty" update of resolutions we have to trigger a re-read of the limits, otherwise the outer limits still apply.
map.getView().setMinZoom(0);
map.getView().setMaxZoom(viewerResolutions.length - 1);
originalGrids.clear();
}
printMapComponent.removePrintControls();
if (map.getView().getRotation() !== 0) {
map.getView().setRotation(0);
Expand Down Expand Up @@ -354,6 +487,9 @@ const PrintComponent = function PrintComponent(options = {}) {
map.setTarget(printMapComponent.getId());
this.removeViewerControls();
printMapComponent.addPrintControls();
if (!supressResolutionsRecalculation) {
updateResolutions();
}
printMapComponent.dispatch('change:toggleScale', { showScale });
this.updatePageSize();
},
Expand Down
26 changes: 12 additions & 14 deletions src/controls/print/set-scale-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ export default function SetScaleControl(options = {}, map) {
initialScale
} = options;

let projection;
let resolutions;
let selectScale;

function getScales() {
return resolutions.map(resolution => mapUtils.resolutionToFormattedScale(resolution, projection));
/**
* Parses a formatted scale string and returns the denominator as a number
* @param {any} scale
*/
function parseScale(scale) {
return parseInt(scale.replace(/\s+/g, '').split(':').pop(), 10);
}

return Component({
Expand All @@ -26,30 +28,26 @@ export default function SetScaleControl(options = {}, map) {
text: 'Välj skala'
});
this.addComponents([selectScale]);
projection = map.getView().getProjection();
resolutions = map.getView().getResolutions();
},
onChangeScale(evt) {
const scaleDenominator = parseInt(evt.replace(/\s+/g, '').split(':').pop(), 10);
const scaleDenominator = parseScale(evt);
this.dispatch('change:scale', { scale: scaleDenominator / 1000 });
selectScale.setButtonText(evt);
},
onRender() {
this.dispatch('render');
if (Array.isArray(scales) && scales.length) {
selectScale.setItems(scales);
} else {
selectScale.setItems(getScales());
}
selectScale.setItems(scales);
document.getElementById(selectScale.getId()).addEventListener('dropdown:select', (evt) => {
this.onChangeScale(evt.target.textContent);
});
if (initialScale) {
this.onChangeScale(initialScale);
} else {
const viewResolution = map.getView().getResolution();
const closest = resolutions.reduce((prev, curr) => (Math.abs(curr - viewResolution) < Math.abs(prev - viewResolution) ? curr : prev));
this.onChangeScale(mapUtils.resolutionToFormattedScale(closest, projection));
const projection = map.getView().getProjection();
const mapScale = mapUtils.resolutionToScale(viewResolution, projection);
const closest = scales.reduce((prev, curr) => (Math.abs(parseScale(curr) - mapScale) < Math.abs(parseScale(prev) - mapScale) ? curr : prev));
this.onChangeScale(closest);
}
},
render() {
Expand Down
1 change: 1 addition & 0 deletions src/layer/wms.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const wms = function wms(layerOptions, viewer) {
sourceOptions.tileGrid = viewer.getTileGrid();

if (wmsOptions.extent) {
// FIXME: there is no "extent" property to set. Code has no effect. Probably must create a new grid from viewer.getTileGridSettings .
sourceOptions.tileGrid.extent = wmsOptions.extent;
}
}
Expand Down
Loading

0 comments on commit 0614df0

Please sign in to comment.