5

I made a map using an orthographic projection and I try to improve performance because the rotation is not smooth (around 6-7FPS).

It's a map of the world built with a topojson file (world-100m). I need to interact with country and colorized them so there is as many svg:path as there are countries.

After the loading I have an automatic rotation function launched using d3.timer :

autoRotate = () =>
  @start_time = Date.now()     # Store the current time (used by automatic rotation)

  d3.timer () =>
    dt = Date.now() - @start_time

    if @stopRotation or dt > @config.autoRotationDuration
      true
    else
      @currentRotation[0] = @currentRotation[0] - @config.autoRotationSpeed
      @projection.rotate @currentRotation
      redrawPathsOnRotationOrScale(@currentRotation, @projection.scale())
      false

redrawPathsOnRotationOrScale = (rotation, scale, duration = 1) =>
  @currentRotation = rotation

  @projection
    .rotate(@currentRotation)
    .scale(scale)

  @groupPaths.selectAll("path")
    .attr("d", path)

To understand why it was so slow, I made a profile record in Chrome and here is the result :

Chrome profiling 1/2 Chrome profiling 2/2

It seems the Animation Frame Fired is the slow part but I don't really know what it is. And when I open it, there is 2 GC Event (garbage collector ?) but nothing around... Do you have an idea what is happening during this 90ms ?

Any tips to improve the performance is more than welcome :-)

Thanks by advance !

By the way, it looks like this : Map overview

John Smith
  • 489
  • 1
  • 6
  • 12

2 Answers2

3

Try reducing the complexity of the SVG paths by adjusting the --simplify-proportion, -s or --quantization topojson flags. Browsers still have fairly poor SVG rendering performance, and with maps it really helps to reduce the number and precision of the points.

Yuri Feldman
  • 126
  • 1
  • 6
  • Adding a --simplify-proportion 0.6 while generating the topojson file improved performance from 11 to 20 FPS without loosing to much details. – John Smith Jul 10 '13 at 12:28
2

D3.js uses Request Animation Frames to perform timers.

From D3 documentation:

If your browser supports it, the timer queue will use requestAnimationFrame for fluid and efficient animation.

As I know it's the best approach to perform animations in modern browsers and I don't think you can directly optimize this part. Otherwise it seems that you call stack use selection_each that could probably be cached into a variable.

Pirhoo
  • 680
  • 8
  • 21
  • Yes, I knew for the *Request Animation Frames*, but I would expect that he would be the fastest as possible. My understanding of *Request Animation Frames* is that it avoid looping more often that the browser can redraw to avoid useless computation, but this shouldn't make the animation slower. For the `selection_each`, you are absolutely right, I'm gonna cache this result. Thanks ! – John Smith Jul 10 '13 at 08:26