Animate CC: HTML5 Canvas Timeline Scrubber

Introduction

While most animations produced through Animate CC simply play back according to the author’s design, it is entirely possible to provide control of the timeline to the user as well. We will need to build an interactive playback scrubber and write some code to allow the user to utilize this element to scrub the timeline of an HTML5 Canvas document.

The Sample Document

Download FLA

The provided sample document is already set up with a slider for scrubbing and a draggable thumb element the user can interact with. As you can see in the image below, the stage has been set at 300×300 with a black background. The animation is set to run at 24 frames per second with content in the timeline extending across 24 frames – making 1 second of animation.

The timeline contains 3 layers, one named “Actions” to hold our JavaScript code, one named “Slider” for our interactive scrubber MovieClip symbol instances, and a “Content” layer containing 24 keyframes with text expressing the current frame number visually.

Within the “Slider” layer are two very important elements. Both are MovieClip symbol instances and have been assigned specific instance names in order to reference them within our code.

The instance of “SliderRail” has been given the instance name of “rail”. This element visually indicates to the user the bounds of where they can drag the scrubber, and also is used to calculate the actual bounds through JavaScript. In order for this to work properly, we must also choose to publish Multiframe bounds within the Advanced tab of our document Publish Settings. This setting will publish addition information about our objects, including their width and height.

The instance of “SliderThumb” has been given the instance name of “thumb” and is a simple circular object that the user will be able to drag along the rail.

Again, the “Content” layer could really be anything – it’s just visual content that changes along with the playhead.

Writing the Scrubber Code

Within the “Actions” layer, on frame 1, there is a bit of code. We’ll now open the Actions panel with that frame selected to go over the JavaScript instructions within. If your Actions panel is not open, you can open it from the Window option of the application menu.

The first thing we do is stop the playhead from running by invoking:

this.stop();

We then set a variable named _this to refer to the main timeline and avoid scope issues within JavaScript. Additionally, we need to preserve the x position and width measurements of our rail in order to properly calculate everything that needs to happen and to place restrictions on the scrubber thumb movement. We gather the width from a frameBounds array – which is only produced when we publish multiframe bounds.

var _this = this;
this.railX = this.rail.x; this.railW = this.rail.frameBounds[0].width;

Next is the drag function itself is define by a pressmove event is bound to our “thumb” instance on the stage. We calculate a new x position for the “thumb” instance based upon the movement of the mouse cursor once the object has been pressed upon. This is based on the x position of the cursor at the time, taking the pixel density of the screen into consideration as well.

_this.thumb.on("pressmove", function(e) {
var newX = e.stageX / _this.stage.scaleX;
});

Still within the body of this function, we use the recorded scrubber rail position and width information to detect whether the new position of the slider thumb is valid or not. Basically, if the position overlays the rail… then we are okay to proceed. We immediately set the x position of the thumb scrubber to match that of the mouse cursor. This is what causes the drag action.

if(newX >= _this.railX && newX <= (_this.railW + _this.railX)){
e.currentTarget.x = newX;
}

Within that same if statement, we perform some mathematics to figure out the frame ratio based upon the position of our thumb scrubber in relation to the entire with and position of the rail we are constraining its movement to. Using that, we can discover the exact frame we need to jump to by multiplying it by the total number of frames along the timeline. We finally instruct the playhead to jump to that specific frame.

var frameRatio = (e.target.parent.x - _this.railX) / _this.railW;
var newFrame = Math.round(frameRatio * (_this.totalFrames-1));
_this.gotoAndStop(newFrame);

The completed code appears as below:

this.stop();
var _this = this; this.railX = this.rail.x; this.railW = this.rail.frameBounds[0].width;
_this.thumb.on("pressmove", function(e) { var newX = e.stageX / _this.stage.scaleX; if(newX >= _this.railX && newX <= (_this.railW + _this.railX)){ e.currentTarget.x = newX; var frameRatio = (e.target.parent.x - _this.railX) / _this.railW; var newFrame = Math.round(frameRatio * (_this.totalFrames-1)); _this.gotoAndStop(newFrame); } });

Conclusion

The preceding example allows the user to control the timeline through a basic slider. The way this has been written, the rail can have any width you desire, and the slider can be placed wherever you wish. It’s very flexible!

12 thoughts on “Animate CC: HTML5 Canvas Timeline Scrubber”

  1. This is a great function to have for AnCC HTML5, thank you.

    I am attempting to modify it for use inside a MovieClip, instead of scrubbing the main timeline, I want it to scrub the timeline of a MC.

    Using it’s Instance Name

    Since “_this” = the main timeline, I should be able to replace that with a reference to my MC, correct?

    This is my modified code:

    this.stop();

    var this.parent.MClip_01 = this;
    this.railX = this.rail.x;
    this.railW = this.rail.frameBounds[0].width;

    _this.thumb.on(“pressmove”, function(e) {
    var newX = this.parent.MClip_01X / this.parent.MClip_01.scaleX;
    if(newX >= _this.railX && newX <= (_this.railW + _this.railX)){
    e.currentTarget.x = newX;
    var frameRatio = (e.target.this.parent.MClip_01.x – _this.railX) / _this.railW;
    var newFrame = Math.round(frameRatio * (_this.totalFrames-1));
    _this.gotoAndStop(newFrame);
    }
    });

    Unsurprisingly it does nothing at all, any pointers for me?

    Thanks!

      1. Thanks!

        I managed to get it to work inside movie clips, this is very cool. I am modifying your code to create scrollable dynamic text windows and seem to have got it working somewhat…

        The feature works fine on desktop browsers but isn’t working at all on my Android phone – is there some way to make this mobile friendly?

        Have a look at what I’ve done so far and thanks again for this!

        http://jefferywright.com/wp-content/uploads/2018/10/html5_drag_text_window_slider_timeline_scrub_vertical_adobe_animatecc_canvas_10.08.2018-1.html

        1. Never mind, got it sorted, totally forgot about createjs.Touch.enable(stage);

          Sorry to be such a spazz, I’m pretty excited about being able to have this to use… I’ll make my edited version available to download for anyone to use.

        2. I know your above notes where from last you but could you possibly remember how you where able to get the code to work inside the movie clip? Thanks!

          1. Kaitlyn Ducharme

            I would really, really appreciate that modified code to attach a scrubber to a Movie Clip if possible. Thanks in advance!

  2. Can code be added to this so the scrubber can move along with timeline and still be able to “pressmove” the scrubber. Sort of a progress/drag scrubber

Leave a Comment

Your email address will not be published. Required fields are marked *