Files
impress.js/src/lib
thawk 629f7686f3 Add relative move and rotate to rel plugin (#794)
The relative position in rel plugin is currently based on the world coordinate. So for the same effect, like fly in from the right-hand side, we must use different `data-rel-x/y/z` value. Why not let the plugin do the hard part?

So I introduce a `data-rel-position`, when set to `relative`, all relative attribute is based on the position and rotation of previous slide. So no matter the rotation of previous slide, data-rel-x="1000" always looks like fly in from the right-hand side. We can change the position and rotation of one slide, and the position of all following slides will be changed too.

When `data-rel-position` is set to `relative`, relative rotation has a clear meaning. It describes the relative rotations between slides. We don't need to set rotations for all slide, setting the key slides is enough. If `data-rel-position` is not relative, the effect of `data-rel-rotate-x/y/z` is not clear, so they're only used when `data-rel-position="relative"`.

After the introduction of relative rotation, there're 6 attribute that will inherit from previous slide. If we want to set a relative X move, we have to set all other 5 attributes to 0. It's boring. So a `data-rel-clear` is used to set all 6 attributes to 0, and then the value specified in current slide is applied. 

The `examples/3D-positions/index.html` shows some usage. As you can see, the html code of two slide ring is the same, and slides except for the first two in a ring has no position attributes. It work by inheriting the previous one.

This PR invokes a lot math calculations. Basically, the rotation of a slide is translated into the coordinate describing the directions of X/Y/Z axes. And `data-rel-x/y/z` can be easily calculated by that. The rotations is the hard part, I mainly use the algorithm in the Quaternions and spatial rotation - Wikipedia to compose two and more rotations.  I'm not a math guy, hope I don't make much mistakes.
2022-04-24 21:37:50 +03:00
..

Impress.js Libraries

The src/lib/*.js files contain library functions. The main difference to plugins is that:

  1. Libraries are closer to the impress.js core than plugins (arguably a subjective metric)
  2. Libraries are common utility functions used by many plugins
  3. Libraries are called synchronously, which is why the event based paradigm that plugins use to communicate isn't useful.

Plugins can access libraries via the API:

var api;
document.addEventListener( "impress:init", function(event){
    api = event.detail.api;
    api().lib.<libraryName>.<libaryFunction>();
});

...which is equivalent to:

impress().lib.<libraryName>.<libraryFunction>();

Implementing a library

  1. Create a file under src/lib/.

  2. Start with the standard boilerplate documentation, and the (function(document, window){})(); wrapper.

  3. The library should implement a factory function, and make its existence known to impress.js core:

    window.impress.addLibraryFactory( { libName : libraryFactory} );

  4. The library function should return a similar API object as core impress() function does:

    var libraryFactory = function(rootId) { /* implement library functions ... */

     var lib = {
         libFunction1: libFunction1,
         libFunction2: libFunction2
     }
     return lib;
    

    };

  5. While rarely used, impress.js actually supports multiple presentation root div elements on a single html page. Each of these have their own API object, identified by the root element id attribute:

    impress("other-root-id").init();

(The default rootId obviously is "impress".)

Libraries MUST implement this support for multiple root elements as well.

  • impress.js core will call the factory once for each separate root element being initialized via impress.init(rootId).
  • Any state that a library might hold, MUST be stored per rootId.
  • Note that as we now support also impress(rootId).tear(), the same root element might be initialized more than once, and each of these MUST be treated as a new valid initialization.

Putting all of the above together, a skeleton library file will look like:

/**
* Example library libName
*
* Henrik Ingo (c) 2016
* MIT License
*/
(function ( document, window ) {
    'use strict';
    // Singleton library variables
    var roots = [];
    var singletonVar = {};
    
    var libraryFactory = function(rootId) {
        if (roots["impress-root-" + rootId]) {
            return roots["impress-root-" + rootId];
        }
        
        // Per root global variables (instance variables?)
        var instanceVar = {};

        // LIBRARY FUNCTIONS
        var libraryFunction1 = function () {
            /* ... */
        };
        
        var libraryFunction2 = function () {
            /* ... */
        };
        
        var lib = {
                libFunction1: libFunction1,
                libFunction2: libFunction2
            }
        roots["impress-root-" + rootId] = lib;
        return lib;
    };
    
    // Let impress core know about the existence of this library
    window.impress.addLibraryFactory( { libName : libraryFactory } );
    
})(document, window);