Skip to content

Commit

Permalink
Use a custom layer for the print mask
Browse files Browse the repository at this point in the history
  • Loading branch information
fredj committed Aug 27, 2019
1 parent a085ec5 commit 3ae929a
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 12 deletions.
95 changes: 95 additions & 0 deletions contribs/gmf/src/print/Mask.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import Layer from 'ol/layer/Layer.js'
import {createCanvasContext2D} from 'ol/dom.js';
import {INCHES_PER_METER, DOTS_PER_INCH} from 'ngeo/print/Utils.js';


/**
* @extends {Layer<any>}
*/
export default class Mask extends Layer {

constructor(options = {}) {

super(options);

/**
* @private
*/
this.context_ = createCanvasContext2D();

this.context_.canvas.style.opacity = '0.5';

/**
* @type {function(import("ol/PluggableMap.js").FrameState):number}
*/
this.getScale;

/**
* @type {function():import("ol/size.js").Size}
*/
this.getSize;

/**
* @type {undefined|function():number}
*/
this.getRotation;
}

/**
* @param {import("ol/PluggableMap").FrameState} frameState
*/
render(frameState) {
this.context_.canvas.width = frameState.size[0] * frameState.pixelRatio;
this.context_.canvas.height = frameState.size[1] * frameState.pixelRatio;
const center = [this.context_.canvas.width / 2, this.context_.canvas.height / 2];

// background (clockwise)
this.context_.beginPath();
this.context_.moveTo(0, 0);
this.context_.lineTo(this.context_.canvas.width, 0);
this.context_.lineTo(this.context_.canvas.width, this.context_.canvas.height);
this.context_.lineTo(0, this.context_.canvas.height);
this.context_.lineTo(0, 0);
this.context_.closePath();

const size = this.getSize();
const height = size[1] * frameState.pixelRatio;
const width = size[0] * frameState.pixelRatio;
const scale = this.getScale(frameState);
const resolution = frameState.viewState.resolution;

const extentHalfWidth = (((width / DOTS_PER_INCH) / INCHES_PER_METER) * scale / resolution) / 2;
const extentHalfHeight = (((height / DOTS_PER_INCH) / INCHES_PER_METER) * scale / resolution) / 2;

const rotation = this.getRotation !== undefined ? this.getRotation() : 0;

// diagonal = distance p1 to center.
const diagonal = Math.sqrt(Math.pow(extentHalfWidth, 2) + Math.pow(extentHalfHeight, 2));
// gamma = angle between horizontal and diagonal (with rotation).
const gamma = Math.atan(extentHalfHeight / extentHalfWidth) - rotation;
// omega = angle between diagonal and vertical (with rotation).
const omega = Math.atan(extentHalfWidth / extentHalfHeight) - rotation;
// Calculation of each corner.
const x1 = center[0] - Math.cos(gamma) * diagonal;
const y1 = center[1] + Math.sin(gamma) * diagonal;
const x2 = center[0] + Math.sin(omega) * diagonal;
const y2 = center[1] + Math.cos(omega) * diagonal;
const x3 = center[0] + Math.cos(gamma) * diagonal;
const y3 = center[1] - Math.sin(gamma) * diagonal;
const x4 = center[0] - Math.sin(omega) * diagonal;
const y4 = center[1] - Math.cos(omega) * diagonal;

// hole (counter-clockwise)
this.context_.moveTo(x1, y1);
this.context_.lineTo(x2, y2);
this.context_.lineTo(x3, y3);
this.context_.lineTo(x4, y4);
this.context_.lineTo(x1, y1);
this.context_.closePath();

this.context_.fillStyle = '#000';
this.context_.fill();

return this.context_.canvas;
}
}
23 changes: 11 additions & 12 deletions contribs/gmf/src/print/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {DATALAYERGROUP_NAME} from 'gmf/index.js';

import gmfAuthenticationService from 'gmf/authentication/Service.js';

import MaskLayer from 'gmf/print/Mask.js';
import gmfThemeThemes, {findGroupByLayerNodeName, findObjectByName} from 'gmf/theme/Themes.js';
import ngeoMapLayerHelper from 'ngeo/map/LayerHelper.js';
import ngeoMapFeatureOverlayMgr from 'ngeo/map/FeatureOverlayMgr.js';
Expand Down Expand Up @@ -284,6 +285,11 @@ export class PrintController {
*/
this.map = null;

/**
* @private
*/
this.maskLayer_ = new MaskLayer();

/**
* @type {boolean}
*/
Expand Down Expand Up @@ -433,12 +439,6 @@ export class PrintController {
*/
this.rotationTimeoutPromise_ = null;

/**
* @type {?import("ol/events.js").EventsKey}
* @private
*/
this.postComposeListenerKey_ = null;

/**
* @type {?import("ol/events.js").EventsKey}
* @private
Expand Down Expand Up @@ -628,8 +628,9 @@ export class PrintController {
getRotationFn = () => this.rotation;
}

this.postcomposeListener_ = this.ngeoPrintUtils_.createPrintMaskPostcompose(
getSizeFn, this.getScaleFn.bind(this), getRotationFn);
this.maskLayer_.getSize = getSizeFn;
this.maskLayer_.getScale = this.getScaleFn.bind(this);
this.maskLayer_.getRotation = getRotationFn;
}


Expand Down Expand Up @@ -680,7 +681,7 @@ export class PrintController {
this.gmfPrintState_.state = PrintStateEnum.NOT_IN_USE;
// Get capabilities - On success
this.parseCapabilities_(resp);
this.postComposeListenerKey_ = olEvents.listen(this.map, 'postcompose', this.postcomposeListener_);
this.map.addLayer(this.maskLayer_);
this.pointerDragListenerKey_ = olEvents.listen(this.map, 'pointerdrag', this.onPointerDrag_, this);
this.mapViewResolutionChangeKey_ = olEvents.listen(this.map.getView(), 'change:resolution', () => {
this.scaleManuallySelected_ = false;
Expand All @@ -695,9 +696,7 @@ export class PrintController {
if (!this.map) {
throw new Error('Missing map');
}
if (this.postComposeListenerKey_) {
olEvents.unlistenByKey(this.postComposeListenerKey_);
}
this.map.removeLayer(this.maskLayer_);
if (this.pointerDragListenerKey_) {
olEvents.unlistenByKey(this.pointerDragListenerKey_);
}
Expand Down

0 comments on commit 3ae929a

Please sign in to comment.