Search code examples
javascriptopenlayerskonvajs

Blending mode between konvajs and openlayers


I try to use blending mode between konvajs (https://konvajs.org/) and openlayers (https://openlayers.org/)

I have a map created with openlayers, then I use Overlay (https://openlayers.org/en/latest/examples/overlay.html) of openlayers to add canvas konvajs on over the map.

I've try:

  1. property globalCompositeOperation of konvajs, but it works only with items in konvajs
  2. css mix-blend-mode, but it all items in konvajs were stuck with the same mode, I want each items have different mode.

Is there any way to achieve this?

Here example code I tried with No.1 above: https://codesandbox.io/s/cool-monad-ow21j?file=/main.js


Solution

  • To help investigate how OpenLayer and Konvajs canvas might interact I created the below snippet. This draws an Openlayer map element then adds a Konvajs canvas element. Both are positioned absolute so that they overlap. I threw in some simple rectangles with varying opacity to illustrate the possibility in case that was all you really require.

    The image below shows the F12 inspector view of the elements. As we can see, label a points out that the OpenLayers element employs a dedicated canvas. Similarly, label b shows the Konvajs canvas.

    The conclusion is that these elements are indeed separate HTML5 canvas elements. Therefore the question switches to 'is it possible to use blend mode across canvasses?'. Fortunately this has been asked before.

    So, in answer to your question, 'Is there any way to achieve this [blend between OpenLayer and Konvajs] ?' the answer seems to be a definite maybe. However, looking at the potential approaches it would seem that you might lose some of the mouse/touch functionality of both of the canvas layers.

    F12 view of the elements

    // Create the map element
    var map = new ol.Map({
      target: 'map',
      layers: [
        new ol.layer.Tile({
          source: new ol.source.OSM()
        })
      ],
      view: new ol.View({
        center: ol.proj.fromLonLat([-1.1656, 51.0856]),
        zoom: 15
      })
    });
    
    
    // Create the Konva element
    var stage = new Konva.Stage({container: 'container1', width: 600, height: 400});
    var layer1 = new Konva.Layer();
    stage.add(layer1);
    
    var rect = new Konva.Rect({x: 100, y: 25, width: 100, height: 50, fill: 'magenta', stroke: 'black', draggable: true });
    layer1.add(rect); 
    
    rect = new Konva.Rect({x: 200, y: 75, width: 100, height: 50, fill: 'magenta', stroke: 'black', draggable: true, opacity: 0.5 });
    layer1.add(rect); 
    
    rect = new Konva.Rect({x: 300, y: 125, width: 100, height: 50, fill: 'magenta', stroke: 'black', draggable: true, opacity: 0.25 });
    layer1.add(rect); 
    
    stage.draw();
          .map {
            height: 400px;
            width: 100%;
          }
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
    <script src="https://cdn.rawgit.com/konvajs/konva/1.6.5/konva.min.js"></script>
        <div id="map" class="map"  style="left: 0; top: 0; width: 600px; height: 400px; background-color: transparent; position: absolute;"></div>
        
        <div id='container1' style="left: 0; top: 0; width: 600px; height: 400px; background-color: transparent; position: absolute;"></div>