226 lines
10 KiB
TypeScript
226 lines
10 KiB
TypeScript
/* ! Licensed under MIT License - https://github.com/impress/impress.js/blob/master/LICENSE */
|
|
/**
|
|
* impress.js
|
|
*
|
|
* impress.js is a presentation tool based on the power of CSS3 transforms and transitions
|
|
* in modern browsers and inspired by the idea behind prezi.com.
|
|
*
|
|
*
|
|
* Copyright 2011-2012 Bartek Szopka (@bartaz), 2016-2024 Henrik Ingo (@henrikingo), 2024 Janis Hutz
|
|
* and 70+ other contributors
|
|
*
|
|
* Released under the MIT License.
|
|
*
|
|
* ------------------------------------------------
|
|
* authors: Bartek Szopka, Henrik Ingo, Janis Hutz
|
|
* version: 3.0.0
|
|
* url: http://impress.js.org
|
|
* source: http://github.com/impress/impress.js/
|
|
*/
|
|
|
|
// Welcome to the impress.js source code!
|
|
// You are one of those who would like to know how impress.js works?
|
|
// Let us show you!
|
|
// Please note that compared to previous versions of impress, this code is documented in a more technical fashion.
|
|
|
|
// Important note on the file structure of impress.js, as it has changed with V3:
|
|
// -------------------------------------------------------------------------------
|
|
// This file contains all the interface definitions and uses various components from the ./lib directory,
|
|
// as well as loading impress plugins from the ./plugins directory. A fully built impress.js version
|
|
// has all of these files combined into a single file, as to enable a simple include.
|
|
|
|
// All internal functions are (to be) prefixed with an underscore
|
|
|
|
class ImpressNotSupportedError extends Error {}
|
|
class ImpressInitError extends Error {}
|
|
|
|
class ImpressConfig {
|
|
constructor( ) {
|
|
|
|
}
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
( window as any ).impress = () => {
|
|
// Somehow eslint didn't like the variable being reassigned inside of a function...
|
|
// So I had it shut up
|
|
// eslint-disable-next-line prefer-const
|
|
let initializedElements = {};
|
|
|
|
// Check if impress is supported. We use the CSS.supports API which is supported in all
|
|
// browsers except IE, for which we dropped support with V3 to move forward with state-of-the-art
|
|
// CSS & JS features.
|
|
// eslint-disable-next-line no-warning-comments
|
|
// TODO: Add additional required elements to checks as well
|
|
|
|
const isImpressSupported = ( CSS !== undefined ) && CSS.supports( 'perspective', '100px' ) && ( document.body.classList ) && document.body.dataset;
|
|
if ( !isImpressSupported ) {
|
|
// We can't be sure that classList exists, so let's better not use it
|
|
document.body.className += ' impress-not-supported';
|
|
} else {
|
|
document.body.classList.remove( 'impress-not-supported' );
|
|
document.body.classList.add( 'impress-supported' );
|
|
}
|
|
|
|
type PluginInitFunction = () => void;
|
|
|
|
/**
|
|
* This function is used to initialize impress. It calls some prep functions and then loads
|
|
* all plugins that are registered. By default, these are the built-in plugins. You can define
|
|
* which plugins are loaded by passing in an array of plugin-functions into the init function
|
|
* @param {Array<String>|undefined} [pluginsToLoad] An array of plugins to load when initializing impress. Defaults to the built-in plugins that require explicit initialization.
|
|
* @returns {undefined}
|
|
*/
|
|
const init = ( pluginsToLoad?: Array<PluginInitFunction> ): void => {
|
|
// Check if impress is supported and refuse to init, if not supported.
|
|
if ( !isImpressSupported ) {
|
|
throw new ImpressNotSupportedError( 'Your browser does not support all required CSS attributes. Impress.js can therefore not be started. You will see a simplified version of the presentation.' );
|
|
}
|
|
|
|
// Set default set of plugins to initialize on init or, if pluginsToLoad is defined,
|
|
// use the plugins array to load
|
|
let toBeLoadedPlugins: Array<PluginInitFunction> = [];
|
|
if ( typeof pluginsToLoad !== 'undefined' ) {
|
|
toBeLoadedPlugins = pluginsToLoad;
|
|
}
|
|
|
|
// Let's initialize all plugins that have to be initialized
|
|
for ( const plugin in toBeLoadedPlugins ) {
|
|
if ( typeof ( toBeLoadedPlugins[ plugin ] ) === 'function' ) {
|
|
toBeLoadedPlugins[ plugin ]();
|
|
} else {
|
|
// Maybe somebody thinks they are funny to pass in an array of something but functions...
|
|
console.warn( 'impress().init() only accepts an array of functions! What you passed in was an array of ' + typeof ( toBeLoadedPlugins[ plugin ] ) + '. Impress will load regardless, but the plugins you wanted to load will not be loaded!' );
|
|
}
|
|
}
|
|
|
|
// Get the main #impress element and raise ImpressInitError if no #impress element was found
|
|
var impressMain = document.getElementById( 'impress' );
|
|
if ( impressMain === null ) {
|
|
throw new ImpressInitError( 'Your presentation does not contain any element with id "impress"' );
|
|
}
|
|
|
|
console.log( impressMain.dataset );
|
|
// create config for impress
|
|
|
|
// Finally, with init done, send out the 'impress:init' event.
|
|
// All plugins which use this event to initialize will now be initialized
|
|
document.dispatchEvent( new Event( 'impress:init' ) );
|
|
};
|
|
|
|
/**
|
|
* Use this function to create a new element on the canvas of impress.js
|
|
* It is used for example by the "presentation" plugin, which parses the presentation
|
|
* and initializes impress itself. You can also use this function to edit a previously
|
|
* generated element. This allows for example the Overview plugin to work as it does.
|
|
*
|
|
* @param {string} DOMElementID The DOM ID of the element to add to impress
|
|
* @param {object} coordinates An object representing the position in the 3D canvas
|
|
* @param {number} coordinates.x The translation in direction of x-axis
|
|
* @param {number} coordinates.y The translation in direction of y-axis
|
|
* @param {number} coordinates.z The translation in direction of z-axis
|
|
* @param {object} rotation An object representing the rotation around the x, y and z-axis
|
|
* @param {number} rotation.x The rotation in degrees around the x-axis
|
|
* @param {number} rotation.y The rotation in degrees around the y-axis
|
|
* @param {number} rotation.z The rotation in degrees around the z-axis
|
|
* @returns {boolean} Returns true if successful at positioning this element, false, if failed
|
|
*/
|
|
const addElement = ( DOMElementID: string, coordinates: { x: number; y: number; z: number; }, rotation: { x: number; y: number; z: number; } ): boolean => {
|
|
if ( DOMElementID === '' || !DOMElementID ) {
|
|
return false;
|
|
}
|
|
coordinates.x = coordinates.x ?? 0;
|
|
coordinates.y = coordinates.y ?? 0;
|
|
coordinates.z = coordinates.z ?? 0;
|
|
rotation.x = rotation.x ?? 0;
|
|
rotation.y = rotation.y ?? 0;
|
|
rotation.z = rotation.z ?? 0;
|
|
initializedElements[ DOMElementID ] = {
|
|
coordinates: coordinates,
|
|
rotation: rotation,
|
|
id: DOMElementID
|
|
};
|
|
positionElements();
|
|
|
|
// Dispatch event that an element was added
|
|
document.dispatchEvent( new Event( 'impress:addedElement' ) );
|
|
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* This function allows you to remove an element from the canvas. Essentially,
|
|
* impress.js just hides this element and ignores it in translations & rotations
|
|
* @param {string} DOMElementID The element that is removed. Has to be the element ID of a DOM element
|
|
* @returns {boolean} Returns true if successful, false if failed.
|
|
*/
|
|
const removeElement = ( DOMElementID: string ): boolean => {
|
|
try {
|
|
delete initializedElements[ DOMElementID ];
|
|
} catch ( err ) {
|
|
return false;
|
|
}
|
|
positionElements();
|
|
// Dispatch event that an element was removed
|
|
document.dispatchEvent( new Event( 'impress:removedElement' ) );
|
|
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Internal function that positions elements on the canvas. Called every time a element is added / removed
|
|
* @returns {undefined}
|
|
*/
|
|
const positionElements = (): undefined => {
|
|
// Gets current position and calls moveTo function
|
|
moveTo( getCurrentPos().coordinates, getCurrentPos().rotation );
|
|
};
|
|
|
|
/**
|
|
* You can use this function to specify a movement and/or rotation of the canvas.
|
|
* @param {object} coordinates An object of the coordinatest to move to
|
|
* @param {number} coordinates.x The translation in direction of x-axis
|
|
* @param {number} coordinates.y The translation in direction of y-axis
|
|
* @param {number} coordinates.z The translation in direction of z-axis
|
|
* @param {object} rotation An object of the rotation around the axis to get to
|
|
* @param {number} rotation.x The rotation in degrees around the x-axis
|
|
* @param {number} rotation.y The rotation in degrees around the y-axis
|
|
* @param {number} rotation.z The rotation in degrees around the z-axis
|
|
* @returns {promise<boolean>} This promise resolves as a boolean, indicating success or failure
|
|
*/
|
|
const moveTo = ( coordinates: object, rotation: object ): Promise<boolean> => new Promise( ( resolve, reject ) => {
|
|
// Dispatch event telling all plugins that we're moving
|
|
document.dispatchEvent( new Event( 'impress:moving' ) );
|
|
console.log( coordinates, rotation );
|
|
if ( typeof ( coordinates ) === 'object' ) {
|
|
resolve( true );
|
|
} else {
|
|
reject( new Error( 'moveTo takes a coordinate and rotation object as arguments' ) );
|
|
}
|
|
} );
|
|
|
|
/**
|
|
* You can use this function to get all registered impress elements.
|
|
* @returns {object} Returns an object containing all initialized elements
|
|
*/
|
|
const getElements = ():object => initializedElements;
|
|
|
|
/**
|
|
* Returns the current position as an object of form { coordinates: Object, rotation: Object }
|
|
* @returns {object} Returns an object that contains an object of the coordinates and rotation:
|
|
* { coordinates: { x: number, y: number, z: number }, rotation: { x: number, y: number, z: number }
|
|
*/
|
|
const getCurrentPos = ():{ coordinates: { x: number, y: number, z: number }, rotation: { x: number, y: number, z: number } } => ( { coordinates: { x: 0, y: 0, z: 0 }, rotation: { x: 0, y: 0, z: 0 } } );
|
|
|
|
|
|
// Return all functions that are exposed by impress
|
|
return {
|
|
init,
|
|
getElements,
|
|
moveTo,
|
|
removeElement,
|
|
addElement,
|
|
getCurrentPos
|
|
};
|
|
};
|