Here’s a video showing the final proof of concept of using fisheye distortion to navigate around a google sheet


The principle of this kind of projection is to enlarge items closer to the mouse  position and shrink those further away. This gives this kind of effect, and entails repositioning each cell of a standardized grid as well as resizing them. The fisheye algorithm has 2 parameters.

  • distortion – how aggressively to resize
  • radius – the extent of the distortion – in the image below you can see a kind of sphere where the fisheye effects are applied


I came across this very concise algorithm on github, and converted it make it work in the Apps Script IDE, and applied it in the context of cells of a spreadsheet.

Tricky stuff

Ideally I would have treated each cell as a clickable object in its own right, but the problem is that when a cell is in focus, it needs to be in front, and furthermore, all of those that are more enlarged need to be in front of those that are not. Since D3 uses SVG to render, and since SVG has no z-index, the only way to do that was to reattach rendered elements to the SVG container after sorting them. It turns out that mouse events get detached from elements when they are re-arranged in this way, with the result that events get triggered for where the cell used to be in the DOM, not where it now is. To get round this, the clickable frame is the entire SVG parent element, and the cell in focus is derived from the mouse position. The click event does not fire reliably even in this scenario, so I used the mousedown event in its place, which seems to work just fine. I also have scrolling tabs positioned within the svg frame that suffer from the same problem.
There’s a standalone version demo at


Because of that, the initializing phase is a little more complex than I would have liked.


The size of the viz is controlled by the size of container element, and these parameters control how it works and looks

Data changes

Changes in data provokes a reassessment and flattening of the viz data and color scale


A change in mouse position or some other interaction provokes a re-rendering of the entire viz, since the fisheye distortion will have repositioned every cell.


The viz is a window onto, probably, a larger grid that is the original sheet, as below
Each data item has an original row and column offset, and the viz maintains a row and column offset which is updated each time a scroll operation happens as below, which makes selecting the data to include in the viz pretty straightforward

The code

The entire code for this namespace is on github.
For more like this, see Google Apps Scripts Snippets
Why not join our forum, follow the blog or follow me on Twitter to ensure you get updates when they are available.