• Stars
    star
    152
  • Rank 237,839 (Top 5 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 6 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Smoothly zoom in and out with the multi-touch pinch gesture

Smooth Multi-Touch Zoom Extension for Firefox

Add to Firefox

Update 2020: This feature is arriving natively in firefox! It's expected to be enabled by default in Firefox 83, so this extension will no longer required :)

This extension adds support for smooth zooming with the pinch gesture on a trackpad or touch screen. It's been designed to match the behavior of Chrome and Safari.

Non-multi-touch users can still smooth zoom by scrolling and holding down the Shift key

Zoom can be reset by pressing ⌘ + 0 on macOS or Ctrl + 0 on Windows

Requires Firefox 55 or greater

Motivation

Firefox is still missing smooth multi-touch zoom support, an issue has been sitting in Bugzilla for the last 6 7 8 9 years gathering comments

Given we live in a time with MacBook trackpads as big as a tablet, I've become so used to the pinch-to-zoom feature while browsing in Safari and Chrome that its absence was a deal breaker for me when trying to switch to the new Firefox Quantum. I put this together to try and bring the feature to Firefox

It turned out to be tricker to implement than I thought! There are a number of little hacks required to get it to work and to achieve a smooth user experience. I've explained the implementation below and hopefully this could help someone else trying to achieve high-performance scalling with CSS

Implementation Details and Hacks

No 'real' multi-touch trackpad gesture events in Firefox for Desktop

In-spite of having PointerEvents, TouchEvents and even a 'MozMagnifyGesture' event, none of these will fire when the user performs multi-touch gestures on a desktop trackpad. However, there's a trick to capturing a pinch action: Since Firefox 55.0 the pinch gesture maps to the 'wheel' event with the ctrlKey flag artificially set to true. It's an ugly hack, but it lets us distinguish between mouse-wheel + ctrl and pinch by keeping track of the real ctrlKey state and comparing (this is only true on macOS).

We'd really want to capture pinch-start and pinch-end events to enable the best user experience but unfortunately I'm not aware of any technique to enable this.

Just setting scaleX() and scaleY() isn't enough for acceptable performance

The page can be magnified by setting a CSS scale transform on the root element, this works for magnification but experience is anything but smooth - even with the new WebRender enabled the experience is essentially the same: janky. To work around the performance problems I found a few tricks:

  • We can abuse transform: perspective() for faster zooming. Surprisingly scaling via scale functions and scaling via perspective produces different results. Scaling via scale functions triggers the browser to re-rasterize after scaling. The result is your fonts and SVGs stay sharp when scaled up but it comes with a significant frame-time cost. Scaling via perspective on the other hand, just scales up the already rasterized content - your fonts and sharp lines become fussy as you zoom in but it's much cheaper to perform. To produce the same scale using a perspective transform, we can set the z-coordinate to p - p/scale where p is the CSS perspective value (or distance to the z = 0 plane).

    To achieve the best of both world we can use the perspective trick during the pinch gesture and swap to regular scale functions once the gesture has finished.

  • Setting overflow: hidden on the root element helps to reduce re-painting: scaling causes the content to overflow and the scroll region to change. Rapidly changing the scroll region seems to trigger a whole bunch of expensive work. Setting overflow to hidden seems to prevent this and fortunately we can still use scrollLeft and scrollTop to apply an offset to the page, but the scroll bar is hidden and panning is disabled. In this extension overflow is set to scroll as soon as the pinch gesture completes but there's a noticeable delay between zooming and being able to pan whilst the browser does a whole bunch of repainting work. I'm not convinced this work is necessary but I've not yet been able to hint to the browser that it doesn't need to be done.

  • Enabling CSS transitions on the transform property and setting the duration to 0 seconds seems to help. This one is a bit of voodoo, I'm not convinced it should work but it does seem to. It could potentially be acting as a hint to enable certain rendering optimizations but I'm not sure. Would love to learn more if anyone has ideas.

Quirks mode breaks scroll positions

When a site doesn't specify a modern docType, Firefox falls back into 'quirks mode' rendering. In this mode Firefox enables a long list of historic bugs. Foruntately we can detect quirks mode rendering and work around this.

Known Issues

  • Elements with position: sticky are not correctly scaled up with the rest of the page

Please report any webpages that have issues and I'll see if it's possible to fix them!

Other Notes

Meta tags

Pages may have meta tags to configure the behavior of 'magnifying-glass' zoom on tablets. These tags let a page disable zoom and set the mininum and maximum zoom. So far, all desktop browser seem to ignore these, citing that a page shouldn't have a say on whether or not the user is allowed to zoom. I've decided to match the behavior of other browser and ignore them too but I'd love to hear from users if this should change

More Repositories

1

GPU-Fluid-Experiments

Haxe
2,882
star
2

dts2hx

Converts TypeScript definition files (d.ts) to haxe externs (.hx) via the TypeScript compiler API
Haxe
127
star
3

haxe-c-bridge

Easily interact with haxe classes from C with an automatically generated C header
Haxe
48
star
4

console.hx

A haxe logging utility for easy rich output in both native and browser consoles
Haxe
45
star
5

vector-math

Shader-math in haxe: library for GLSL vector operations, complete with swizzles and all
Haxe
36
star
6

dotfiles

dotfiles: .zshrc, .bash_profile & .inputrc with terminal and iterm2 color profiles
Shell
31
star
7

haxe-glsl-parser

GLSL ES 1.0 parser in Haxe
Haxe
26
star
8

haxe-threejs-template

three.js + haxe starter project
Haxe
26
star
9

gluon

WebGL implementation for hxcpp
C
24
star
10

gltoolbox

A collection of utilities to slim down the process of writing lime-based Haxe OpenGL programs.
Haxe
19
star
11

html-text-to-canvas

Draw text formatted with HTML to a canvas element, leveraging the browser's layout engine. Useful for generating text for WebGL
JavaScript
16
star
12

three-toolkit

My personal lib for three.js haxe projects
Haxe
12
star
13

webgl-workshop

JavaScript
7
star
14

demos

using gh-pages to host rough demos
JavaScript
6
star
15

haxe-shader-demo

Haxe
6
star
16

GPU-Particles-Experiment

Haxe
5
star
17

three-js-haxe-externs

Three.js haxe externs, automatically generated from the typescript definitions
Haxe
4
star
18

three.js-refraction

Exploring refraction in three.js
Haxe
3
star
19

twitter-to-mastodon

So long and thanks for all the fish
3
star
20

sublime-text-3-externs

Complete haxe externs for sublime text 3's python API (auto-generated from API docs)
HTML
3
star
21

ThreeHX-Basic-Scene

Porting three.js to Haxe by converting only the classes and functions involved in a very simple scene and building out from there
Haxe
3
star
22

reading-list

2
star
23

cloud-rendering

Cloud rendering with three.js for met office informatics lab
JavaScript
2
star
24

Planetary-Stability-N-Body-Algorithms

Techniques for optimising n-body simulations of planetary systems are explored as part of a physics project
Haxe
2
star
25

demo.js

This is a little utility class to quickly whip up canvas based demos
JavaScript
1
star
26

ArrowTabs

Flexible Resposive Tabs - jQuery plugin
CSS
1
star
27

RPi-SLA-3D-Printer

Experimental Raspberry Pi stereolithography based 3D printer
JavaScript
1
star
28

simple-haxe-demo

Haxe
1
star
29

Browser-Monitor

Tool for keeping track of browser data - with the primary aim of improving client side performance
CSS
1
star