4

I need to implement pinch to zoom and drag to pan over an SVG. This SVG gets shown at 480*480 pixels, but its real size is 1920*1920 pixels.

I went with HammerJS, and listened for pinch and drag:

$(document).hammer().on('pinch', $.throttle(30, setZoom)).
on('drag', $.throttle(30, moveTo));

Inside those methods (setZoom, moveTo) I'm already preventing the default action for the event, as suggested by Hammer creator

ev.gesture.preventDefault()

As you can see, I'm throttling the handlers using jQuery.throttle.

My zoom and pan implementation works by changing the viewbox attribute of the SVG. So that to show the whole image I set said attribute to viewbox="0 0 1920 1920", and to show a particular I set it to viewbox="100 100 1720 1720". (To manipulate the SVG I'm using svg.js)

Finally, the SVG has this structure:

  • One image (1920*1920 pixels),
  • 20 lines, inside a group, that represent a grid,
  • More or less 50 groups, each containing an ellipse and a text > tspan elements.

This is part of the code of the SVG:

<image id="SvgjsImage1027" xlink:href="/exams/still_picture/exam-4" width="1920" height="1920" x="0" y="0"></image>
<g id="SvgjsG1002" class="grid">
    <line id="SvgjsLine1003" x1="0" y1="0" x2="1920" y2="0"></line>
    …
</g>
<g id="SvgjsG1026" class="points">
    <g id="s10621674-24" class="threshold">
        <ellipse id="SvgjsEllipse1029" rx="7" ry="7" cx="1062" cy="1674" fill="#2b96d9"></ellipse>
        <text id="SvgjsText1030" style="font-size:40;font-family:Helvetica, Arial, sans-serif;text-anchor:middle;textLength:1;" font-size="40" text-anchor="middle" x="1067.6568542494924" y="1690.5354797464468">
            <tspan id="SvgjsTspan1031" dy="36.93333336" x="1067.6568542494924" style="font-size:40;font-family:Helvetica, Arial, sans-serif;text-anchor:middle;textLength:1;">24</tspan>
        </text>
    </g>
    …
</g>

Question

Performance on Android is pretty bad. We've tried on Chrome 26 (Chrome 26.0.1410.58) and Chrome Beta 27 (Chrome 27.0.1453.74) on a Samsung Galaxy Tab 2, but it feels sluggish. We've tried to open the same page on an iPad 2 (Safari on iOS 6), and it works just right, with performance that's comparable to a native app.

What can we try in order to improve performance on Android? We cannot switch to another browser (say, Firefox Mobile), so the solution must be in the HTML/Javascript land.


We've also tried to use some libraries to handle pinch to zoom and drag to pan (for example jQuery.panzoom) but we haven't had better results.

Alessandro Vendruscolo
  • 14,493
  • 4
  • 32
  • 41
  • have you tried with a smaller svg or just moving a div around? I did something similar and it was the dom/css updates that were the bottleneck. for example if I update a dom position (expensive) it was unusable, but using one of the hardware accelerated css transforms made performance acceptable even on my crappy generic knock off tablet. – Tom Elmore May 09 '13 at 12:39
  • What Tom said. Android ICS performance with SVG is appalling. If you need to target Android then try to switch to HTML and move with translate3d. – methodofaction May 09 '13 at 13:48

1 Answers1

2

We gave up on trying to get this to work well as web app.

We tried to use HTML instead of SVG, but we didn't see a great performance improvement — this leads me to think that multitouch event handling in Javascript is just slow (on Android).

Since we planned to distribute a native Android app wrapping our web app, we decided to handle zoom and pan using the native app.

Basically, when the zoom and pan feature is required, the web app sends through a web socket some messages, which are intercepted by the native app. At this point it displays another web view on top of the other, which is loaded with just the SVG (our web app creates and manipulates the SVG, serializes it and sends it to the native app over the web socket). Because of this, zoom and pan performance are really good, because are handled by the web view. The end user doesn't notice what's happening behind the scenes.

Alessandro Vendruscolo
  • 14,493
  • 4
  • 32
  • 41