Skip to content
This repository has been archived by the owner on Dec 15, 2018. It is now read-only.

animate features in maps.data #2

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open

Conversation

jlivni
Copy link

@jlivni jlivni commented May 2, 2014

No description provided.

this.map = map;

/**
* Number of steps for the animation (higher # is smoother).
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could I just set this to Number.MAX_VALUE? What's the trade-off? I assume performance but make a note here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to try render more than requestAnimationFrame, and sometimes users want relatively course/discrete steps thru the animation. Made a todo.

* Seconds the animation should last.
* @type {number}
*/
this.duration = 30; // seconds the aninmation should last.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JS devs really prefer their animation lengths in ms due to history of setTimeout, Date.now(), etc

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@brendankenny
Copy link
Contributor

The execution flow of animate is a little confusing right now, especially with currentTime being updated from the features themselves You'll also run into problems here with setTimeout clamping to 4ms. It seems like you also want it to always run as smoothly as possible, letting the browser's performance be the limiting factor.

Really you just want to line up the range of times in the data itself and the range of time from the start of the animation to (start + duration). I think it would be clearer to rearrange the current code to first calculate how far you are into the animation range at the beginning, then map it to a time in the data range, and then loop over the features to see if they're before or after that time. This has the added benefit that setTimeout then becomes really easy to map to requestAnimationFrame, as you just run it util your animation progress is past 100%

So something like (in pseudo-pseudo-code):

Animator.prototype.animate = function() {
  var animationProgress = (new Date().getTime() - this.animationStart) / this.duration;
  var currentTime = this.startTime + animationProgress * (this.endTime - this.startTime);
  // display currentTime in control

  for (var i = this.index; i < this.features_.length; i++) {
    // if feature.time < currentTime, add to map.Data
    // else break
  }
  this.index = i;

  if (animationProgress < 1) {
    var that = this; // ugh
    window.requestAnimationFrame(function() {
      that.animate();
    });
  } else {
    if (this.repeat) {
      this.start();
    }
  }
}

and then use one the requestAnimationFrame polyfills listed here for IE8/9: http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

just a suggestion, but this approach seems clearer (to me, at least).

@jlivni
Copy link
Author

jlivni commented May 7, 2014

That makes sense, but there's also the use case for a non-smooth animation
(like I want to have N steps, with a large chunk of data changing in each)
which is why I originally figured developers may want to provide the # of
steps; it seems like maybe this would be trickier with your proposed
workflow?

On Wed, May 7, 2014 at 4:39 PM, Brendan Kenny notifications@github.comwrote:

The execution flow of animate is a little confusing right now, especially
with currentTime being updated from the features themselves You'll also run
into problems here with setTimeout clamping to 4ms. It seems like you also
want it to always run as smoothly as possible, letting the browser's
performance be the limiting factor.

Really you just want to line up the range of times in the data itself and
the range of time from the start of the animation to (start + duration). I
think it would be clearer to rearrange the current code to first calculate
how far you are into the animation range at the beginning, then map it to a
time in the data range, and then loop over the features to see if they're
before or after that time. This has the added benefit that setTimeout then
becomes really easy to map to requestAnimationFrame, as you just run it
util your animation progress is past 100%

So something like (in pseudo-pseudo-code):

Animator.prototype.animate = function() {
var animationProgress = (new Date().getTime() - this.animationStart) / this.duration;
var currentTime = this.startTime + animationProgress * (this.endTime - this.startTime);
// display currentTime in control

for (var i = this.index; i < this.features_.length; i++) {
// if feature.time < currentTime, add to map.Data
// else break
}
this.index = i;

if (animationProgress < 1) {
var that = this; // ugh
window.requestAnimationFrame(function() {
that.animate();
});
} else {
if (this.repeat) {
this.start();
}
}
}

and then use one the requestAnimationFrame polyfills listed here for
IE8/9:
http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

just a suggestion, but this approach seems clearer (to me, at least).


Reply to this email directly or view it on GitHubhttps://github.com//pull/2#issuecomment-42496625
.

@brendankenny
Copy link
Contributor

Ah, good point. You can actually still achieve that by adding
animationProgress = Math.floor(animationProgress * this.steps) / this.steps;
as the second line to the above function.

(though this depends on your definition of "number of steps" for an animation, as this gives an animation of this.steps steps, including the 0th and ending state...you'd use this.steps + 1 or this.steps + 2 if you wanted to interpret "number of steps" exclusive of the end or exclusive of both, respectively)

@jlivni
Copy link
Author

jlivni commented May 19, 2014

Thanks makes sense. Done.


/**
* @constructor
* @param {google.maps.Map} map features already loaded in map.data.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth passing in map.data separately - can't people create separate Data objects?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah but that's fairly (extremely?) rare; will add it to options anyone requests it.

* @type {number}
*/
//TODO(jlivni): implement this.
this.fadeSteps = 3;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it's more intuitive to express fading as a function of time, rather than steps, which are kind of like time.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I am not sure. But since I have not implemented it I will just remove it for now and probably add back in later with option for time or steps.

* Milliseconds the animation should last.
* @type {number}
*/
this.duration = 30000; // ms the aninmation should last.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are still a heap of public properties that i'm pretty sure should be private, no?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

other options private for reals now

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants