1

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

whatdym
  • 17
  • 5
  • 1
    Sounds like a really interesting project. Can you post a [minimal reproduceable example](https://stackoverflow.com/help/minimal-reproducible-example) to illustrate the bug you are experiencing please ? – Vanquished Wombat Sep 01 '20 at 15:07
  • @VanquishedWombat Thanks for your remind, I added example code link. – whatdym Sep 01 '20 at 16:53
  • 1
    I am guessing that the openlayers map is not perceived by Konva as a konva shape. Therefore Konva is not able to manipulate it in the form of blending. Could you perhaps get the openlayers map as an image that can be passed to konva ? There is also a question & answer here about blending images in Konva: https://stackoverflow.com/questions/46557532/using-image-mask-with-globalcompositeoperation-on-konvajs – Vanquished Wombat Sep 01 '20 at 17:03
  • Thank for your interest, I'll give it a try – whatdym Sep 02 '20 at 04:26

1 Answers1

2

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>
    
Vanquished Wombat
  • 9,075
  • 5
  • 28
  • 67
  • 1
    thanks for your help, but does your solution work with blend mode like "screen, lighter, difference,..."? I tried to add globalCompositeOperation in your snippet but it seems like only opacity work? – whatdym Sep 02 '20 at 11:59
  • 1
    Sorry I wasn't giving you a solution - more like explaining the complications. So I don't expect that snippet to work as-is. Follow the link I posted to that previous question which has some possible routes forward. – Vanquished Wombat Sep 02 '20 at 12:51
  • 1
    thanks for your explaining, it's very clear to me, I'll try those methods in the link you gave, but I'll try to not lose some of the mouse/touch functionality cause I need them in my project – whatdym Sep 02 '20 at 13:21
  • 1
    ok cool. If my answer explained / answered your issue, even though it was of course a negative outcome, please mark it as correct. Thanks. – Vanquished Wombat Sep 02 '20 at 15:47
  • 1
    I tried the link you gave and got the answer. The main idea is split items in canvas' konva into multi one then blend it with **'Normal' Blend Mode** (mix-blend-mode) in the link. Of cause it still has some problems, first it reduces performance and second mouse/touch event can't pass from upper canvas's konva to lower one. Anyway, thank you. – whatdym Sep 03 '20 at 14:42