StoryBoard Basics

Storyboard - Slideshow

The storyboard allows for state logic to be written into specific classes and eliminates the need to override the hamonengine.core.engine class. Creating a frame is as simple as overriding the hamonengine.events.frame class and responds to many of the same events.

One of the simpler implementations is to provide linear functionaltiy such as a slide show (slideFrame) The keys listed below or clicking on the arrows using a mouse or touch areas will change the images (frames). Clicking on the home button will return to first image (frame).

  • Left Arrow - Shows the previous image.
  • Right Arrow - Shows the next image.
  • Up Arrow - Jumps to the first image.

Canvas tag not supported

Image Credit

All images were provided by https://www.pexels.com/ with the credit information below.

The setup is a very simple using a series of flat storyboard where the frames are only siblings of each other.

  • Note that the frames are all of the same class as well.
  • The loop argument is true so the last and first frames will wrap onto each other.
  • The preloadAllFrames argument is false so all frames load in parallel.
const storyboard = new hamonengine.events.storyboard({ loop: true, preloadAllFrames: true, allowFramesToComplete: false });
storyboard.append(new slideFrame({ url: '../../content/media/Stream2.jpg', credit: 'Michael Block', name: 'Stream During Daytime' }));
storyboard.append(new slideFrame({ url: '../../content/media/Waves2.jpg', credit: 'Lukas Rodriguez', name: 'Sea Waves Crashing' }));
storyboard.append(new slideFrame({ url: '../../content/media/Clouds2.jpg', credit: 'Ruvim', name: 'Cumulus Clouds at Sunset' }));
storyboard.append(new slideFrame({ url: '../../content/media/Squirrel.jpeg', credit: 'David Selbert', name: 'Squirrel Eating Cone' }));

(await new hamonengine.core.engine({storyboard}).load()).start();
                        

The frame (storyboard element) responds to all events supported in the engine with the exception that these events contain a reference to the parent storyboard. A reference to the engine & primaryScreen are found within the storyboard.

/**
* An event that occurs when attempting to load resources.
* @param {object} storyboard calling the load operation.
* @return {Object} a promise that the resource has loaded successfully.
*/
async onloadResources(storyboard) {
    ...
    //Fetch the primaryScreen for drawing.
    const screen = storyboard.engine.primaryScreen;
    ...
}
                        
/**
* An onFrame event that is triggered when this item is active.
* @param {number} elapsedTimeInMilliseconds since the last frame.
* @param {object} storyboard used to invoke this onFrame event.
* @param {number} totalTimeInMilliseconds is the total time that has elapsed since the engine has started.
* @param {object} lastFrame contains the last frame before transitioning to this one.  NOTE: This can be null or undefined.
*/
onFrame(elapsedTimeInMilliseconds, storyboard, totalTimeInMilliseconds, lastFrame) {
    const engine = storyboard.engine;
    const screen = engine.primaryScreen;
    ...
}
                        

Using the HamonEngine's onKeyEvent event the storyboard can be advanced to the next, previous, or first frames based on key events. The engine can also be stopped.

/**
* Processes keyboard events.
* @param {object} storyboard used to invoke this onKeyEvent event.
* @param {string} type of keyboard event such as 'up' or 'down' for keyup and keydown.
* @param {string} keyCode of the key (see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code)
* @param {object} e KeyboardEvent (see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)
* @param {object} caller that triggered the event that can be a HTMLElement, instance of the HamonEngine, or a screen (see hamonengine.graphics.screen).
*/
onKeyEvent(storyboard, type, keyCode, e, caller) {
    if (type === 'down') {
        switch (keyCode) {
            case 'ArrowRight':
                storyboard.goNext();
                break;

            case 'ArrowLeft':
                storyboard.goPrev();
                break;

            case 'ArrowUp':
                storyboard.goFirst();
                break;

            case 'Escape':
                storyboard.engine.stop();
                break;
        }
    }
}
                        

Using the HamonEngine's onMouseEvent event the storyboard can be advanced to the next, previous, or first frames based on mouse events. The engine can also be stopped.

/**
* Processes mouse & touch events if captureTouchAsMouseEvents is set to true.
* @param {object} storyboard used to invoke this onMouseEvent event.
* @param {string} type of mouse event such as: 'click', 'up', 'down', 'move', 'enter', 'leave'.
* @param {object} v an instance of vector2 object that contain the x & y coordinates (see hamonengine.math.vector2).
* @param {object} e MouseEvent (see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent)
* @param {object} caller that triggered the event that can be a HTMLElement, instance of the HamonEngine, or a screen (see hamonengine.graphics.screen).
*/
onMouseEvent(storyboard, type, v, e, caller) {
    const tolerance = 60;
    if (type === 'click') {
        //Clicking on the left of the screen will navigate to the previous frame in the storyboard.
        if (v.x > 0 && v.x < caller.viewPort.x + tolerance) {
            storyboard.goPrev();
        }
        //Clicking on the right of the screen will navigate to the next frame in the storyboard.
        else if (v.x > caller.viewPort.width - tolerance && v.x < caller.viewPort.width) {
            storyboard.goNext();
        }

        //Clicking on the top of the screen will reset the storyboard to the first frame.
        if (v.y > 0 && v.y < caller.viewPort.y + tolerance) {
            storyboard.goFirst();
        }

        caller.tooltip = '';
    }

    //Show the appropriate tooltip & cursor based on the lcoation of the mouse cursor.
    if (type === 'move') {
        let tooltip = '';
        if (v.x > 0 && v.x < caller.viewPort.x + tolerance) {
            tooltip = 'Previous';
        }
        else if (v.x > caller.viewPort.width - tolerance && v.x < caller.viewPort.width) {
            tooltip = 'Next';
        }

        if (storyboard.first !== this && v.y > 0 && v.y < caller.viewPort.y + tolerance) {
            tooltip = 'Home';
        }

        caller.tooltip = tooltip;
        caller.cursor = tooltip === '' ? 'auto' : 'pointer';
    }
}