8

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/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.3.1/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>
elMarquis
  • 7,450
  • 4
  • 38
  • 42
  • I guess you've read the Leaflet documentation on map handlers? – IvanSanchez Mar 04 '18 at 15:29
  • @IvanSanchez 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. – elMarquis Mar 05 '18 at 04:02
  • Disable the default map panning handler, enable it on the first 2-finger interaction. – IvanSanchez Mar 05 '18 at 08:22
  • 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. – elMarquis Mar 05 '18 at 22:48

1 Answers1

21

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

elMarquis
  • 7,450
  • 4
  • 38
  • 42