Leaflet JS - Implementing Gesture Handling to enforce 2 fingered scrolling
Asked Answered
A

1

9

You know when you're on a mobile device and you scroll down a web page which has a google map. The map goes dark and tells you "Use two fingers to move the map". enter image description here

I want to implement exactly this in my Leaflet map. Leaflet doesn't currently offer this kind of functionality out the box.

Google refers to this functionality as Gesture Handling. If you set it to "Cooperative" you get the effect I just described. https://developers.google.com/maps/documentation/javascript/interaction

It's easy enough to detect the number of fingers being used and display the message as shown in my code example. (You'll need to run this on a mobile device or emulator to see it in effect)

If it's 1 finger I cancel the touchmove event and show my warning. Otherwise I allow the event to apply to the map. But I need to figure out some way of applying that one fingered touch event to the containing page after I've cancelled it on the map. So that the user scrolls the page instead.

Does anyone have any good ideas how to achieve this? I thought about using dispatchEvent to relay the received touchmove event object directly to the parent document. e.g: document.dispatchEvent(touchmoveevent); But no luck. Perhaps there's a better overall approach.

var myMap = L.map('mapid').setView([51.505, -0.09], 13);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  maxZoom: 19
}).addTo(myMap);

$("#mapid").on("touchmove", function(e) {
  if (e.touches.length !== 2) {
    $('.mask').fadeIn();
    return false;
  }
});

$("#mapid").on("touchend", function(e) {
  if ($('.mask').is(':visible')) {
    $('.mask').fadeOut();
  }
});
#mapid {
  height: 600px;
}

.mask {
  display: none;
  position: absolute;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.8);
  top: 0;
  left: 0;
  z-index: 400;
}

.message {
  color: #ffffff;
  position: absolute;
  width: 100%;
  text-align: center;
  top: 50%;
  transform: translateY(-50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw==" crossorigin=""></script>

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">

  <head>

    <body>
      <h1>Leaflet Map</h1>

      <div id="mapid"></div>
      <div class="scroll-shield"></div>
      <div class="mask">
        <div class="message">
          <p>Use two fingers to move the map</p>
        </div>
      </div>

      <h2>Stuff below</h2>
      <ul>
        <li>Here</li>
        <li>is</li>
        <li>some</li>
        <li>stuff</li>
        <li>below</li>
      </ul>

    </body>
Advertent answered 4/3, 2018 at 12:13 Comment(4)
I guess you've read the Leaflet documentation on map handlers?Calibre
@Calibre Thanks. I've just mocked up a test using the map handlers instead of jQuery. A nicer way of writing the code and in keeping with Leaflet best practise. But ultimately I end up with the same issue. I can cancel a one fingered touchmove and show the warning, but I can't get it to also scroll the page past the map.Advertent
Disable the default map panning handler, enable it on the first 2-finger interaction.Calibre
Thanks for that. Yip, I was able to get a working solution using that approach. I'll tidy things up then post as an answer.Advertent
A
23

The key to this was ensuring that dragging, tap and scrollWheelZoom are disabled when intitializing the map.

Then temporarily re-enabling them when 2 fingered dragging, or scrolling with command or ctrl key is detected.

I've now packaged this solution into a leaflet plugin.

https://github.com/elmarquis/Leaflet.GestureHandling

Advertent answered 19/3, 2018 at 15:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.