最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Leaflet JS - Implementing Gesture Handling to enforce 2 fingered scrolling - Stack Overflow

programmeradmin2浏览0评论

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".

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.

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/{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=".1.1/jquery.min.js"></script>
<link rel="stylesheet" href="/[email protected]/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="/[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>

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".

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>

Share Improve this question edited Mar 4, 2018 at 12:20 elMarquis asked Mar 4, 2018 at 12:13 elMarquiselMarquis 7,7304 gold badges39 silver badges43 bronze badges 4
  • I guess you've read the Leaflet documentation on map handlers? – IvanSanchez Commented Mar 4, 2018 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 Commented Mar 5, 2018 at 4:02
  • Disable the default map panning handler, enable it on the first 2-finger interaction. – IvanSanchez Commented Mar 5, 2018 at 8: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 Commented Mar 5, 2018 at 22:48
Add a comment  | 

1 Answer 1

Reset to default 24

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

发布评论

评论列表(0)

  1. 暂无评论