OpenLayers 3 postcompose 到 Vue SPA 中的 OpenLayers 6 事件

OpenLayers 3 postcompose to OpenLayers 6 event in Vue SPA

我做了这个 codepen,我在 postcompose 上操作 OpenLayers 地图底图的上下文。我遇到的问题是将此工作演示转换为使用 OpenLayers 6 的 Vue SPA,我想 link 将暗模式映射效果切换为切换。 postcompose 事件在 OL6 中的触发方式与在 OL3 中的触发方式不同,因此我尝试连接到 prerender.

import TileLayer from 'ol/layer/Tile';
...
osm: new TileLayer({source: new OSM()})

在 OpenLayers 3 中,以下代码为我提供了永久暗模式地图:

OSM_LAYER.on('postcompose', function (evt) {
    evt.context.globalCompositeOperation = 'color';
    evt.context.fillStyle = 'rgba(0,0,0,' + 1.0 + ')';
    evt.context.fillRect(0, 0, evt.context.canvas.width, evt.context.canvas.height);
    evt.context.globalCompositeOperation = 'overlay';
    evt.context.fillStyle = 'rgb(' + [200,200,200].toString() + ')';
    evt.context.fillRect(0, 0, evt.context.canvas.width, evt.context.canvas.height);
    evt.context.globalCompositeOperation = 'source-over';
    document.querySelector('canvas').style.filter="invert(99%)";
});

目前我正在尝试按照 使用 getVectorContext 但我不理解某些东西,因为我的代码没有给我正确的暗模式:

OSM_LAYER.on('prerender', function (evt) {
    var ctx = getVectorContext(evt).context_
    ctx.globalCompositeOperation = ‘color’;
    ctx.fillStyle = ‘rgba(0,0,0,’ + 1.0 + ‘)’;
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    ctx.globalCompositeOperation = ‘overlay’;
    ctx.fillStyle = ‘rgb(‘ + [200,200,200].toString() + ‘)’;
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    ctx.globalCompositeOperation = ‘source-over’;
    document.querySelector('canvas').style.filter="invert(99%)";
});

编辑:感谢 Mike 先生的回答,我能够复制 OL3 黑暗模式的外观。现在的问题是我实际上使用这个底图来创建一个动画,我在 for 循环中更新所有图层的时间参数,然后使用 :

提取地图 canvas
getMapCanvas () {
    var mapCanvas = document.createElement('canvas');
    var divElement = document.querySelector(".map");
    mapCanvas.width = divElement.offsetWidth;//size[0];
    mapCanvas.height = divElement.offsetHeight;//size[1];
    var mapContext = mapCanvas.getContext('2d');
    Array.prototype.forEach.call(
        document.querySelectorAll('.ol-layer canvas'),
        function (canvas) {
            if (canvas.width > 0) {
                const opacity = canvas.parentNode.style.opacity;
                mapContext.globalAlpha = opacity === '' ? 1 : Number(opacity);
                const transform = canvas.style.transform;
                const matrix = transform
                                        .match(/^matrix\(([^\(]*)\)$/)[1] //eslint-disable-line
                                        .split(',')
                                        .map(Number);
                CanvasRenderingContext2D.prototype.setTransform.apply(mapContext,matrix);
                mapContext.drawImage(canvas, 0, 0);
            }
        }
    );
    return mapCanvas;
},

仅在 rendercomplete 承诺得到解决后调用。使用迈克先生的方法,我得到了一种奇怪的白色色调,而不是暗模式 OSM,我认为这是因为我在 getMapCanvas 函数中导出 canvas 的方式。有人可以帮我调试一下吗?

样式过滤器仅影响 canvas 在屏幕上的显示方式。要反转绘制的内容,需要 difference 带有白色填充的 globalCompositeOperation。

this.map.getLayers().getArray()[0].on(['postrender'], (evt) => {
    if ( this.darkOSM !== null && this.darkOSM === false ) {
        evt.context.globalCompositeOperation = 'color';
        evt.context.fillStyle = 'rgba(0,0,0,' + 1.0 + ')';
        evt.context.fillRect(0, 0, evt.context.canvas.width, evt.context.canvas.height);
        evt.context.globalCompositeOperation = 'overlay';
        evt.context.fillStyle = 'rgb(' + [200,200,200].toString() + ')';
        evt.context.fillRect(0, 0, evt.context.canvas.width, evt.context.canvas.height);
        evt.context.globalCompositeOperation = 'difference';
        evt.context.fillStyle = 'rgba(255,255,255,' + 0.9 + ')';
        evt.context.fillRect(0, 0, evt.context.canvas.width, evt.context.canvas.height);
        evt.context.globalCompositeOperation = 'source-over';
    } 
});

要使用 onun,您需要:

this.myFunction = (evt) => {
    if ( this.darkOSM !== null && this.darkOSM === false ) {
        evt.context.globalCompositeOperation = 'color';
        evt.context.fillStyle = 'rgba(0,0,0,' + 1.0 + ')';
        evt.context.fillRect(0, 0, evt.context.canvas.width, evt.context.canvas.height);
        evt.context.globalCompositeOperation = 'overlay';
        evt.context.fillStyle = 'rgb(' + [200,200,200].toString() + ')';
        evt.context.fillRect(0, 0, evt.context.canvas.width, evt.context.canvas.height);
        evt.context.globalCompositeOperation = 'difference';
        evt.context.fillStyle = 'rgba(255,255,255,' + 0.9 + ')';
        evt.context.fillRect(0, 0, evt.context.canvas.width, evt.context.canvas.height);
        evt.context.globalCompositeOperation = 'source-over';
    } 
};
this.map.getLayers().getArray()[0].on(['postrender'], this.myFunction);
this.map.getLayers().getArray()[0].un(['postrender'], this.myFunction);

如果您从 on 中保存密钥,则它必须与 unByKey https://openlayers.org/en/latest/apidoc/module-ol_Observable.html#.unByKey

一起使用