简体   繁体   中英

D3 pan/zoom behaviors don't work on mobile Safari

On an iPhone, D3's pan/zoom behaviors don't work very well. To see the problem, visit this page on an iPhone: http://bl.ocks.org/mbostock/3892919

When you pan, the whole browser window tends to get dragged around. When you zoom, the iPhone itself will often zoom on the page, instead of the D3 element catching the pinch event.

I'm using D3 v3.5.17. This happens on mobile Safari as well as Chrome on the iPhone (but we all know that's still just Safari).

On further investigation, it appears that certain SVG elements such as <rect> and <circle> will properly catch the touch events, direct them through D3, and prevent the mobile browser from responding to them. Other SVG elements, such as <svg> and <g> , will ignore the touch events and they will bubble up to the browser.

I've tried attaching a touchmove handler to the SVG element and using event.preventDefault() to try to keep the browser from taking over the event. That doesn't work.

I've tried calling the function returned by d3.behavior.zoom()... from different elements than the container SVG. That also doesn't work.

How can I make the whole SVG respond properly to touch events (drag and pinch) on iOS browsers?

The solution turned out to be hacky, but simple: alongside the <g> element that gets appended to the parent <svg> and is transformed by the D3 zoom event, I append a <rect> element and make sure that it receives the same scale(...) transform value as the <g> element. The upshot of this is that there is a big invisible rectangle behind my SVG that catches mobile Safari touch events without any trouble.

The end result is something like this:

<svg>
  <rect fill="transparent" x="0" y="0" width="3000" height="1000" transform="scale(0.8)"></rect>
  <g transform="translate(900,38) scale(0.8)">
    <!-- My SVG drawing/chart/whatever -->
  </g>
</svg>

EDIT: An even better solution is to attach the click handler to a traditional HTML element like a <div> . I attached it to the <div> that contains the entire SVG and it works perfectly--no hacky invisible <rect> s required.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM