Compare commits
31 Commits
getting-st
...
v3
| Author | SHA1 | Date | |
|---|---|---|---|
| 77a83f6a4e | |||
| ef80cf45dc | |||
|
|
1d185e05a7 | ||
|
|
667cca709e | ||
|
|
33386d6247 | ||
|
|
d0b9bca5d4 | ||
|
|
2f99906932 | ||
| b0eb35bae4 | |||
|
|
b07199bc16 | ||
|
|
587be5ee61 | ||
|
|
2efd14b392 | ||
|
|
328cf3b8e8 | ||
|
|
6761ff8dfe | ||
| fd49cd4fb4 | |||
| 2d9c48d375 | |||
|
|
6a74c4e237 | ||
| 472e6d0f19 | |||
|
|
e326b2635f | ||
| a1fa8bea3d | |||
| 4199e99d81 | |||
| b4cc35084c | |||
| 90653fa34e | |||
|
|
125ab80766 | ||
|
|
ad27645c39 | ||
|
|
e0ebff6b0c | ||
|
|
80d496f2bd | ||
|
|
42af5452ae | ||
|
|
2b88f378b2 | ||
|
|
78bdf4050b | ||
|
|
fa87b43aab | ||
|
|
698558254f |
532
.eslintrc.js
532
.eslintrc.js
@@ -1,296 +1,300 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
"env": {
|
'env': {
|
||||||
"browser": true,
|
'browser': true,
|
||||||
"es6": true
|
'es6': true
|
||||||
},
|
},
|
||||||
"extends": "eslint:recommended",
|
'extends': [
|
||||||
"globals": {
|
'eslint:recommended',
|
||||||
"Atomics": "readonly",
|
'plugin:@typescript-eslint/recommended'
|
||||||
"SharedArrayBuffer": "readonly"
|
],
|
||||||
|
'globals': {
|
||||||
|
'Atomics': 'readonly',
|
||||||
|
'SharedArrayBuffer': 'readonly'
|
||||||
},
|
},
|
||||||
"parserOptions": {
|
'parserOptions': {
|
||||||
"ecmaVersion": 2018
|
'ecmaVersion': 2022
|
||||||
},
|
},
|
||||||
"rules": {
|
'parser': '@typescript-eslint/parser',
|
||||||
"accessor-pairs": "error",
|
'plugins': ['@typescript-eslint'],
|
||||||
"array-bracket-newline": "error",
|
'rules': {
|
||||||
"array-bracket-spacing": "error",
|
'accessor-pairs': 'error',
|
||||||
"array-callback-return": "error",
|
'array-bracket-newline': 'error',
|
||||||
"array-element-newline": "error",
|
'array-bracket-spacing': 'error',
|
||||||
"arrow-body-style": "error",
|
'array-callback-return': 'error',
|
||||||
"arrow-parens": "error",
|
'array-element-newline': 'error',
|
||||||
"arrow-spacing": "error",
|
'arrow-body-style': 'error',
|
||||||
"block-scoped-var": "off",
|
'arrow-parens': 'error',
|
||||||
"block-spacing": [
|
'arrow-spacing': 'error',
|
||||||
"error",
|
'block-scoped-var': 'off',
|
||||||
"always"
|
'block-spacing': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
],
|
],
|
||||||
"brace-style": [
|
'brace-style': [
|
||||||
"error",
|
'error',
|
||||||
"1tbs",
|
'1tbs',
|
||||||
{
|
{
|
||||||
"allowSingleLine": true
|
'allowSingleLine': true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"callback-return": "error",
|
'callback-return': 'error',
|
||||||
"camelcase": "error",
|
'camelcase': 'error',
|
||||||
"capitalized-comments": "off",
|
'capitalized-comments': 'off',
|
||||||
"class-methods-use-this": "error",
|
'class-methods-use-this': 'off',
|
||||||
"comma-dangle": "error",
|
'comma-dangle': 'error',
|
||||||
"comma-spacing": [
|
'comma-spacing': [
|
||||||
"error",
|
'error',
|
||||||
{
|
{
|
||||||
"after": true,
|
'after': true,
|
||||||
"before": false
|
'before': false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"comma-style": [
|
'comma-style': [
|
||||||
"error",
|
'error',
|
||||||
"last"
|
'last'
|
||||||
],
|
],
|
||||||
"complexity": "error",
|
'complexity': 'error',
|
||||||
"computed-property-spacing": [
|
'computed-property-spacing': [
|
||||||
"error",
|
'error',
|
||||||
"always"
|
'always'
|
||||||
],
|
],
|
||||||
"consistent-return": "error",
|
'consistent-return': 'error',
|
||||||
"consistent-this": "off",
|
'consistent-this': 'off',
|
||||||
"curly": "error",
|
'curly': 'error',
|
||||||
"default-case": "error",
|
'default-case': 'error',
|
||||||
"dot-location": "error",
|
'dot-location': 'error',
|
||||||
"dot-notation": "error",
|
'dot-notation': 'error',
|
||||||
"eol-last": "error",
|
'eol-last': 'error',
|
||||||
"eqeqeq": "error",
|
'eqeqeq': 'error',
|
||||||
"func-call-spacing": "error",
|
'func-call-spacing': 'error',
|
||||||
"func-name-matching": "error",
|
'func-name-matching': 'error',
|
||||||
"func-names": "off",
|
'func-names': 'off',
|
||||||
"func-style": [
|
'func-style': [
|
||||||
"error",
|
'error',
|
||||||
"expression"
|
'expression'
|
||||||
],
|
],
|
||||||
"function-paren-newline": "error",
|
'function-paren-newline': 'error',
|
||||||
"generator-star-spacing": "error",
|
'generator-star-spacing': 'error',
|
||||||
"global-require": "error",
|
'global-require': 'error',
|
||||||
"guard-for-in": "error",
|
'guard-for-in': 'error',
|
||||||
"handle-callback-err": "error",
|
'handle-callback-err': 'error',
|
||||||
"id-blacklist": "error",
|
'id-blacklist': 'error',
|
||||||
"id-length": "off",
|
'id-length': 'off',
|
||||||
"id-match": "error",
|
'id-match': 'error',
|
||||||
"implicit-arrow-linebreak": "error",
|
'implicit-arrow-linebreak': 'error',
|
||||||
"indent": "error",
|
'indent': 'error',
|
||||||
"indent-legacy": "error",
|
'indent-legacy': 'error',
|
||||||
"init-declarations": "off",
|
'init-declarations': 'off',
|
||||||
"jsx-quotes": "error",
|
'jsx-quotes': 'error',
|
||||||
"key-spacing": "off",
|
'key-spacing': 'off',
|
||||||
"keyword-spacing": [
|
'keyword-spacing': [
|
||||||
"error",
|
'error',
|
||||||
{
|
{
|
||||||
"after": true,
|
'after': true,
|
||||||
"before": true
|
'before': true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"line-comment-position": "off",
|
'line-comment-position': 'off',
|
||||||
"linebreak-style": [
|
'linebreak-style': [
|
||||||
"error",
|
'error',
|
||||||
"unix"
|
'unix'
|
||||||
],
|
],
|
||||||
"lines-around-comment": "error",
|
'lines-around-comment': 'error',
|
||||||
"lines-around-directive": "off",
|
'lines-around-directive': 'off',
|
||||||
"lines-between-class-members": "error",
|
'lines-between-class-members': 'error',
|
||||||
"max-classes-per-file": "error",
|
'max-depth': 'error',
|
||||||
"max-depth": "error",
|
'max-len': 'off',
|
||||||
"max-len": "off",
|
'max-lines': 'error',
|
||||||
"max-lines": "error",
|
'max-lines-per-function': 'off',
|
||||||
"max-lines-per-function": "off",
|
'max-nested-callbacks': 'error',
|
||||||
"max-nested-callbacks": "error",
|
'max-params': 'error',
|
||||||
"max-params": "error",
|
'max-statements': 'off',
|
||||||
"max-statements": "off",
|
'max-statements-per-line': 'off',
|
||||||
"max-statements-per-line": "off",
|
'multiline-comment-style': [
|
||||||
"multiline-comment-style": [
|
'error',
|
||||||
"error",
|
'separate-lines'
|
||||||
"separate-lines"
|
|
||||||
],
|
],
|
||||||
"new-cap": "error",
|
'new-cap': 'error',
|
||||||
"new-parens": "error",
|
'new-parens': 'error',
|
||||||
"newline-after-var": "off",
|
'newline-after-var': 'off',
|
||||||
"newline-before-return": "off",
|
'newline-before-return': 'off',
|
||||||
"newline-per-chained-call": "error",
|
'newline-per-chained-call': 'error',
|
||||||
"no-alert": "error",
|
'no-alert': 'error',
|
||||||
"no-array-constructor": "error",
|
'no-array-constructor': 'error',
|
||||||
"no-async-promise-executor": "error",
|
'no-async-promise-executor': 'error',
|
||||||
"no-await-in-loop": "error",
|
'no-await-in-loop': 'error',
|
||||||
"no-bitwise": "error",
|
'no-bitwise': 'error',
|
||||||
"no-buffer-constructor": "error",
|
'no-buffer-constructor': 'error',
|
||||||
"no-caller": "error",
|
'no-caller': 'error',
|
||||||
"no-catch-shadow": "error",
|
'no-catch-shadow': 'error',
|
||||||
"no-confusing-arrow": "error",
|
'no-confusing-arrow': 'error',
|
||||||
"no-continue": "error",
|
'no-continue': 'error',
|
||||||
"no-div-regex": "error",
|
'no-div-regex': 'error',
|
||||||
"no-duplicate-imports": "error",
|
'no-duplicate-imports': 'error',
|
||||||
"no-else-return": "error",
|
'no-else-return': 'error',
|
||||||
"no-empty-function": "error",
|
'no-empty-function': 'error',
|
||||||
"no-eq-null": "error",
|
'no-eq-null': 'error',
|
||||||
"no-eval": "error",
|
'no-eval': 'error',
|
||||||
"no-extend-native": "error",
|
'no-extend-native': 'error',
|
||||||
"no-extra-bind": "error",
|
'no-extra-bind': 'error',
|
||||||
"no-extra-label": "error",
|
'no-extra-label': 'error',
|
||||||
"no-extra-parens": "off",
|
'no-extra-parens': 'off',
|
||||||
"no-floating-decimal": "error",
|
'no-floating-decimal': 'error',
|
||||||
"no-implicit-coercion": "error",
|
'no-implicit-coercion': 'error',
|
||||||
"no-implicit-globals": "error",
|
'no-implicit-globals': 'error',
|
||||||
"no-implied-eval": "error",
|
'no-implied-eval': 'error',
|
||||||
"no-inline-comments": "off",
|
'no-inline-comments': 'off',
|
||||||
"no-inner-declarations": [
|
'no-inner-declarations': [
|
||||||
"error",
|
'error',
|
||||||
"functions"
|
'functions'
|
||||||
],
|
],
|
||||||
"no-invalid-this": "off",
|
'no-invalid-this': 'off',
|
||||||
"no-iterator": "error",
|
'no-iterator': 'error',
|
||||||
"no-label-var": "error",
|
'no-label-var': 'error',
|
||||||
"no-labels": "error",
|
'no-labels': 'error',
|
||||||
"no-lone-blocks": "error",
|
'no-lone-blocks': 'error',
|
||||||
"no-lonely-if": "error",
|
'no-lonely-if': 'error',
|
||||||
"no-loop-func": "error",
|
'no-loop-func': 'error',
|
||||||
"no-magic-numbers": "off",
|
'no-magic-numbers': 'off',
|
||||||
"no-misleading-character-class": "error",
|
'no-misleading-character-class': 'error',
|
||||||
"no-mixed-operators": "error",
|
'no-mixed-operators': 'error',
|
||||||
"no-mixed-requires": "error",
|
'no-mixed-requires': 'error',
|
||||||
"no-multi-assign": "error",
|
'no-multi-assign': 'error',
|
||||||
"no-multi-spaces": "off",
|
'no-multi-spaces': 'off',
|
||||||
"no-multi-str": "error",
|
'no-multi-str': 'error',
|
||||||
"no-multiple-empty-lines": "error",
|
'no-multiple-empty-lines': 'error',
|
||||||
"no-native-reassign": "error",
|
'no-native-reassign': 'error',
|
||||||
"no-negated-condition": "off",
|
'no-negated-condition': 'off',
|
||||||
"no-negated-in-lhs": "error",
|
'no-negated-in-lhs': 'error',
|
||||||
"no-nested-ternary": "error",
|
'no-nested-ternary': 'error',
|
||||||
"no-new": "error",
|
'no-new': 'error',
|
||||||
"no-new-func": "error",
|
'no-new-func': 'error',
|
||||||
"no-new-object": "error",
|
'no-new-object': 'error',
|
||||||
"no-new-require": "error",
|
'no-new-require': 'error',
|
||||||
"no-new-wrappers": "error",
|
'no-new-wrappers': 'error',
|
||||||
"no-octal-escape": "error",
|
'no-octal-escape': 'error',
|
||||||
"no-param-reassign": "off",
|
'no-param-reassign': 'off',
|
||||||
"no-path-concat": "error",
|
'no-path-concat': 'error',
|
||||||
"no-plusplus": "off",
|
'no-plusplus': 'off',
|
||||||
"no-process-env": "error",
|
'no-process-env': 'error',
|
||||||
"no-process-exit": "error",
|
'no-process-exit': 'error',
|
||||||
"no-proto": "error",
|
'no-proto': 'error',
|
||||||
"no-prototype-builtins": "error",
|
'no-prototype-builtins': 'error',
|
||||||
"no-restricted-globals": "error",
|
'no-restricted-globals': 'error',
|
||||||
"no-restricted-imports": "error",
|
'no-restricted-imports': 'error',
|
||||||
"no-restricted-modules": "error",
|
'no-restricted-modules': 'error',
|
||||||
"no-restricted-properties": "error",
|
'no-restricted-properties': 'error',
|
||||||
"no-restricted-syntax": "error",
|
'no-restricted-syntax': 'error',
|
||||||
"no-return-assign": "error",
|
'no-return-assign': 'error',
|
||||||
"no-return-await": "error",
|
'no-return-await': 'error',
|
||||||
"no-script-url": "error",
|
'no-script-url': 'error',
|
||||||
"no-self-compare": "error",
|
'no-self-compare': 'error',
|
||||||
"no-sequences": "error",
|
'no-sequences': 'error',
|
||||||
"no-shadow": "off",
|
'no-shadow': 'off',
|
||||||
"no-shadow-restricted-names": "error",
|
'no-shadow-restricted-names': 'error',
|
||||||
"no-spaced-func": "error",
|
'no-spaced-func': 'error',
|
||||||
"no-sync": "error",
|
'no-sync': 'error',
|
||||||
"no-tabs": "error",
|
'no-tabs': 'error',
|
||||||
"no-template-curly-in-string": "error",
|
'no-template-curly-in-string': 'error',
|
||||||
"no-ternary": "off",
|
'no-ternary': 'off',
|
||||||
"no-throw-literal": "error",
|
'no-throw-literal': 'error',
|
||||||
"no-trailing-spaces": "error",
|
'no-trailing-spaces': 'error',
|
||||||
"no-undef-init": "error",
|
'no-undef-init': 'error',
|
||||||
"no-undefined": "off",
|
'no-undefined': 'off',
|
||||||
"no-underscore-dangle": "error",
|
'no-underscore-dangle': 'error',
|
||||||
"no-unmodified-loop-condition": "error",
|
'no-unmodified-loop-condition': 'error',
|
||||||
"no-unneeded-ternary": "error",
|
'no-unneeded-ternary': 'error',
|
||||||
"no-unused-expressions": "error",
|
'no-unused-expressions': 'error',
|
||||||
"no-use-before-define": "off",
|
'no-use-before-define': 'off',
|
||||||
"no-useless-call": "error",
|
'no-useless-call': 'error',
|
||||||
"no-useless-catch": "error",
|
'no-useless-catch': 'error',
|
||||||
"no-useless-computed-key": "error",
|
'no-useless-computed-key': 'error',
|
||||||
"no-useless-concat": "error",
|
'no-useless-concat': 'error',
|
||||||
"no-useless-constructor": "error",
|
'no-useless-constructor': 'error',
|
||||||
"no-useless-rename": "error",
|
'no-useless-rename': 'error',
|
||||||
"no-useless-return": "error",
|
'no-useless-return': 'error',
|
||||||
"no-var": "off",
|
'no-var': 'off',
|
||||||
"no-void": "error",
|
'no-void': 'error',
|
||||||
"no-warning-comments": "error",
|
'no-warning-comments': 'error',
|
||||||
"no-whitespace-before-property": "error",
|
'no-whitespace-before-property': 'error',
|
||||||
"no-with": "error",
|
'no-with': 'error',
|
||||||
"nonblock-statement-body-position": "error",
|
'nonblock-statement-body-position': 'error',
|
||||||
"object-curly-newline": "error",
|
'object-curly-newline': 'error',
|
||||||
"object-curly-spacing": [
|
'object-curly-spacing': [
|
||||||
"error",
|
'error',
|
||||||
"always"
|
'always'
|
||||||
],
|
],
|
||||||
"object-shorthand": "off",
|
'object-shorthand': 'off',
|
||||||
"one-var": "off",
|
'one-var': 'off',
|
||||||
"one-var-declaration-per-line": "off",
|
'one-var-declaration-per-line': 'off',
|
||||||
"operator-assignment": "error",
|
'operator-assignment': 'error',
|
||||||
"operator-linebreak": "error",
|
'operator-linebreak': 'error',
|
||||||
"padded-blocks": "off",
|
'padded-blocks': 'off',
|
||||||
"padding-line-between-statements": "error",
|
'padding-line-between-statements': 'error',
|
||||||
"prefer-arrow-callback": "off",
|
'prefer-arrow-callback': 'off',
|
||||||
"prefer-const": "error",
|
'prefer-const': 'error',
|
||||||
"prefer-destructuring": "off",
|
'prefer-destructuring': 'off',
|
||||||
"prefer-numeric-literals": "error",
|
'prefer-numeric-literals': 'error',
|
||||||
"prefer-object-spread": "error",
|
'prefer-object-spread': 'error',
|
||||||
"prefer-promise-reject-errors": "error",
|
'prefer-promise-reject-errors': 'error',
|
||||||
"prefer-reflect": "off",
|
'prefer-reflect': 'off',
|
||||||
"prefer-rest-params": "off",
|
'prefer-rest-params': 'off',
|
||||||
"prefer-spread": "error",
|
'prefer-spread': 'error',
|
||||||
"prefer-template": "off",
|
'prefer-template': 'off',
|
||||||
"quote-props": "off",
|
'quote-props': 'off',
|
||||||
"quotes": [
|
'quotes': [
|
||||||
"error",
|
'error',
|
||||||
"double"
|
'single'
|
||||||
],
|
],
|
||||||
"radix": "error",
|
'radix': 'error',
|
||||||
"require-atomic-updates": "error",
|
'require-atomic-updates': 'error',
|
||||||
"require-await": "error",
|
'require-await': 'error',
|
||||||
"require-jsdoc": "error",
|
'require-jsdoc': 'error',
|
||||||
"require-unicode-regexp": "off",
|
'require-unicode-regexp': 'off',
|
||||||
"rest-spread-spacing": "error",
|
'rest-spread-spacing': 'error',
|
||||||
"semi": "error",
|
'semi': 'error',
|
||||||
"semi-spacing": [
|
'semi-spacing': [
|
||||||
"error",
|
'error',
|
||||||
{
|
{
|
||||||
"after": true,
|
'after': true,
|
||||||
"before": false
|
'before': false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"semi-style": [
|
'semi-style': [
|
||||||
"error",
|
'error',
|
||||||
"last"
|
'last'
|
||||||
],
|
],
|
||||||
"sort-imports": "error",
|
'sort-imports': 'error',
|
||||||
"sort-keys": "off",
|
'sort-keys': 'off',
|
||||||
"sort-vars": "off",
|
'sort-vars': 'off',
|
||||||
"space-before-blocks": "error",
|
'space-before-blocks': 'error',
|
||||||
"space-before-function-paren": "off",
|
'space-before-function-paren': 'off',
|
||||||
"space-in-parens": [
|
'space-in-parens': [
|
||||||
"error",
|
'error',
|
||||||
"always"
|
'always'
|
||||||
],
|
],
|
||||||
"space-infix-ops": "error",
|
'space-infix-ops': 'error',
|
||||||
"space-unary-ops": "error",
|
'space-unary-ops': 'error',
|
||||||
"spaced-comment": [
|
'spaced-comment': [
|
||||||
"error",
|
'error',
|
||||||
"always"
|
'always'
|
||||||
],
|
],
|
||||||
"strict": "error",
|
'strict': 'error',
|
||||||
"switch-colon-spacing": "error",
|
'switch-colon-spacing': 'error',
|
||||||
"symbol-description": "error",
|
'symbol-description': 'error',
|
||||||
"template-curly-spacing": "error",
|
'template-curly-spacing': 'error',
|
||||||
"template-tag-spacing": "error",
|
'template-tag-spacing': 'error',
|
||||||
"unicode-bom": [
|
'unicode-bom': [
|
||||||
"error",
|
'error',
|
||||||
"never"
|
'never'
|
||||||
],
|
],
|
||||||
"valid-jsdoc": "error",
|
'valid-jsdoc': 'error',
|
||||||
"vars-on-top": "off",
|
'vars-on-top': 'off',
|
||||||
"wrap-regex": "error",
|
'wrap-regex': 'error',
|
||||||
"yield-star-spacing": "error",
|
'yield-star-spacing': 'error',
|
||||||
"yoda": [
|
'yoda': [
|
||||||
"error",
|
'error',
|
||||||
"never"
|
'never'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@
|
|||||||
/node_modules
|
/node_modules
|
||||||
/npm-debug.log
|
/npm-debug.log
|
||||||
/*.tgz
|
/*.tgz
|
||||||
|
/built
|
||||||
|
|
||||||
# Files for editors and other tools
|
# Files for editors and other tools
|
||||||
/.brackets.json
|
/.brackets.json
|
||||||
|
|||||||
5
.jscsrc
5
.jscsrc
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"preset": "jquery",
|
|
||||||
// Since we check quotemarks already in jshint, this can be turned off
|
|
||||||
"validateQuoteMarks": false
|
|
||||||
}
|
|
||||||
17
.jshintrc
17
.jshintrc
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"globals": {
|
|
||||||
"module": true
|
|
||||||
},
|
|
||||||
"boss": true,
|
|
||||||
"browser": true,
|
|
||||||
"curly": true,
|
|
||||||
"esversion": 6,
|
|
||||||
"eqeqeq": true,
|
|
||||||
"eqnull": true,
|
|
||||||
"expr": true,
|
|
||||||
"immed": true,
|
|
||||||
"noarg": true,
|
|
||||||
"quotmark": "double",
|
|
||||||
"undef": true,
|
|
||||||
"unused": true
|
|
||||||
}
|
|
||||||
14
.vscode/tasks.json
vendored
Normal file
14
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "typescript",
|
||||||
|
"tsconfig": "tsconfig.json",
|
||||||
|
"problemMatcher": [
|
||||||
|
"$tsc"
|
||||||
|
],
|
||||||
|
"group": "build",
|
||||||
|
"label": "tsc: build - tsconfig.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2011-2016 Bartek Szopka
|
Copyright (c) 2011-2016 Bartek Szopka, 2016-2024 Henrik Ingo, 2024 Janis Hutz
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
215
README.md
215
README.md
@@ -1,77 +1,128 @@
|
|||||||
impress.js
|
<div id="title" align="center">
|
||||||
============
|
<img src="./logo.jpg" width="300">
|
||||||
|
<h1>impress.js</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
[](https://circleci.com/gh/impress/impress.js)
|
<div id="badges" align="center">
|
||||||
|
<img alt="Project License" src="https://img.shields.io/github/license/impress/impress.js.svg">
|
||||||
|
<img alt="GitHub Repo size" src="https://img.shields.io/github/repo-size/impress/impress.js.svg">
|
||||||
|
<img alt="GitHub Repo issues" src="https://img.shields.io/github/issues-pr-raw/impress/impress.js">
|
||||||
|
<a href="https://circleci.com/gh/impress/impress.js"><img alt="CircleCI" src="https://circleci.com/gh/impress/impress.js.svg?style=svg"></a>
|
||||||
|
<br>
|
||||||
|
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/impress/impress.js">
|
||||||
|
<img alt="GitHub watchers" src="https://img.shields.io/github/watchers/impress/impress.js">
|
||||||
|
<img alt="GitHub forks" src="https://img.shields.io/github/forks/impress/impress.js">
|
||||||
|
<br>
|
||||||
|
<img alt="GitHub all releases" src="https://img.shields.io/github/downloads/impress/impress.js/total?label=Downloads (total)">
|
||||||
|
<img alt="GitHub release (latest by date)" src="https://img.shields.io/github/downloads/impress/impress.js/latest/total?label=Downloads (latest)">
|
||||||
|
<img alt="Latest release" src="https://img.shields.io/github/release/impress/impress.js.svg">
|
||||||
|
</div>
|
||||||
|
|
||||||
It's a presentation framework based on the power of CSS3 transforms and
|
impress.js is a presentation framework written in JavaScript that uses the power of CSS3 transitions and transforms. It is inspired by the idea behind prezi.com
|
||||||
transitions in modern browsers and inspired by the idea behind prezi.com.
|
|
||||||
|
|
||||||
**WARNING**
|
**WARNING**
|
||||||
|
|
||||||
impress.js may not help you if you have nothing interesting to say ;)
|
impress.js may not help you if you have nothing interesting to say ;)
|
||||||
|
|
||||||
|
|
||||||
HOW TO USE IT
|
***THIS VERSION IS UNSTABLE AND INCOMPLETE. Please use the [upstream version](https://github.com/impress/impress.js) (V2.0.0)!***
|
||||||
---------------
|
|
||||||
### Getting Started Guide
|
|
||||||
Check out our new [Getting Started](GettingStarted.md) guide if you want a quick introduction to the project!
|
|
||||||
|
|
||||||
### Direct download link to only impress.js
|
We are switching to TS as the main impress development language, but you can still develop plugins in JS, if you wish!
|
||||||
You can include this link directly inside of your HTML file in its header. If you want to learn how to do this, you can find a how-to in the [Getting Started](GettingStarted.md) guide.
|
|
||||||
- V2.0.0: https://cdn.jsdelivr.net/gh/impress/impress.js@2.0.0/js/impress.js
|
|
||||||
- V1.1.0: https://cdn.jsdelivr.net/gh/impress/impress.js@1.1.0/js/impress.js
|
|
||||||
- Source: https://cdn.jsdelivr.net/gh/impress/impress.js/js/impress.js
|
|
||||||
|
|
||||||
### Getting Started Guide
|
# Getting Started with impress.js
|
||||||
Check out our new [Getting Started](GettingStarted.md) guide if you want a quick introduction to the project!
|
Welcome to impress.js, the impressive JavaScript framework, that allows you to build presentations for web browsers.
|
||||||
|
|
||||||
### Checking out and initializing the git repository
|
## Browser support
|
||||||
|
Since impress.js is designed to show off the power of modern CSS, we cannot guarantee that it will run in older browser. Whilst we try not to intentionally break support for certain browsers, some features might not work well on all browsers, especially with V3.x. For example, Internet Explorer is known to not work with V3.x, so if you really NEED to use that browser, please use V2.x. impress.js works best with the latest versions of Chrome, Firefox and most likely also with the latest versions of Safari.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
You can visit our website at [https://impress.js.org](https://impress.js.org) to learn more about the project, where you can also find helpful resources for getting started, like the [Getting Started Guide](/docs/GettingStarted.md) and [Documentation](/docs/DOCUMENTATION.md), but rendered as HTML instead of MarkDown, as it is here on GitHub.
|
||||||
|
|
||||||
|
|
||||||
|
## A very quick "quick start"
|
||||||
|
Copy one of the code snippets below to the header of your impress.js presentation's HTML file.
|
||||||
|
- V3.0.0:
|
||||||
|
```
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/impress/impress.js@3.0.0/dist/impress.min.js"/>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/impress/impress.js@3.0.0/dist/impress.min.css">
|
||||||
|
```
|
||||||
|
- V2.0.0:
|
||||||
|
```
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/impress/impress.js@2.0.0/js/impress.js"/>
|
||||||
|
```
|
||||||
|
- V1.1.0:
|
||||||
|
```
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/impress/impress.js@1.1.0/js/impress.js"/>
|
||||||
|
```
|
||||||
|
- Upstream:
|
||||||
|
```
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/impress/impress.js/dist/impress.min.js"/>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/impress/impress.js/dist/impress.min.css">
|
||||||
|
```
|
||||||
|
|
||||||
|
We do not recommend using the Upstream version, as there might be breaking changes coming or features might be temporarily broken due to only partially finished feature updates. Whilst this shouldn't happen normally, please be aware of that risk when using Upstream.
|
||||||
|
|
||||||
|
### Using a self-hosted version of impress.js
|
||||||
|
You can download impress.js from the releases tab. Some older versions might not have the `impress.js` file in the releases, you will be required to extract it from the source code archive. You can find the file in the `js` folder. New versions include the `impress.js`, `impress.min.js`, `impress.css` and `impress.min.css` files in the assets.
|
||||||
|
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
|
||||||
|
You can find the entire documentation of impress.js on our [website](https://impress.js.org/docs) or in the [DOCUMENTATION.md](/docs/DOCUMENTATION.md) file
|
||||||
|
|
||||||
|
The [HTML source code](index.html) of the official [impress.js demo](https://impress.js.org/) serves as a good example usage and contains comments explaining various features of impress.js. For more information about styling you can look into [CSS code](css/impress-demo.css) which shows how classes provided by impress.js can be used. Last but not least [JavaScript code of impress.js](js/impress.js) has some useful comments if you are interested in how everything works. Feel free to explore!
|
||||||
|
|
||||||
|
# Official demo
|
||||||
|
|
||||||
|
[impress.js demo](https://impress.js.org/) by [@bartaz](https://twitter.com/bartaz)
|
||||||
|
|
||||||
|
## Examples and demos
|
||||||
|
|
||||||
|
The [Classic Slides](https://impress.js.org/examples/classic-slides/) demo is targeted towards beginners, or can be used as a template for presentations that look like the traditional PowerPoint slide deck. Over time, it also grew into the example presentation that uses most of the features and addons available.
|
||||||
|
|
||||||
|
More examples and demos can be found on [Examples and demos wiki page](https://github.com/impress/impress.js/wiki/Examples-and-demos).
|
||||||
|
|
||||||
|
Feel free to add your own example presentations (or websites) there.
|
||||||
|
|
||||||
|
## Other tutorials and learning resources
|
||||||
|
|
||||||
|
If you want to learn even more there is a [list of tutorials and other learning resources](https://github.com/impress/impress.js/wiki/impress.js-tutorials-and-other-learning-resources)
|
||||||
|
on the wiki, too.
|
||||||
|
|
||||||
|
There is also a book available about [Building impressive presentations with impress.js](https://www.packtpub.com/building-impressive-presentations-with-impressjs/book) by Rakhitha Nimesh Ratnayake.
|
||||||
|
|
||||||
|
You may want to check out the sibling project [Impressionist](https://github.com/henrikingo/impressionist): a 3D GUI editor that can help you in creating impress.js presentations.
|
||||||
|
|
||||||
|
## Mailing list
|
||||||
|
|
||||||
|
You're welcome to ask impress.js related questions on the [impressionist-presentations](https://groups.google.com/forum/#!forum/impressionist-presentations) mailing list.
|
||||||
|
|
||||||
|
TODO: We should migrate to a different kind of mailing list
|
||||||
|
|
||||||
|
# Contributing
|
||||||
|
## Cloning impress.js locally
|
||||||
|
|
||||||
git clone --recursive https://github.com/impress/impress.js.git
|
git clone --recursive https://github.com/impress/impress.js.git
|
||||||
cd impress.js
|
cd impress.js
|
||||||
|
|
||||||
Note: For a minimal checkout, omit the `--recursive` option. This will leave out extra plugins.
|
Note: For a minimal checkout, omit the `--recursive` option. This will leave out extra plugins.
|
||||||
|
|
||||||
**Stable releases**
|
## Details
|
||||||
|
For developers, once you've made changes to the code, you should run these commands for testing:
|
||||||
|
|
||||||
New features and fixes are continuously merged into the master branch, which is what the above command will check out. For the latest stable release, see the [Github Releases page](https://github.com/impress/impress.js/releases).
|
npm install
|
||||||
|
npm run all
|
||||||
|
|
||||||
|
Note that running `firefox qunit_test_runner.html` is usually more informative than running `karma` with `npm run test`. They both run the same tests.
|
||||||
|
|
||||||
### Documentation
|
More info about the [src/](src/) directory can be found in [src/plugins/README.md](src/plugins/README.md).
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
TODO: Check that these requirements are still ok
|
||||||
|
* >= node 7.6
|
||||||
|
* npm
|
||||||
|
|
||||||
Reference documentation of core impress.js features and API you can find it in [DOCUMENTATION.md](DOCUMENTATION.md).
|
# REPOSITORY STRUCTURE
|
||||||
|
|
||||||
The [HTML source code](index.html) of the official [impress.js demo](http://impress.github.io/impress.js/) serves as a good example usage and contains comments explaining various features of impress.js. For more information about styling you can look into [CSS code](css/impress-demo.css) which shows how classes provided by impress.js can be used. Last but not least [JavaScript code of impress.js](js/impress.js) has some useful comments if you are interested in how everything works. Feel free to explore!
|
|
||||||
|
|
||||||
### Official demo
|
|
||||||
|
|
||||||
[impress.js demo](http://impress.github.io/impress.js/) by [@bartaz](http://twitter.com/bartaz)
|
|
||||||
|
|
||||||
### Examples and demos
|
|
||||||
|
|
||||||
The [Classic Slides](http://impress.github.io/impress.js/examples/classic-slides/) demo is targeted towards beginners, or can be used as a template for presentations that look like the traditional PowerPoint slide deck. Over time, it also grew into the example presentation that uses most of the features and addons available.
|
|
||||||
|
|
||||||
More examples and demos can be found on [Examples and demos wiki page](http://github.com/impress/impress.js/wiki/Examples-and-demos).
|
|
||||||
|
|
||||||
Feel free to add your own example presentations (or websites) there.
|
|
||||||
|
|
||||||
### Other tutorials and learning resources
|
|
||||||
|
|
||||||
If you want to learn even more there is a [list of tutorials and other learning resources](https://github.com/impress/impress.js/wiki/impress.js-tutorials-and-other-learning-resources)
|
|
||||||
on the wiki, too.
|
|
||||||
|
|
||||||
There is also a book available about [Building impressive presentations with impress.js](http://www.packtpub.com/building-impressive-presentations-with-impressjs/book) by Rakhitha Nimesh Ratnayake.
|
|
||||||
|
|
||||||
You may want to check out the sibling project [Impressionist](https://github.com/henrikingo/impressionist): a 3D GUI editor that can help you in creating impress.js presentations.
|
|
||||||
|
|
||||||
### Mailing list
|
|
||||||
|
|
||||||
You're welcome to ask impress.js related questions on the [impressionist-presentations](https://groups.google.com/forum/#!forum/impressionist-presentations) mailing list.
|
|
||||||
|
|
||||||
|
|
||||||
REPOSITORY STRUCTURE
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
* [index.html](index.html): This is the official impress.js demo, showcasing all of the features of the original impress.js, as well as some new plugins as we add them.
|
* [index.html](index.html): This is the official impress.js demo, showcasing all of the features of the original impress.js, as well as some new plugins as we add them.
|
||||||
* As already mentioned, this file is well commented and acts as the official tutorial.
|
* As already mentioned, this file is well commented and acts as the official tutorial.
|
||||||
@@ -86,53 +137,35 @@ REPOSITORY STRUCTURE
|
|||||||
* [build.js](build.js): Simple build file that creates `js/impress.js`. It also creates a minified version `impress.min.js`, but that one is not included in the github repository.
|
* [build.js](build.js): Simple build file that creates `js/impress.js`. It also creates a minified version `impress.min.js`, but that one is not included in the github repository.
|
||||||
* [package.json](build.js): An NPM package specification. This was mainly added so you can easily install [buildify](https://www.npmjs.com/package/buildify) and run `node build.js`. Other than the build process, which is really just doing roughly `cat src/impress.js src/plugins/*/*.js > js/impress.js`, and testing, `impress.js` itself doesn't depend on Node or any NPM modules.
|
* [package.json](build.js): An NPM package specification. This was mainly added so you can easily install [buildify](https://www.npmjs.com/package/buildify) and run `node build.js`. Other than the build process, which is really just doing roughly `cat src/impress.js src/plugins/*/*.js > js/impress.js`, and testing, `impress.js` itself doesn't depend on Node or any NPM modules.
|
||||||
|
|
||||||
WANT TO CONTRIBUTE?
|
TODO: Update repo structure once updating is complete
|
||||||
---------------------
|
|
||||||
|
|
||||||
For developers, once you've made changes to the code, you should run these commands for testing:
|
# About impress.js
|
||||||
|
## ABOUT THE NAME
|
||||||
|
|
||||||
npm install
|
impress.js name is [courtesy of @skuzniak](https://twitter.com/skuzniak/status/143627215165333504).
|
||||||
npm run all
|
|
||||||
|
|
||||||
Note that running `firefox qunit_test_runner.html` is usually more informative than running `karma` with `npm run test`. They both run the same tests.
|
It's an (un)fortunate coincidence that an Open/LibreOffice presentation tool is called Impress ;)
|
||||||
|
|
||||||
More info about the [src/](src/) directory can be found in [src/plugins/README.md](src/plugins/README.md).
|
## Reference API
|
||||||
|
|
||||||
### Requirements
|
See the [Reference API](/docs/DOCUMENTATION.md)
|
||||||
|
|
||||||
* >= node 7.6
|
TODO: Will be updated once full release of V3 is ready
|
||||||
* npm
|
|
||||||
|
## Browser support (again, but for devs)
|
||||||
|
|
||||||
|
impress.js uses the following CSS and JavaScript features
|
||||||
|
|
||||||
|
TODO: Update list below
|
||||||
|
|
||||||
|
* [DataSet API](https://caniuse.com/#search=dataset)
|
||||||
|
* [ClassList API](https://caniuse.com/#search=classlist)
|
||||||
|
* [CSS 3D Transforms](https://caniuse.com/#search=css%203d)
|
||||||
|
* [CSS Transitions](https://caniuse.com/#search=css%20transition)
|
||||||
|
|
||||||
|
|
||||||
ABOUT THE NAME
|
# Copyright and License
|
||||||
----------------
|
|
||||||
|
|
||||||
impress.js name is [courtesy of @skuzniak](http://twitter.com/skuzniak/status/143627215165333504).
|
Copyright 2011-2012 Bartek Szopka (@bartaz), 2016-2023 Henrik Ingo (@henrikingo) and [85+ other contributors](https://github.com/impress/impress.js/graphs/contributors)
|
||||||
|
|
||||||
It's an (un)fortunate coincidence that a Open/LibreOffice presentation tool is called Impress ;)
|
|
||||||
|
|
||||||
Reference API
|
|
||||||
--------------
|
|
||||||
|
|
||||||
See the [Reference API](DOCUMENTATION.md)
|
|
||||||
|
|
||||||
BROWSER SUPPORT
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
The design goal for impress.js has been to showcase awesome CSS3 features as found in modern browser versions. We also use some new DOM functionality, and specifically do not use jQuery or any other JavaScript libraries, nor our own functions, to support older browsers. In general, recent versions of Firefox and Chrome are known to work well. Reportedly IE now works too.
|
|
||||||
|
|
||||||
The typical use case for impress.js is to create presentations that you present from your own laptop, with a browser version you know works well. Some people also use impress.js successfully to embed animations or presentations in a web page, however, be aware that in this some of your visitors may not see the presentation correctly, or at all.
|
|
||||||
|
|
||||||
In particular, impress.js makes use of the following JS and CSS features:
|
|
||||||
|
|
||||||
* [DataSet API](http://caniuse.com/#search=dataset)
|
|
||||||
* [ClassList API](http://caniuse.com/#search=classlist)
|
|
||||||
* [CSS 3D Transforms](http://caniuse.com/#search=css%203d)
|
|
||||||
* [CSS Transitions](http://caniuse.com/#search=css%20transition)
|
|
||||||
|
|
||||||
COPYRIGHT AND LICENSE
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Copyright 2011-2012 Bartek Szopka (@bartaz), 2016-2023 Henrik Ingo (@henrikingo) and [70+ other contributors](https://github.com/impress/impress.js/graphs/contributors)
|
|
||||||
|
|
||||||
Released under the MIT [License](LICENSE)
|
Released under the MIT [License](LICENSE)
|
||||||
|
|||||||
75
build.js
75
build.js
@@ -1,75 +0,0 @@
|
|||||||
const fs = require('fs');
|
|
||||||
var ls = require('ls');
|
|
||||||
var path = require('path');
|
|
||||||
var Terser = require("terser");
|
|
||||||
|
|
||||||
var files = ['src/impress.js'];
|
|
||||||
// Libraries from src/lib
|
|
||||||
files.push('src/lib/gc.js', 'src/lib/util.js', 'src/lib/rotation.js')
|
|
||||||
// Plugins from src/plugins
|
|
||||||
files.push('src/plugins/autoplay/autoplay.js',
|
|
||||||
'src/plugins/blackout/blackout.js',
|
|
||||||
'src/plugins/extras/extras.js',
|
|
||||||
'src/plugins/form/form.js',
|
|
||||||
'src/plugins/fullscreen/fullscreen.js',
|
|
||||||
'src/plugins/goto/goto.js',
|
|
||||||
'src/plugins/bookmark/bookmark.js',
|
|
||||||
'src/plugins/help/help.js',
|
|
||||||
'src/plugins/impressConsole/impressConsole.js',
|
|
||||||
'src/plugins/media/media.js',
|
|
||||||
'src/plugins/mobile/mobile.js',
|
|
||||||
'src/plugins/mouse-timeout/mouse-timeout.js',
|
|
||||||
'src/plugins/navigation/navigation.js',
|
|
||||||
'src/plugins/navigation-ui/navigation-ui.js',
|
|
||||||
'src/plugins/progress/progress.js',
|
|
||||||
'src/plugins/rel/rel.js',
|
|
||||||
'src/plugins/resize/resize.js',
|
|
||||||
'src/plugins/skip/skip.js',
|
|
||||||
'src/plugins/stop/stop.js',
|
|
||||||
'src/plugins/substep/substep.js',
|
|
||||||
'src/plugins/touch/touch.js',
|
|
||||||
'src/plugins/toolbar/toolbar.js')
|
|
||||||
var output = files.map((f)=>{
|
|
||||||
return fs.readFileSync(f).toString();
|
|
||||||
}).join('\n')
|
|
||||||
|
|
||||||
var filename = 'js/impress.js';
|
|
||||||
fs.writeFileSync(filename, '// This file was automatically generated from files in src/ directory.\n\n' + output)
|
|
||||||
console.log(filename);
|
|
||||||
|
|
||||||
// terser --compress --mangle --comments '/^!/' --source-map --output js/impress.min.js js/impress.js
|
|
||||||
var code = fs.readFileSync('js/impress.js').toString();
|
|
||||||
var options = {
|
|
||||||
sourceMap: {
|
|
||||||
filename: 'js/impress.js',
|
|
||||||
url: 'js/impress.min.js.map'
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
comments: /^!/
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var result = Terser.minify({'js/impress.js': code}, options);
|
|
||||||
|
|
||||||
filename = 'js/impress.min.js';
|
|
||||||
fs.writeFileSync(filename, result.code);
|
|
||||||
console.log(filename);
|
|
||||||
filename = 'js/impress.min.js.map';
|
|
||||||
fs.writeFileSync(filename, result.map);
|
|
||||||
console.log(filename);
|
|
||||||
|
|
||||||
/* Auto generate an index.html that lists all the directories under examples/
|
|
||||||
* This is useful for gh-pages, so you can link to http://impress.github.io/impress.js/examples
|
|
||||||
*/
|
|
||||||
var html_list = '<ul><br />\n'
|
|
||||||
ls( 'examples/*', { type: 'dir' }).forEach(function(dir) {
|
|
||||||
html_list += ' <li><a href="' + dir['file'] + '/">' + dir['name'] + '</a></li>\n';
|
|
||||||
});
|
|
||||||
html_list += '</ul>\n'
|
|
||||||
|
|
||||||
var html = '<html>\n<head>\n<title>Example presentations</title>\n</head>\n<body>'
|
|
||||||
html += '<h1>Example presentations</h1>\n' + html_list
|
|
||||||
html += '</body>\n</html>'
|
|
||||||
|
|
||||||
filename = path.resolve(__dirname, 'examples', 'index.html');
|
|
||||||
fs.writeFileSync(filename, html);
|
|
||||||
console.log(filename);
|
|
||||||
2
docs/core/addElements.md
Normal file
2
docs/core/addElements.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# Adding Elements to impress
|
||||||
|
You can add elements to impress by calling the `impress.addElement` function.
|
||||||
8922
package-lock.json
generated
8922
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "impress.js",
|
"name": "impress.js",
|
||||||
"version": "1.1.0",
|
"version": "3.0.0",
|
||||||
"description": "It's a presentation framework based on the power of CSS3 transforms and transitions in modern browsers and inspired by the idea behind prezi.com.",
|
"description": "It's a presentation framework based on the power of CSS3 transforms and transitions in modern browsers and inspired by the idea behind prezi.com.",
|
||||||
"main": "js/impress.js",
|
"main": "js/impress.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -24,15 +24,16 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"all": "npm run build && npm run test && npm run lint",
|
"all": "npm run build && npm run test && npm run lint",
|
||||||
"build": "node build.js",
|
"build": "node build.js",
|
||||||
"lint": "npm exec -- jshint src test/*.js && npm exec -- jscs src test/*.js",
|
"lint": "npm exec -- eslint src test",
|
||||||
"new-lint": "npm exec -- eslint src test",
|
|
||||||
"test": "npm exec -- karma start --log-level debug --single-run=true"
|
"test": "npm exec -- karma start --log-level debug --single-run=true"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^6.8.0",
|
"@typescript-eslint/eslint-plugin": "^6.18.0",
|
||||||
"jscs": "^3.0.7",
|
"@typescript-eslint/parser": "^6.18.0",
|
||||||
|
"eslint": "^8.56.0",
|
||||||
|
"jscs": "^2.1.1",
|
||||||
"jshint": "^2.11.0",
|
"jshint": "^2.11.0",
|
||||||
"karma": "^4.4.1",
|
"karma": "^6.4.2",
|
||||||
"karma-chrome-launcher": "^3.1.0",
|
"karma-chrome-launcher": "^3.1.0",
|
||||||
"karma-firefox-launcher": "^1.3.0",
|
"karma-firefox-launcher": "^1.3.0",
|
||||||
"karma-qunit": "^4.0.0",
|
"karma-qunit": "^4.0.0",
|
||||||
@@ -41,6 +42,7 @@
|
|||||||
"qunit": "^2.9.3",
|
"qunit": "^2.9.3",
|
||||||
"qunit-assert-close": "^2.1.2",
|
"qunit-assert-close": "^2.1.2",
|
||||||
"syn": "^0.14.1",
|
"syn": "^0.14.1",
|
||||||
"terser": "^4.6.7"
|
"terser": "^4.6.7",
|
||||||
|
"typescript": "^5.3.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
75
src/build.js
Normal file
75
src/build.js
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
const fs = require( 'fs' );
|
||||||
|
var ls = require( 'ls' );
|
||||||
|
var path = require( 'path' );
|
||||||
|
var Terser = require( 'terser' );
|
||||||
|
|
||||||
|
var files = ['src/impress.js'];
|
||||||
|
// Libraries from src/lib
|
||||||
|
files.push( 'src/lib/gc.js', 'src/lib/util.js', 'src/lib/rotation.js' );
|
||||||
|
// Plugins from src/plugins
|
||||||
|
files.push(
|
||||||
|
'src/plugins/autoplay/autoplay.js',
|
||||||
|
'src/plugins/blackout/blackout.js',
|
||||||
|
'src/plugins/extras/extras.js',
|
||||||
|
'src/plugins/form/form.js',
|
||||||
|
'src/plugins/fullscreen/fullscreen.js',
|
||||||
|
'src/plugins/goto/goto.js',
|
||||||
|
'src/plugins/bookmark/bookmark.js',
|
||||||
|
'src/plugins/help/help.js',
|
||||||
|
'src/plugins/impressConsole/impressConsole.js',
|
||||||
|
'src/plugins/media/media.js',
|
||||||
|
'src/plugins/mobile/mobile.js',
|
||||||
|
'src/plugins/mouse-timeout/mouse-timeout.js',
|
||||||
|
'src/plugins/navigation/navigation.js',
|
||||||
|
'src/plugins/navigation-ui/navigation-ui.js',
|
||||||
|
'src/plugins/progress/progress.js',
|
||||||
|
'src/plugins/rel/rel.js',
|
||||||
|
'src/plugins/resize/resize.js',
|
||||||
|
'src/plugins/skip/skip.js',
|
||||||
|
'src/plugins/stop/stop.js',
|
||||||
|
'src/plugins/substep/substep.js',
|
||||||
|
'src/plugins/touch/touch.js',
|
||||||
|
'src/plugins/toolbar/toolbar.js'
|
||||||
|
);
|
||||||
|
var output = files.map( ( f ) => fs.readFileSync( f ).toString() ).join( '\n' );
|
||||||
|
|
||||||
|
var filename = 'js/impress.js';
|
||||||
|
fs.writeFileSync( filename, '// This file was automatically generated from files in src/ directory.\n\n' + output );
|
||||||
|
console.log( filename );
|
||||||
|
|
||||||
|
// terser --compress --mangle --comments '/^!/' --source-map --output js/impress.min.js js/impress.js
|
||||||
|
var code = fs.readFileSync( 'js/impress.js' ).toString();
|
||||||
|
var options = {
|
||||||
|
sourceMap: {
|
||||||
|
filename: 'js/impress.js',
|
||||||
|
url: 'js/impress.min.js.map'
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
comments: /^!/
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var result = Terser.minify( { 'js/impress.js': code }, options );
|
||||||
|
|
||||||
|
filename = 'js/impress.min.js';
|
||||||
|
fs.writeFileSync( filename, result.code );
|
||||||
|
console.log( filename );
|
||||||
|
filename = 'js/impress.min.js.map';
|
||||||
|
fs.writeFileSync( filename, result.map );
|
||||||
|
console.log( filename );
|
||||||
|
|
||||||
|
// Auto generate an index.html that lists all the directories under examples/
|
||||||
|
// This is useful for gh-pages, so you can link to http://impress.github.io/impress.js/examples
|
||||||
|
//
|
||||||
|
var html_list = '<ul><br />\n';
|
||||||
|
ls( 'examples/*', { type: 'dir' } ).forEach( function( dir ) {
|
||||||
|
html_list += ' <li><a href="' + dir.file + '/">' + dir.name + '</a></li>\n';
|
||||||
|
} );
|
||||||
|
html_list += '</ul>\n';
|
||||||
|
|
||||||
|
var html = '<html>\n<head>\n<title>Example presentations</title>\n</head>\n<body>';
|
||||||
|
html += '<h1>Example presentations</h1>\n' + html_list;
|
||||||
|
html += '</body>\n</html>';
|
||||||
|
|
||||||
|
filename = path.resolve( __dirname, 'examples', 'index.html' );
|
||||||
|
fs.writeFileSync( filename, html );
|
||||||
|
console.log( filename );
|
||||||
1110
src/impress.js
1110
src/impress.js
File diff suppressed because it is too large
Load Diff
925
src/impress.old.js
Normal file
925
src/impress.old.js
Normal file
@@ -0,0 +1,925 @@
|
|||||||
|
/*! Licensed under MIT License - http://github.com/impress/impress.js */
|
||||||
|
/**
|
||||||
|
* 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-2023 Henrik Ingo (@henrikingo)
|
||||||
|
* and 70+ other contributors
|
||||||
|
*
|
||||||
|
* Released under the MIT License.
|
||||||
|
*
|
||||||
|
* ------------------------------------------------
|
||||||
|
* author: Bartek Szopka, Henrik Ingo
|
||||||
|
* version: 2.0.0
|
||||||
|
* url: http://impress.js.org
|
||||||
|
* source: http://github.com/impress/impress.js/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// You are one of those who like to know how things work inside?
|
||||||
|
// Let me show you the cogs that make impress.js run...
|
||||||
|
( function( document, window ) {
|
||||||
|
"use strict";
|
||||||
|
var lib;
|
||||||
|
|
||||||
|
// HELPER FUNCTIONS
|
||||||
|
|
||||||
|
// `pfx` is a function that takes a standard CSS property name as a parameter
|
||||||
|
// and returns it's prefixed version valid for current browser it runs in.
|
||||||
|
// The code is heavily inspired by Modernizr http://www.modernizr.com/
|
||||||
|
var pfx = ( function() {
|
||||||
|
|
||||||
|
var style = document.createElement( "dummy" ).style,
|
||||||
|
prefixes = "Webkit Moz O ms Khtml".split( " " ),
|
||||||
|
memory = {};
|
||||||
|
|
||||||
|
return function( prop ) {
|
||||||
|
if ( typeof memory[ prop ] === "undefined" ) {
|
||||||
|
|
||||||
|
var ucProp = prop.charAt( 0 ).toUpperCase() + prop.substr( 1 ),
|
||||||
|
props = ( prop + " " + prefixes.join( ucProp + " " ) + ucProp ).split( " " );
|
||||||
|
|
||||||
|
memory[ prop ] = null;
|
||||||
|
for ( var i in props ) {
|
||||||
|
if ( style[ props[ i ] ] !== undefined ) {
|
||||||
|
memory[ prop ] = props[ i ];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return memory[ prop ];
|
||||||
|
};
|
||||||
|
|
||||||
|
} )();
|
||||||
|
|
||||||
|
var validateOrder = function( order, fallback ) {
|
||||||
|
var validChars = "xyz";
|
||||||
|
var returnStr = "";
|
||||||
|
if ( typeof order === "string" ) {
|
||||||
|
for ( var i in order.split( "" ) ) {
|
||||||
|
if ( validChars.indexOf( order[ i ] ) >= 0 ) {
|
||||||
|
returnStr += order[ i ];
|
||||||
|
|
||||||
|
// Each of x,y,z can be used only once.
|
||||||
|
validChars = validChars.split( order[ i ] ).join( "" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( returnStr ) {
|
||||||
|
return returnStr;
|
||||||
|
} else if ( fallback !== undefined ) {
|
||||||
|
return fallback;
|
||||||
|
} else {
|
||||||
|
return "xyz";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// `css` function applies the styles given in `props` object to the element
|
||||||
|
// given as `el`. It runs all property names through `pfx` function to make
|
||||||
|
// sure proper prefixed version of the property is used.
|
||||||
|
var css = function( el, props ) {
|
||||||
|
var key, pkey;
|
||||||
|
for ( key in props ) {
|
||||||
|
if ( props.hasOwnProperty( key ) ) {
|
||||||
|
pkey = pfx( key );
|
||||||
|
if ( pkey !== null ) {
|
||||||
|
el.style[ pkey ] = props[ key ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
||||||
|
// `translate` builds a translate transform string for given data.
|
||||||
|
var translate = function( t ) {
|
||||||
|
return " translate3d(" + t.x + "px," + t.y + "px," + t.z + "px) ";
|
||||||
|
};
|
||||||
|
|
||||||
|
// `rotate` builds a rotate transform string for given data.
|
||||||
|
// By default the rotations are in X Y Z order that can be reverted by passing `true`
|
||||||
|
// as second parameter.
|
||||||
|
var rotate = function( r, revert ) {
|
||||||
|
var order = r.order ? r.order : "xyz";
|
||||||
|
var css = "";
|
||||||
|
var axes = order.split( "" );
|
||||||
|
if ( revert ) {
|
||||||
|
axes = axes.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( var i = 0; i < axes.length; i++ ) {
|
||||||
|
css += " rotate" + axes[ i ].toUpperCase() + "(" + r[ axes[ i ] ] + "deg)";
|
||||||
|
}
|
||||||
|
return css;
|
||||||
|
};
|
||||||
|
|
||||||
|
// `scale` builds a scale transform string for given data.
|
||||||
|
var scale = function( s ) {
|
||||||
|
return " scale(" + s + ") ";
|
||||||
|
};
|
||||||
|
|
||||||
|
// `computeWindowScale` counts the scale factor between window size and size
|
||||||
|
// defined for the presentation in the config.
|
||||||
|
var computeWindowScale = function( config ) {
|
||||||
|
var hScale = window.innerHeight / config.height,
|
||||||
|
wScale = window.innerWidth / config.width,
|
||||||
|
scale = hScale > wScale ? wScale : hScale;
|
||||||
|
|
||||||
|
if ( config.maxScale && scale > config.maxScale ) {
|
||||||
|
scale = config.maxScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( config.minScale && scale < config.minScale ) {
|
||||||
|
scale = config.minScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
return scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
// CHECK SUPPORT
|
||||||
|
var body = document.body;
|
||||||
|
var impressSupported =
|
||||||
|
|
||||||
|
// Browser should support CSS 3D transtorms
|
||||||
|
( pfx( "perspective" ) !== null ) &&
|
||||||
|
|
||||||
|
// And `classList` and `dataset` APIs
|
||||||
|
( body.classList ) &&
|
||||||
|
( body.dataset );
|
||||||
|
|
||||||
|
if ( !impressSupported ) {
|
||||||
|
|
||||||
|
// We can't be sure that `classList` is supported
|
||||||
|
body.className += " impress-not-supported ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// GLOBALS AND DEFAULTS
|
||||||
|
|
||||||
|
// This is where the root elements of all impress.js instances will be kept.
|
||||||
|
// Yes, this means you can have more than one instance on a page, but I'm not
|
||||||
|
// sure if it makes any sense in practice ;)
|
||||||
|
var roots = {};
|
||||||
|
|
||||||
|
var preInitPlugins = [];
|
||||||
|
var preStepLeavePlugins = [];
|
||||||
|
|
||||||
|
// Some default config values.
|
||||||
|
var defaults = {
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
maxScale: 3,
|
||||||
|
minScale: 0,
|
||||||
|
|
||||||
|
perspective: 1000,
|
||||||
|
|
||||||
|
transitionDuration: 1000
|
||||||
|
};
|
||||||
|
|
||||||
|
// Configuration options
|
||||||
|
var config = null;
|
||||||
|
|
||||||
|
// It's just an empty function ... and a useless comment.
|
||||||
|
var empty = function() { return false; };
|
||||||
|
|
||||||
|
// IMPRESS.JS API
|
||||||
|
|
||||||
|
// And that's where interesting things will start to happen.
|
||||||
|
// It's the core `impress` function that returns the impress.js API
|
||||||
|
// for a presentation based on the element with given id ("impress"
|
||||||
|
// by default).
|
||||||
|
var impress = window.impress = function( rootId ) {
|
||||||
|
// If impress.js is not supported by the browser return a dummy API
|
||||||
|
// it may not be a perfect solution but we return early and avoid
|
||||||
|
// running code that may use features not implemented in the browser.
|
||||||
|
if ( !impressSupported ) {
|
||||||
|
return {
|
||||||
|
init: empty,
|
||||||
|
goto: empty,
|
||||||
|
prev: empty,
|
||||||
|
next: empty,
|
||||||
|
swipe: empty,
|
||||||
|
tear: empty,
|
||||||
|
lib: {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
rootId = rootId || "impress";
|
||||||
|
|
||||||
|
// If given root is already initialized just return the API
|
||||||
|
if ( roots[ "impress-root-" + rootId ] ) {
|
||||||
|
return roots[ "impress-root-" + rootId ];
|
||||||
|
}
|
||||||
|
|
||||||
|
// The gc library depends on being initialized before we do any changes to DOM.
|
||||||
|
lib = initLibraries( rootId );
|
||||||
|
|
||||||
|
body.classList.remove( "impress-not-supported" );
|
||||||
|
body.classList.add( "impress-supported" );
|
||||||
|
|
||||||
|
// Data of all presentation steps
|
||||||
|
var stepsData = {};
|
||||||
|
|
||||||
|
// Element of currently active step
|
||||||
|
var activeStep = null;
|
||||||
|
|
||||||
|
// Current state (position, rotation and scale) of the presentation
|
||||||
|
var currentState = null;
|
||||||
|
|
||||||
|
// Array of step elements
|
||||||
|
var steps = null;
|
||||||
|
|
||||||
|
// Scale factor of the browser window
|
||||||
|
var windowScale = null;
|
||||||
|
|
||||||
|
// Root presentation elements
|
||||||
|
var root = lib.util.byId( rootId );
|
||||||
|
var canvas = document.createElement( "div" );
|
||||||
|
|
||||||
|
var initialized = false;
|
||||||
|
|
||||||
|
// STEP EVENTS
|
||||||
|
//
|
||||||
|
// There are currently two step events triggered by impress.js
|
||||||
|
// `impress:stepenter` is triggered when the step is shown on the
|
||||||
|
// screen (the transition from the previous one is finished) and
|
||||||
|
// `impress:stepleave` is triggered when the step is left (the
|
||||||
|
// transition to next step just starts).
|
||||||
|
|
||||||
|
// Reference to last entered step
|
||||||
|
var lastEntered = null;
|
||||||
|
|
||||||
|
// `onStepEnter` is called whenever the step element is entered
|
||||||
|
// but the event is triggered only if the step is different than
|
||||||
|
// last entered step.
|
||||||
|
// We sometimes call `goto`, and therefore `onStepEnter`, just to redraw a step, such as
|
||||||
|
// after screen resize. In this case - more precisely, in any case - we trigger a
|
||||||
|
// `impress:steprefresh` event.
|
||||||
|
var onStepEnter = function( step ) {
|
||||||
|
if ( lastEntered !== step ) {
|
||||||
|
lib.util.triggerEvent( step, "impress:stepenter" );
|
||||||
|
lastEntered = step;
|
||||||
|
}
|
||||||
|
lib.util.triggerEvent( step, "impress:steprefresh" );
|
||||||
|
};
|
||||||
|
|
||||||
|
// `onStepLeave` is called whenever the currentStep element is left
|
||||||
|
// but the event is triggered only if the currentStep is the same as
|
||||||
|
// lastEntered step.
|
||||||
|
var onStepLeave = function( currentStep, nextStep ) {
|
||||||
|
if ( lastEntered === currentStep ) {
|
||||||
|
lib.util.triggerEvent( currentStep, "impress:stepleave", { next: nextStep } );
|
||||||
|
lastEntered = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// `initStep` initializes given step element by reading data from its
|
||||||
|
// data attributes and setting correct styles.
|
||||||
|
var initStep = function( el, idx ) {
|
||||||
|
var data = el.dataset,
|
||||||
|
step = {
|
||||||
|
translate: {
|
||||||
|
x: lib.util.toNumberAdvanced( data.x ),
|
||||||
|
y: lib.util.toNumberAdvanced( data.y ),
|
||||||
|
z: lib.util.toNumberAdvanced( data.z )
|
||||||
|
},
|
||||||
|
rotate: {
|
||||||
|
x: lib.util.toNumber( data.rotateX ),
|
||||||
|
y: lib.util.toNumber( data.rotateY ),
|
||||||
|
z: lib.util.toNumber( data.rotateZ || data.rotate ),
|
||||||
|
order: validateOrder( data.rotateOrder )
|
||||||
|
},
|
||||||
|
scale: lib.util.toNumber( data.scale, 1 ),
|
||||||
|
transitionDuration: lib.util.toNumber(
|
||||||
|
data.transitionDuration, config.transitionDuration
|
||||||
|
),
|
||||||
|
el: el
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( !el.id ) {
|
||||||
|
el.id = "step-" + ( idx + 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
stepsData[ "impress-" + el.id ] = step;
|
||||||
|
|
||||||
|
css( el, {
|
||||||
|
position: "absolute",
|
||||||
|
transform: "translate(-50%,-50%)" +
|
||||||
|
translate( step.translate ) +
|
||||||
|
rotate( step.rotate ) +
|
||||||
|
scale( step.scale ),
|
||||||
|
transformStyle: "preserve-3d"
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize all steps.
|
||||||
|
// Read the data-* attributes, store in internal stepsData, and render with CSS.
|
||||||
|
var initAllSteps = function() {
|
||||||
|
steps = lib.util.$$( ".step", root );
|
||||||
|
steps.forEach( initStep );
|
||||||
|
};
|
||||||
|
|
||||||
|
// Build configuration from root and defaults
|
||||||
|
var buildConfig = function() {
|
||||||
|
var rootData = root.dataset;
|
||||||
|
return {
|
||||||
|
width: lib.util.toNumber( rootData.width, defaults.width ),
|
||||||
|
height: lib.util.toNumber( rootData.height, defaults.height ),
|
||||||
|
maxScale: lib.util.toNumber( rootData.maxScale, defaults.maxScale ),
|
||||||
|
minScale: lib.util.toNumber( rootData.minScale, defaults.minScale ),
|
||||||
|
perspective: lib.util.toNumber( rootData.perspective, defaults.perspective ),
|
||||||
|
transitionDuration: lib.util.toNumber(
|
||||||
|
rootData.transitionDuration, defaults.transitionDuration
|
||||||
|
)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// `init` API function that initializes (and runs) the presentation.
|
||||||
|
var init = function() {
|
||||||
|
if ( initialized ) { return; }
|
||||||
|
|
||||||
|
// Initialize the configuration object, so it can be used by pre-init plugins.
|
||||||
|
config = buildConfig();
|
||||||
|
execPreInitPlugins( root );
|
||||||
|
|
||||||
|
// First we set up the viewport for mobile devices.
|
||||||
|
// For some reason iPad goes nuts when it is not done properly.
|
||||||
|
var meta = lib.util.$( "meta[name='viewport']" ) || document.createElement( "meta" );
|
||||||
|
meta.content = "width=device-width, minimum-scale=1, maximum-scale=1, user-scalable=no";
|
||||||
|
if ( meta.parentNode !== document.head ) {
|
||||||
|
meta.name = "viewport";
|
||||||
|
document.head.appendChild( meta );
|
||||||
|
}
|
||||||
|
|
||||||
|
windowScale = computeWindowScale( config );
|
||||||
|
|
||||||
|
// Wrap steps with "canvas" element
|
||||||
|
lib.util.arrayify( root.childNodes ).forEach( function( el ) {
|
||||||
|
canvas.appendChild( el );
|
||||||
|
} );
|
||||||
|
root.appendChild( canvas );
|
||||||
|
|
||||||
|
// Set initial styles
|
||||||
|
document.documentElement.style.height = "100%";
|
||||||
|
|
||||||
|
css( body, {
|
||||||
|
height: "100%",
|
||||||
|
overflow: "hidden"
|
||||||
|
} );
|
||||||
|
|
||||||
|
var rootStyles = {
|
||||||
|
position: "absolute",
|
||||||
|
transformOrigin: "top left",
|
||||||
|
transition: "all 0s ease-in-out",
|
||||||
|
transformStyle: "preserve-3d"
|
||||||
|
};
|
||||||
|
|
||||||
|
css( root, rootStyles );
|
||||||
|
css( root, {
|
||||||
|
top: "50%",
|
||||||
|
left: "50%",
|
||||||
|
perspective: ( config.perspective / windowScale ) + "px",
|
||||||
|
transform: scale( windowScale )
|
||||||
|
} );
|
||||||
|
css( canvas, rootStyles );
|
||||||
|
|
||||||
|
body.classList.remove( "impress-disabled" );
|
||||||
|
body.classList.add( "impress-enabled" );
|
||||||
|
|
||||||
|
// Get and init steps
|
||||||
|
initAllSteps();
|
||||||
|
|
||||||
|
// Set a default initial state of the canvas
|
||||||
|
currentState = {
|
||||||
|
translate: { x: 0, y: 0, z: 0 },
|
||||||
|
rotate: { x: 0, y: 0, z: 0, order: "xyz" },
|
||||||
|
scale: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
lib.util.triggerEvent( root, "impress:init",
|
||||||
|
{ api: roots[ "impress-root-" + rootId ] } );
|
||||||
|
};
|
||||||
|
|
||||||
|
// `getStep` is a helper function that returns a step element defined by parameter.
|
||||||
|
// If a number is given, step with index given by the number is returned, if a string
|
||||||
|
// is given step element with such id is returned, if DOM element is given it is returned
|
||||||
|
// if it is a correct step element.
|
||||||
|
var getStep = function( step ) {
|
||||||
|
if ( typeof step === "number" ) {
|
||||||
|
step = step < 0 ? steps[ steps.length + step ] : steps[ step ];
|
||||||
|
} else if ( typeof step === "string" ) {
|
||||||
|
step = lib.util.byId( step );
|
||||||
|
}
|
||||||
|
return ( step && step.id && stepsData[ "impress-" + step.id ] ) ? step : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used to reset timeout for `impress:stepenter` event
|
||||||
|
var stepEnterTimeout = null;
|
||||||
|
|
||||||
|
// `goto` API function that moves to step given as `el` parameter (by index, id or element).
|
||||||
|
// `duration` optionally given as second parameter, is the transition duration in css.
|
||||||
|
// `reason` is the string "next", "prev" or "goto" (default) and will be made available to
|
||||||
|
// preStepLeave plugins.
|
||||||
|
// `origEvent` may contain event that caused the call to goto, such as a key press event
|
||||||
|
var goto = function( el, duration, reason, origEvent ) {
|
||||||
|
reason = reason || "goto";
|
||||||
|
origEvent = origEvent || null;
|
||||||
|
|
||||||
|
if ( !initialized ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-execute initAllSteps for each transition. This allows to edit step attributes
|
||||||
|
// dynamically, such as change their coordinates, or even remove or add steps, and have
|
||||||
|
// that change apply when goto() is called.
|
||||||
|
initAllSteps();
|
||||||
|
|
||||||
|
if ( !( el = getStep( el ) ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sometimes it's possible to trigger focus on first link with some keyboard action.
|
||||||
|
// Browser in such a case tries to scroll the page to make this element visible
|
||||||
|
// (even that body overflow is set to hidden) and it breaks our careful positioning.
|
||||||
|
//
|
||||||
|
// So, as a lousy (and lazy) workaround we will make the page scroll back to the top
|
||||||
|
// whenever slide is selected
|
||||||
|
//
|
||||||
|
// If you are reading this and know any better way to handle it, I'll be glad to hear
|
||||||
|
// about it!
|
||||||
|
window.scrollTo( 0, 0 );
|
||||||
|
|
||||||
|
var step = stepsData[ "impress-" + el.id ];
|
||||||
|
duration = ( duration !== undefined ? duration : step.transitionDuration );
|
||||||
|
|
||||||
|
// If we are in fact moving to another step, start with executing the registered
|
||||||
|
// preStepLeave plugins.
|
||||||
|
if ( activeStep && activeStep !== el ) {
|
||||||
|
var event = { target: activeStep, detail: {} };
|
||||||
|
event.detail.next = el;
|
||||||
|
event.detail.transitionDuration = duration;
|
||||||
|
event.detail.reason = reason;
|
||||||
|
if ( origEvent ) {
|
||||||
|
event.origEvent = origEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( execPreStepLeavePlugins( event ) === false ) {
|
||||||
|
|
||||||
|
// PreStepLeave plugins are allowed to abort the transition altogether, by
|
||||||
|
// returning false.
|
||||||
|
// see stop and substep plugins for an example of doing just that
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugins are allowed to change the detail values
|
||||||
|
el = event.detail.next;
|
||||||
|
step = stepsData[ "impress-" + el.id ];
|
||||||
|
duration = event.detail.transitionDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( activeStep ) {
|
||||||
|
activeStep.classList.remove( "active" );
|
||||||
|
body.classList.remove( "impress-on-" + activeStep.id );
|
||||||
|
}
|
||||||
|
el.classList.add( "active" );
|
||||||
|
|
||||||
|
body.classList.add( "impress-on-" + el.id );
|
||||||
|
|
||||||
|
// Compute target state of the canvas based on given step
|
||||||
|
var target = {
|
||||||
|
rotate: {
|
||||||
|
x: -step.rotate.x,
|
||||||
|
y: -step.rotate.y,
|
||||||
|
z: -step.rotate.z,
|
||||||
|
order: step.rotate.order
|
||||||
|
},
|
||||||
|
translate: {
|
||||||
|
x: -step.translate.x,
|
||||||
|
y: -step.translate.y,
|
||||||
|
z: -step.translate.z
|
||||||
|
},
|
||||||
|
scale: 1 / step.scale
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if the transition is zooming in or not.
|
||||||
|
//
|
||||||
|
// This information is used to alter the transition style:
|
||||||
|
// when we are zooming in - we start with move and rotate transition
|
||||||
|
// and the scaling is delayed, but when we are zooming out we start
|
||||||
|
// with scaling down and move and rotation are delayed.
|
||||||
|
var zoomin = target.scale >= currentState.scale;
|
||||||
|
|
||||||
|
duration = lib.util.toNumber( duration, config.transitionDuration );
|
||||||
|
var delay = ( duration / 2 );
|
||||||
|
|
||||||
|
// If the same step is re-selected, force computing window scaling,
|
||||||
|
// because it is likely to be caused by window resize
|
||||||
|
if ( el === activeStep ) {
|
||||||
|
windowScale = computeWindowScale( config );
|
||||||
|
}
|
||||||
|
|
||||||
|
var targetScale = target.scale * windowScale;
|
||||||
|
|
||||||
|
// Trigger leave of currently active element (if it's not the same step again)
|
||||||
|
if ( activeStep && activeStep !== el ) {
|
||||||
|
onStepLeave( activeStep, el );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we alter transforms of `root` and `canvas` to trigger transitions.
|
||||||
|
//
|
||||||
|
// And here is why there are two elements: `root` and `canvas` - they are
|
||||||
|
// being animated separately:
|
||||||
|
// `root` is used for scaling and `canvas` for translate and rotations.
|
||||||
|
// Transitions on them are triggered with different delays (to make
|
||||||
|
// visually nice and "natural" looking transitions), so we need to know
|
||||||
|
// that both of them are finished.
|
||||||
|
css( root, {
|
||||||
|
|
||||||
|
// To keep the perspective look similar for different scales
|
||||||
|
// we need to "scale" the perspective, too
|
||||||
|
// For IE 11 support we must specify perspective independent
|
||||||
|
// of transform.
|
||||||
|
perspective: ( config.perspective / targetScale ) + "px",
|
||||||
|
transform: scale( targetScale ),
|
||||||
|
transitionDuration: duration + "ms",
|
||||||
|
transitionDelay: ( zoomin ? delay : 0 ) + "ms"
|
||||||
|
} );
|
||||||
|
|
||||||
|
css( canvas, {
|
||||||
|
transform: rotate( target.rotate, true ) + translate( target.translate ),
|
||||||
|
transitionDuration: duration + "ms",
|
||||||
|
transitionDelay: ( zoomin ? 0 : delay ) + "ms"
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Here is a tricky part...
|
||||||
|
//
|
||||||
|
// If there is no change in scale or no change in rotation and translation, it means
|
||||||
|
// there was actually no delay - because there was no transition on `root` or `canvas`
|
||||||
|
// elements. We want to trigger `impress:stepenter` event in the correct moment, so
|
||||||
|
// here we compare the current and target values to check if delay should be taken into
|
||||||
|
// account.
|
||||||
|
//
|
||||||
|
// I know that this `if` statement looks scary, but it's pretty simple when you know
|
||||||
|
// what is going on - it's simply comparing all the values.
|
||||||
|
if ( currentState.scale === target.scale ||
|
||||||
|
( currentState.rotate.x === target.rotate.x &&
|
||||||
|
currentState.rotate.y === target.rotate.y &&
|
||||||
|
currentState.rotate.z === target.rotate.z &&
|
||||||
|
currentState.translate.x === target.translate.x &&
|
||||||
|
currentState.translate.y === target.translate.y &&
|
||||||
|
currentState.translate.z === target.translate.z ) ) {
|
||||||
|
delay = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store current state
|
||||||
|
currentState = target;
|
||||||
|
activeStep = el;
|
||||||
|
|
||||||
|
// And here is where we trigger `impress:stepenter` event.
|
||||||
|
// We simply set up a timeout to fire it taking transition duration (and possible delay)
|
||||||
|
// into account.
|
||||||
|
//
|
||||||
|
// I really wanted to make it in more elegant way. The `transitionend` event seemed to
|
||||||
|
// be the best way to do it, but the fact that I'm using transitions on two separate
|
||||||
|
// elements and that the `transitionend` event is only triggered when there was a
|
||||||
|
// transition (change in the values) caused some bugs and made the code really
|
||||||
|
// complicated, cause I had to handle all the conditions separately. And it still
|
||||||
|
// needed a `setTimeout` fallback for the situations when there is no transition at all.
|
||||||
|
// So I decided that I'd rather make the code simpler than use shiny new
|
||||||
|
// `transitionend`.
|
||||||
|
//
|
||||||
|
// If you want learn something interesting and see how it was done with `transitionend`
|
||||||
|
// go back to version 0.5.2 of impress.js:
|
||||||
|
// http://github.com/bartaz/impress.js/blob/0.5.2/js/impress.js
|
||||||
|
window.clearTimeout( stepEnterTimeout );
|
||||||
|
stepEnterTimeout = window.setTimeout( function() {
|
||||||
|
onStepEnter( activeStep );
|
||||||
|
}, duration + delay );
|
||||||
|
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
||||||
|
// `prev` API function goes to previous step (in document order)
|
||||||
|
// `event` is optional, may contain the event that caused the need to call prev()
|
||||||
|
var prev = function( origEvent ) {
|
||||||
|
var prev = steps.indexOf( activeStep ) - 1;
|
||||||
|
prev = prev >= 0 ? steps[ prev ] : steps[ steps.length - 1 ];
|
||||||
|
|
||||||
|
return goto( prev, undefined, "prev", origEvent );
|
||||||
|
};
|
||||||
|
|
||||||
|
// `next` API function goes to next step (in document order)
|
||||||
|
// `event` is optional, may contain the event that caused the need to call next()
|
||||||
|
var next = function( origEvent ) {
|
||||||
|
var next = steps.indexOf( activeStep ) + 1;
|
||||||
|
next = next < steps.length ? steps[ next ] : steps[ 0 ];
|
||||||
|
|
||||||
|
return goto( next, undefined, "next", origEvent );
|
||||||
|
};
|
||||||
|
|
||||||
|
// Swipe for touch devices by @and3rson.
|
||||||
|
// Below we extend the api to control the animation between the currently
|
||||||
|
// active step and a presumed next/prev step. See touch plugin for
|
||||||
|
// an example of using this api.
|
||||||
|
|
||||||
|
// Helper function
|
||||||
|
var interpolate = function( a, b, k ) {
|
||||||
|
return a + ( b - a ) * k;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Animate a swipe.
|
||||||
|
//
|
||||||
|
// Pct is a value between -1.0 and +1.0, designating the current length
|
||||||
|
// of the swipe.
|
||||||
|
//
|
||||||
|
// If pct is negative, swipe towards the next() step, if positive,
|
||||||
|
// towards the prev() step.
|
||||||
|
//
|
||||||
|
// Note that pre-stepleave plugins such as goto can mess with what is a
|
||||||
|
// next() and prev() step, so we need to trigger the pre-stepleave event
|
||||||
|
// here, even if a swipe doesn't guarantee that the transition will
|
||||||
|
// actually happen.
|
||||||
|
//
|
||||||
|
// Calling swipe(), with any value of pct, won't in itself cause a
|
||||||
|
// transition to happen, this is just to animate the swipe. Once the
|
||||||
|
// transition is committed - such as at a touchend event - caller is
|
||||||
|
// responsible for also calling prev()/next() as appropriate.
|
||||||
|
//
|
||||||
|
// Note: For now, this function is made available to be used by the swipe plugin (which
|
||||||
|
// is the UI counterpart to this). It is a semi-internal API and intentionally not
|
||||||
|
// documented in DOCUMENTATION.md.
|
||||||
|
var swipe = function( pct ) {
|
||||||
|
if ( Math.abs( pct ) > 1 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare & execute the preStepLeave event
|
||||||
|
var event = { target: activeStep, detail: {} };
|
||||||
|
event.detail.swipe = pct;
|
||||||
|
|
||||||
|
// Will be ignored within swipe animation, but just in case a plugin wants to read this,
|
||||||
|
// humor them
|
||||||
|
event.detail.transitionDuration = config.transitionDuration;
|
||||||
|
var idx; // Needed by jshint
|
||||||
|
if ( pct < 0 ) {
|
||||||
|
idx = steps.indexOf( activeStep ) + 1;
|
||||||
|
event.detail.next = idx < steps.length ? steps[ idx ] : steps[ 0 ];
|
||||||
|
event.detail.reason = "next";
|
||||||
|
} else if ( pct > 0 ) {
|
||||||
|
idx = steps.indexOf( activeStep ) - 1;
|
||||||
|
event.detail.next = idx >= 0 ? steps[ idx ] : steps[ steps.length - 1 ];
|
||||||
|
event.detail.reason = "prev";
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// No move
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( execPreStepLeavePlugins( event ) === false ) {
|
||||||
|
|
||||||
|
// If a preStepLeave plugin wants to abort the transition, don't animate a swipe
|
||||||
|
// For stop, this is probably ok. For substep, the plugin it self might want to do
|
||||||
|
// some animation, but that's not the current implementation.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var nextElement = event.detail.next;
|
||||||
|
|
||||||
|
var nextStep = stepsData[ "impress-" + nextElement.id ];
|
||||||
|
|
||||||
|
// If the same step is re-selected, force computing window scaling,
|
||||||
|
var nextScale = nextStep.scale * windowScale;
|
||||||
|
var k = Math.abs( pct );
|
||||||
|
|
||||||
|
var interpolatedStep = {
|
||||||
|
translate: {
|
||||||
|
x: interpolate( currentState.translate.x, -nextStep.translate.x, k ),
|
||||||
|
y: interpolate( currentState.translate.y, -nextStep.translate.y, k ),
|
||||||
|
z: interpolate( currentState.translate.z, -nextStep.translate.z, k )
|
||||||
|
},
|
||||||
|
rotate: {
|
||||||
|
x: interpolate( currentState.rotate.x, -nextStep.rotate.x, k ),
|
||||||
|
y: interpolate( currentState.rotate.y, -nextStep.rotate.y, k ),
|
||||||
|
z: interpolate( currentState.rotate.z, -nextStep.rotate.z, k ),
|
||||||
|
|
||||||
|
// Unfortunately there's a discontinuity if rotation order changes. Nothing I
|
||||||
|
// can do about it?
|
||||||
|
order: k < 0.7 ? currentState.rotate.order : nextStep.rotate.order
|
||||||
|
},
|
||||||
|
scale: interpolate( currentState.scale * windowScale, nextScale, k )
|
||||||
|
};
|
||||||
|
|
||||||
|
css( root, {
|
||||||
|
|
||||||
|
// To keep the perspective look similar for different scales
|
||||||
|
// we need to 'scale' the perspective, too
|
||||||
|
perspective: config.perspective / interpolatedStep.scale + "px",
|
||||||
|
transform: scale( interpolatedStep.scale ),
|
||||||
|
transitionDuration: "0ms",
|
||||||
|
transitionDelay: "0ms"
|
||||||
|
} );
|
||||||
|
|
||||||
|
css( canvas, {
|
||||||
|
transform: rotate( interpolatedStep.rotate, true ) +
|
||||||
|
translate( interpolatedStep.translate ),
|
||||||
|
transitionDuration: "0ms",
|
||||||
|
transitionDelay: "0ms"
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
|
// Teardown impress
|
||||||
|
// Resets the DOM to the state it was before impress().init() was called.
|
||||||
|
// (If you called impress(rootId).init() for multiple different rootId's, then you must
|
||||||
|
// also call tear() once for each of them.)
|
||||||
|
var tear = function() {
|
||||||
|
lib.gc.teardown();
|
||||||
|
delete roots[ "impress-root-" + rootId ];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Adding some useful classes to step elements.
|
||||||
|
//
|
||||||
|
// All the steps that have not been shown yet are given `future` class.
|
||||||
|
// When the step is entered the `future` class is removed and the `present`
|
||||||
|
// class is given. When the step is left `present` class is replaced with
|
||||||
|
// `past` class.
|
||||||
|
//
|
||||||
|
// So every step element is always in one of three possible states:
|
||||||
|
// `future`, `present` and `past`.
|
||||||
|
//
|
||||||
|
// There classes can be used in CSS to style different types of steps.
|
||||||
|
// For example the `present` class can be used to trigger some custom
|
||||||
|
// animations when step is shown.
|
||||||
|
lib.gc.addEventListener( root, "impress:init", function() {
|
||||||
|
|
||||||
|
// STEP CLASSES
|
||||||
|
steps.forEach( function( step ) {
|
||||||
|
step.classList.add( "future" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
lib.gc.addEventListener( root, "impress:stepenter", function( event ) {
|
||||||
|
event.target.classList.remove( "past" );
|
||||||
|
event.target.classList.remove( "future" );
|
||||||
|
event.target.classList.add( "present" );
|
||||||
|
}, false );
|
||||||
|
|
||||||
|
lib.gc.addEventListener( root, "impress:stepleave", function( event ) {
|
||||||
|
event.target.classList.remove( "present" );
|
||||||
|
event.target.classList.add( "past" );
|
||||||
|
}, false );
|
||||||
|
|
||||||
|
}, false );
|
||||||
|
|
||||||
|
// Adding hash change support.
|
||||||
|
lib.gc.addEventListener( root, "impress:init", function() {
|
||||||
|
|
||||||
|
// Last hash detected
|
||||||
|
var lastHash = "";
|
||||||
|
|
||||||
|
// `#/step-id` is used instead of `#step-id` to prevent default browser
|
||||||
|
// scrolling to element in hash.
|
||||||
|
//
|
||||||
|
// And it has to be set after animation finishes, because in Chrome it
|
||||||
|
// makes transition laggy.
|
||||||
|
// BUG: http://code.google.com/p/chromium/issues/detail?id=62820
|
||||||
|
lib.gc.addEventListener( root, "impress:stepenter", function( event ) {
|
||||||
|
window.location.hash = lastHash = "#/" + event.target.id;
|
||||||
|
}, false );
|
||||||
|
|
||||||
|
lib.gc.addEventListener( window, "hashchange", function() {
|
||||||
|
|
||||||
|
// When the step is entered hash in the location is updated
|
||||||
|
// (just few lines above from here), so the hash change is
|
||||||
|
// triggered and we would call `goto` again on the same element.
|
||||||
|
//
|
||||||
|
// To avoid this we store last entered hash and compare.
|
||||||
|
if ( window.location.hash !== lastHash ) {
|
||||||
|
goto( lib.util.getElementFromHash() );
|
||||||
|
}
|
||||||
|
}, false );
|
||||||
|
|
||||||
|
// START
|
||||||
|
// by selecting step defined in url or first step of the presentation
|
||||||
|
goto( lib.util.getElementFromHash() || steps[ 0 ], 0 );
|
||||||
|
}, false );
|
||||||
|
|
||||||
|
body.classList.add( "impress-disabled" );
|
||||||
|
|
||||||
|
// Store and return API for given impress.js root element
|
||||||
|
return ( roots[ "impress-root-" + rootId ] = {
|
||||||
|
init: init,
|
||||||
|
goto: goto,
|
||||||
|
next: next,
|
||||||
|
prev: prev,
|
||||||
|
swipe: swipe,
|
||||||
|
tear: tear,
|
||||||
|
lib: lib
|
||||||
|
} );
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Flag that can be used in JS to check if browser have passed the support test
|
||||||
|
impress.supported = impressSupported;
|
||||||
|
|
||||||
|
// ADD and INIT LIBRARIES
|
||||||
|
// Library factories are defined in src/lib/*.js, and register themselves by calling
|
||||||
|
// impress.addLibraryFactory(libraryFactoryObject). They're stored here, and used to augment
|
||||||
|
// the API with library functions when client calls impress(rootId).
|
||||||
|
// See src/lib/README.md for clearer example.
|
||||||
|
// (Advanced usage: For different values of rootId, a different instance of the libaries are
|
||||||
|
// generated, in case they need to hold different state for different root elements.)
|
||||||
|
var libraryFactories = {};
|
||||||
|
impress.addLibraryFactory = function( obj ) {
|
||||||
|
for ( var libname in obj ) {
|
||||||
|
if ( obj.hasOwnProperty( libname ) ) {
|
||||||
|
libraryFactories[ libname ] = obj[ libname ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call each library factory, and return the lib object that is added to the api.
|
||||||
|
var initLibraries = function( rootId ) { //jshint ignore:line
|
||||||
|
var lib = {};
|
||||||
|
for ( var libname in libraryFactories ) {
|
||||||
|
if ( libraryFactories.hasOwnProperty( libname ) ) {
|
||||||
|
if ( lib[ libname ] !== undefined ) {
|
||||||
|
throw "impress.js ERROR: Two libraries both tried to use libname: " + libname;
|
||||||
|
}
|
||||||
|
lib[ libname ] = libraryFactories[ libname ]( rootId );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lib;
|
||||||
|
};
|
||||||
|
|
||||||
|
// `addPreInitPlugin` allows plugins to register a function that should
|
||||||
|
// be run (synchronously) at the beginning of init, before
|
||||||
|
// impress().init() itself executes.
|
||||||
|
impress.addPreInitPlugin = function( plugin, weight ) {
|
||||||
|
weight = parseInt( weight ) || 10;
|
||||||
|
if ( weight <= 0 ) {
|
||||||
|
throw "addPreInitPlugin: weight must be a positive integer";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( preInitPlugins[ weight ] === undefined ) {
|
||||||
|
preInitPlugins[ weight ] = [];
|
||||||
|
}
|
||||||
|
preInitPlugins[ weight ].push( plugin );
|
||||||
|
};
|
||||||
|
|
||||||
|
// Called at beginning of init, to execute all pre-init plugins.
|
||||||
|
var execPreInitPlugins = function( root ) { //jshint ignore:line
|
||||||
|
for ( var i = 0; i < preInitPlugins.length; i++ ) {
|
||||||
|
var thisLevel = preInitPlugins[ i ];
|
||||||
|
if ( thisLevel !== undefined ) {
|
||||||
|
for ( var j = 0; j < thisLevel.length; j++ ) {
|
||||||
|
thisLevel[ j ]( root, roots[ "impress-root-" + root.id ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// `addPreStepLeavePlugin` allows plugins to register a function that should
|
||||||
|
// be run (synchronously) at the beginning of goto()
|
||||||
|
impress.addPreStepLeavePlugin = function( plugin, weight ) { //jshint ignore:line
|
||||||
|
weight = parseInt( weight ) || 10;
|
||||||
|
if ( weight <= 0 ) {
|
||||||
|
throw "addPreStepLeavePlugin: weight must be a positive integer";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( preStepLeavePlugins[ weight ] === undefined ) {
|
||||||
|
preStepLeavePlugins[ weight ] = [];
|
||||||
|
}
|
||||||
|
preStepLeavePlugins[ weight ].push( plugin );
|
||||||
|
};
|
||||||
|
|
||||||
|
impress.getConfig = function() {
|
||||||
|
return config;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Called at beginning of goto(), to execute all preStepLeave plugins.
|
||||||
|
var execPreStepLeavePlugins = function( event ) { //jshint ignore:line
|
||||||
|
for ( var i = 0; i < preStepLeavePlugins.length; i++ ) {
|
||||||
|
var thisLevel = preStepLeavePlugins[ i ];
|
||||||
|
if ( thisLevel !== undefined ) {
|
||||||
|
for ( var j = 0; j < thisLevel.length; j++ ) {
|
||||||
|
if ( thisLevel[ j ]( event ) === false ) {
|
||||||
|
|
||||||
|
// If a plugin returns false, the stepleave event (and related transition)
|
||||||
|
// is aborted
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} )( document, window );
|
||||||
|
|
||||||
|
// THAT'S ALL FOLKS!
|
||||||
|
//
|
||||||
|
// Thanks for reading it all.
|
||||||
|
// Or thanks for scrolling down and reading the last part.
|
||||||
|
//
|
||||||
|
// I've learnt a lot when building impress.js and I hope this code and comments
|
||||||
|
// will help somebody learn at least some part of it.
|
||||||
39
src/index.html
Normal file
39
src/index.html
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<!--
|
||||||
|
* impress.js - index.html
|
||||||
|
*
|
||||||
|
* This is just a test file for development of impress.js V3
|
||||||
|
*
|
||||||
|
* Created by Janis Hutz 01/08/2024, Licensed under the MIT License
|
||||||
|
* https://janishutz.com, development@janishutz.com
|
||||||
|
*
|
||||||
|
*
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title></title>
|
||||||
|
<style>
|
||||||
|
.impress-supported .fallback-message {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="impress-not-supported">
|
||||||
|
<div class="fallback-message">
|
||||||
|
<p>Your browser <b>doesn't support the features required</b> by impress.js, so you are presented with a simplified version of this presentation.</p>
|
||||||
|
<p>For the best experience please use the latest <b>Chrome</b>, <b>Safari</b> or <b>Firefox</b> browser.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="impress" data-width="1920" data-height="1080">
|
||||||
|
<div id="title" class="step">
|
||||||
|
<h1>Test</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="/impress.js"></script>
|
||||||
|
<script>
|
||||||
|
impress().init();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
429
src/lib-old/rotation.js
Normal file
429
src/lib-old/rotation.js
Normal file
@@ -0,0 +1,429 @@
|
|||||||
|
/**
|
||||||
|
* Helper functions for rotation.
|
||||||
|
*
|
||||||
|
* Tommy Tam (c) 2021
|
||||||
|
* MIT License
|
||||||
|
*/
|
||||||
|
( function( document, window ) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Singleton library variables
|
||||||
|
var roots = [];
|
||||||
|
|
||||||
|
var libraryFactory = function( rootId ) {
|
||||||
|
if ( roots[ "impress-root-" + rootId ] ) {
|
||||||
|
return roots[ "impress-root-" + rootId ];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Round the number to 2 decimals, it's enough for use
|
||||||
|
*/
|
||||||
|
var roundNumber = function( num ) {
|
||||||
|
return Math.round( ( num + Number.EPSILON ) * 100 ) / 100;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the length/norm of a vector.
|
||||||
|
*
|
||||||
|
* https://en.wikipedia.org/wiki/Norm_(mathematics)
|
||||||
|
*/
|
||||||
|
var vectorLength = function( vec ) {
|
||||||
|
return Math.sqrt( vec.x * vec.x + vec.y * vec.y + vec.z * vec.z );
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dot product of two vectors.
|
||||||
|
*
|
||||||
|
* https://en.wikipedia.org/wiki/Dot_product
|
||||||
|
*/
|
||||||
|
var vectorDotProd = function( vec1, vec2 ) {
|
||||||
|
return vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cross product of two vectors.
|
||||||
|
*
|
||||||
|
* https://en.wikipedia.org/wiki/Cross_product
|
||||||
|
*/
|
||||||
|
var vectorCrossProd = function( vec1, vec2 ) {
|
||||||
|
return {
|
||||||
|
x: vec1.y * vec2.z - vec1.z * vec2.y,
|
||||||
|
y: vec1.z * vec2.x - vec1.x * vec2.z,
|
||||||
|
z: vec1.x * vec2.y - vec1.y * vec2.x
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine wheter a vector is a zero vector
|
||||||
|
*/
|
||||||
|
var isZeroVector = function( vec ) {
|
||||||
|
return !roundNumber( vec.x ) && !roundNumber( vec.y ) && !roundNumber( vec.z );
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scalar triple product of three vectors.
|
||||||
|
*
|
||||||
|
* It can be used to determine the handness of vectors.
|
||||||
|
*
|
||||||
|
* https://en.wikipedia.org/wiki/Triple_product#Scalar_triple_product
|
||||||
|
*/
|
||||||
|
var tripleProduct = function( vec1, vec2, vec3 ) {
|
||||||
|
return vectorDotProd( vectorCrossProd( vec1, vec2 ), vec3 );
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The world/absolute unit coordinates.
|
||||||
|
*
|
||||||
|
* This coordinate is used by browser to position objects.
|
||||||
|
* It will not be affected by object rotations.
|
||||||
|
* All relative positions will finally be converted to this
|
||||||
|
* coordinate to be used.
|
||||||
|
*/
|
||||||
|
var worldUnitCoordinate = {
|
||||||
|
x: { x:1, y:0, z:0 },
|
||||||
|
y: { x:0, y:1, z:0 },
|
||||||
|
z: { x:0, y:0, z:1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make quaternion from rotation axis and angle.
|
||||||
|
*
|
||||||
|
* q = [ cos(½θ), sin(½θ) axis ]
|
||||||
|
*
|
||||||
|
* If the angle is zero, returns the corresponded quaternion
|
||||||
|
* of axis.
|
||||||
|
*
|
||||||
|
* If the angle is not zero, returns the rotating quaternion
|
||||||
|
* which corresponds to rotation about the axis, by the angle θ.
|
||||||
|
*
|
||||||
|
* https://en.wikipedia.org/wiki/Quaternion
|
||||||
|
* https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
|
||||||
|
*/
|
||||||
|
var makeQuaternion = function( axis, theta = 0 ) {
|
||||||
|
var r = 0;
|
||||||
|
var t = 1;
|
||||||
|
|
||||||
|
if ( theta ) {
|
||||||
|
var radians = theta * Math.PI / 180;
|
||||||
|
r = Math.cos( radians / 2 );
|
||||||
|
t = Math.sin( radians / 2 ) / vectorLength( axis );
|
||||||
|
}
|
||||||
|
|
||||||
|
var q = [ r, axis.x * t, axis.y * t, axis.z * t ];
|
||||||
|
|
||||||
|
return q;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract vector from quaternion
|
||||||
|
*/
|
||||||
|
var quaternionToVector = function( quaternion ) {
|
||||||
|
return {
|
||||||
|
x: roundNumber( quaternion[ 1 ] ),
|
||||||
|
y: roundNumber( quaternion[ 2 ] ),
|
||||||
|
z: roundNumber( quaternion[ 3 ] )
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the conjugate quaternion of a quaternion
|
||||||
|
*
|
||||||
|
* https://en.wikipedia.org/wiki/Quaternion#Conjugation,_the_norm,_and_reciprocal
|
||||||
|
*/
|
||||||
|
var conjugateQuaternion = function( quaternion ) {
|
||||||
|
return [ quaternion[ 0 ], -quaternion[ 1 ], -quaternion[ 2 ], -quaternion[ 3 ] ];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Left multiple two quaternion.
|
||||||
|
*
|
||||||
|
* Is's used to combine two rotating quaternion into one.
|
||||||
|
*/
|
||||||
|
var leftMulQuaternion = function( q1, q2 ) {
|
||||||
|
return [
|
||||||
|
( q1[ 0 ] * q2[ 0 ] - q1[ 1 ] * q2[ 1 ] - q1[ 2 ] * q2[ 2 ] - q1[ 3 ] * q2[ 3 ] ),
|
||||||
|
( q1[ 1 ] * q2[ 0 ] + q1[ 0 ] * q2[ 1 ] - q1[ 3 ] * q2[ 2 ] + q1[ 2 ] * q2[ 3 ] ),
|
||||||
|
( q1[ 2 ] * q2[ 0 ] + q1[ 3 ] * q2[ 1 ] + q1[ 0 ] * q2[ 2 ] - q1[ 1 ] * q2[ 3 ] ),
|
||||||
|
( q1[ 3 ] * q2[ 0 ] - q1[ 2 ] * q2[ 1 ] + q1[ 1 ] * q2[ 2 ] + q1[ 0 ] * q2[ 3 ] )
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a rotation into a quaternion
|
||||||
|
*/
|
||||||
|
var rotationToQuaternion = function( baseCoordinate, rotation ) {
|
||||||
|
var order = rotation.order ? rotation.order : "xyz";
|
||||||
|
var axes = order.split( "" );
|
||||||
|
var result = [ 1, 0, 0, 0 ];
|
||||||
|
|
||||||
|
for ( var i = 0; i < axes.length; i++ ) {
|
||||||
|
var deg = rotation[ axes[ i ] ];
|
||||||
|
if ( !deg || ( Math.abs( deg ) < 0.0001 ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All CSS rotation is based on the rotated coordinate
|
||||||
|
// So we need to calculate the rotated coordinate first
|
||||||
|
var coordinate = baseCoordinate;
|
||||||
|
if ( i > 0 ) {
|
||||||
|
coordinate = {
|
||||||
|
x: rotateByQuaternion( baseCoordinate.x, result ),
|
||||||
|
y: rotateByQuaternion( baseCoordinate.y, result ),
|
||||||
|
z: rotateByQuaternion( baseCoordinate.z, result )
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
result = leftMulQuaternion(
|
||||||
|
makeQuaternion( coordinate[ axes[ i ] ], deg ),
|
||||||
|
result );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotate a vector by a quaternion.
|
||||||
|
*/
|
||||||
|
var rotateByQuaternion = function( vec, quaternion ) {
|
||||||
|
var q = makeQuaternion( vec );
|
||||||
|
|
||||||
|
q = leftMulQuaternion(
|
||||||
|
leftMulQuaternion( quaternion, q ),
|
||||||
|
conjugateQuaternion( quaternion ) );
|
||||||
|
|
||||||
|
return quaternionToVector( q );
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotate a vector by rotaion sequence.
|
||||||
|
*/
|
||||||
|
var rotateVector = function( baseCoordinate, vec, rotation ) {
|
||||||
|
var quaternion = rotationToQuaternion( baseCoordinate, rotation );
|
||||||
|
|
||||||
|
return rotateByQuaternion( vec, quaternion );
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a rotation, return the rotationed coordinate
|
||||||
|
*/
|
||||||
|
var rotateCoordinate = function( coordinate, rotation ) {
|
||||||
|
var quaternion = rotationToQuaternion( coordinate, rotation );
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: rotateByQuaternion( coordinate.x, quaternion ),
|
||||||
|
y: rotateByQuaternion( coordinate.y, quaternion ),
|
||||||
|
z: rotateByQuaternion( coordinate.z, quaternion )
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the angle between two vector.
|
||||||
|
*
|
||||||
|
* The axis is used to determine the rotation direction.
|
||||||
|
*/
|
||||||
|
var angleBetweenTwoVector = function( axis, vec1, vec2 ) {
|
||||||
|
var vecLen1 = vectorLength( vec1 );
|
||||||
|
var vecLen2 = vectorLength( vec2 );
|
||||||
|
|
||||||
|
if ( !vecLen1 || !vecLen2 ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cos = vectorDotProd( vec1, vec2 ) / vecLen1 / vecLen2 ;
|
||||||
|
var angle = Math.acos( cos ) * 180 / Math.PI;
|
||||||
|
|
||||||
|
if ( tripleProduct( vec1, vec2, axis ) > 0 ) {
|
||||||
|
return angle;
|
||||||
|
} else {
|
||||||
|
return -angle;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the angle between a vector and a plane.
|
||||||
|
*
|
||||||
|
* The plane is determined by an axis and a vector on the plane.
|
||||||
|
*/
|
||||||
|
var angleBetweenPlaneAndVector = function( axis, planeVec, rotatedVec ) {
|
||||||
|
var norm = vectorCrossProd( axis, planeVec );
|
||||||
|
|
||||||
|
if ( isZeroVector( norm ) ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 90 - angleBetweenTwoVector( axis, rotatedVec, norm );
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculated a order specified rotation sequence to
|
||||||
|
* transform from the world coordinate to required coordinate.
|
||||||
|
*/
|
||||||
|
var coordinateToOrderedRotation = function( coordinate, order ) {
|
||||||
|
var axis0 = order[ 0 ];
|
||||||
|
var axis1 = order[ 1 ];
|
||||||
|
var axis2 = order[ 2 ];
|
||||||
|
var reversedOrder = order.split( "" ).reverse().join( "" );
|
||||||
|
|
||||||
|
var rotate2 = angleBetweenPlaneAndVector(
|
||||||
|
coordinate[ axis2 ],
|
||||||
|
worldUnitCoordinate[ axis0 ],
|
||||||
|
coordinate[ axis0 ] );
|
||||||
|
|
||||||
|
// The r2 is the reverse of rotate for axis2
|
||||||
|
// The coordinate1 is the coordinate before rotate of axis2
|
||||||
|
var r2 = { order: reversedOrder };
|
||||||
|
r2[ axis2 ] = -rotate2;
|
||||||
|
|
||||||
|
var coordinate1 = rotateCoordinate( coordinate, r2 );
|
||||||
|
|
||||||
|
// Calculate the rotation for axis1
|
||||||
|
var rotate1 = angleBetweenTwoVector(
|
||||||
|
coordinate1[ axis1 ],
|
||||||
|
worldUnitCoordinate[ axis0 ],
|
||||||
|
coordinate1[ axis0 ] );
|
||||||
|
|
||||||
|
// Calculate the rotation for axis0
|
||||||
|
var rotate0 = angleBetweenTwoVector(
|
||||||
|
worldUnitCoordinate[ axis0 ],
|
||||||
|
worldUnitCoordinate[ axis1 ],
|
||||||
|
coordinate1[ axis1 ] );
|
||||||
|
|
||||||
|
var rotation = { };
|
||||||
|
rotation.order = order;
|
||||||
|
rotation[ axis0 ] = roundNumber( rotate0 );
|
||||||
|
rotation[ axis1 ] = roundNumber( rotate1 );
|
||||||
|
rotation[ axis2 ] = roundNumber( rotate2 );
|
||||||
|
|
||||||
|
return rotation;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the possible rotations from unit coordinate
|
||||||
|
* to specified coordinate.
|
||||||
|
*/
|
||||||
|
var possibleRotations = function( coordinate ) {
|
||||||
|
var orders = [ "xyz", "xzy", "yxz", "yzx", "zxy", "zyx" ];
|
||||||
|
var rotations = [ ];
|
||||||
|
|
||||||
|
for ( var i = 0; i < orders.length; ++i ) {
|
||||||
|
rotations.push(
|
||||||
|
coordinateToOrderedRotation( coordinate, orders[ i ] )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rotations;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate a degree which in range (-180, 180] of baseDeg
|
||||||
|
*/
|
||||||
|
var nearestAngle = function( baseDeg, deg ) {
|
||||||
|
while ( deg > baseDeg + 180 ) {
|
||||||
|
deg -= 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( deg < baseDeg - 180 ) {
|
||||||
|
deg += 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
return deg;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a base rotation and multiple rotations, return the best one.
|
||||||
|
*
|
||||||
|
* The best one is the one has least rotate from base.
|
||||||
|
*/
|
||||||
|
var bestRotation = function( baseRotate, rotations ) {
|
||||||
|
var bestScore;
|
||||||
|
var bestRotation;
|
||||||
|
|
||||||
|
for ( var i = 0; i < rotations.length; ++i ) {
|
||||||
|
var rotation = {
|
||||||
|
order: rotations[ i ].order,
|
||||||
|
x: nearestAngle( baseRotate.x, rotations[ i ].x ),
|
||||||
|
y: nearestAngle( baseRotate.y, rotations[ i ].y ),
|
||||||
|
z: nearestAngle( baseRotate.z, rotations[ i ].z )
|
||||||
|
};
|
||||||
|
|
||||||
|
var score = Math.abs( rotation.x - baseRotate.x ) +
|
||||||
|
Math.abs( rotation.y - baseRotate.y ) +
|
||||||
|
Math.abs( rotation.z - baseRotate.z );
|
||||||
|
|
||||||
|
if ( !i || ( score < bestScore ) ) {
|
||||||
|
bestScore = score;
|
||||||
|
bestRotation = rotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bestRotation;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a coordinate, return the best rotation to achieve it.
|
||||||
|
*
|
||||||
|
* The baseRotate is used to select the near rotation from it.
|
||||||
|
*/
|
||||||
|
var coordinateToRotation = function( baseRotate, coordinate ) {
|
||||||
|
var rotations = possibleRotations( coordinate );
|
||||||
|
|
||||||
|
return bestRotation( baseRotate, rotations );
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply a relative rotation to the base rotation.
|
||||||
|
*
|
||||||
|
* Calculate the coordinate after the rotation on each axis,
|
||||||
|
* and finally find out a one step rotation has the effect
|
||||||
|
* of two rotation.
|
||||||
|
*
|
||||||
|
* If there're multiple way to accomplish, select the one
|
||||||
|
* that is nearest to the base.
|
||||||
|
*
|
||||||
|
* Return one rotation has the same effect.
|
||||||
|
*/
|
||||||
|
var combineRotations = function( rotations ) {
|
||||||
|
|
||||||
|
// No rotation
|
||||||
|
if ( rotations.length <= 0 ) {
|
||||||
|
return { x:0, y:0, z:0, order:"xyz" };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find out the base coordinate
|
||||||
|
var coordinate = worldUnitCoordinate;
|
||||||
|
|
||||||
|
// One by one apply rotations in order
|
||||||
|
for ( var i = 0; i < rotations.length; i++ ) {
|
||||||
|
coordinate = rotateCoordinate( coordinate, rotations[ i ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate one rotation from unit coordinate to rotated
|
||||||
|
// coordinate. Because there're multiple possibles,
|
||||||
|
// select the one nearest to the base
|
||||||
|
var rotate = coordinateToRotation( rotations[ 0 ], coordinate );
|
||||||
|
|
||||||
|
return rotate;
|
||||||
|
};
|
||||||
|
|
||||||
|
var translateRelative = function( relative, prevRotation ) {
|
||||||
|
var result = rotateVector(
|
||||||
|
worldUnitCoordinate, relative, prevRotation );
|
||||||
|
result.rotate = combineRotations(
|
||||||
|
[ prevRotation, relative.rotate ] );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
var lib = {
|
||||||
|
translateRelative: translateRelative
|
||||||
|
};
|
||||||
|
|
||||||
|
roots[ "impress-root-" + rootId ] = lib;
|
||||||
|
return lib;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Let impress core know about the existence of this library
|
||||||
|
window.impress.addLibraryFactory( { rotation: libraryFactory } );
|
||||||
|
|
||||||
|
} )( document, window );
|
||||||
7
src/lib/position.js
Normal file
7
src/lib/position.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// File name: position.js
|
||||||
|
// Author: Janis Hutz
|
||||||
|
// Date created: 2025-10-24 13:54:52
|
||||||
|
// Date modified: 2025-10-24 13:54:53
|
||||||
|
// ------
|
||||||
|
|
||||||
|
|
||||||
85
src/lib/render.js
Normal file
85
src/lib/render.js
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
// File name: render.js
|
||||||
|
// Author: Janis Hutz
|
||||||
|
// Date created: 2025-10-24 14:04:37
|
||||||
|
// Date modified: 2025-10-24 14:26:50
|
||||||
|
// ------
|
||||||
|
|
||||||
|
class ImpressCamera {
|
||||||
|
constructor () {
|
||||||
|
this.position = {
|
||||||
|
'x': 0,
|
||||||
|
'y': 0,
|
||||||
|
'z': 0
|
||||||
|
};
|
||||||
|
|
||||||
|
this.rotation = {
|
||||||
|
'x': 0,
|
||||||
|
'y': 0,
|
||||||
|
'z': 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
setPosition ( x, y, z ) {
|
||||||
|
this.position.x = x;
|
||||||
|
this.position.y = y;
|
||||||
|
this.position.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRotation ( x, y, z ) {
|
||||||
|
this.rotation.x = x;
|
||||||
|
this.rotation.y = y;
|
||||||
|
this.rotation.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
getState () {
|
||||||
|
return {
|
||||||
|
'position': this.position,
|
||||||
|
'rotation': this.rotation
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ImpressElement {
|
||||||
|
// eslint-disable-next-line max-params
|
||||||
|
constructor ( element, x, y, z, rotationX, rotationY, rotationZ ) {
|
||||||
|
this.element = element;
|
||||||
|
this.position = {
|
||||||
|
'x': x,
|
||||||
|
'y': y,
|
||||||
|
'z': z
|
||||||
|
};
|
||||||
|
|
||||||
|
this.rotation = {
|
||||||
|
'x': rotationX,
|
||||||
|
'y': rotationY,
|
||||||
|
'z': rotationZ
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const renderer = () => {
|
||||||
|
const camera = new ImpressCamera();
|
||||||
|
|
||||||
|
const addElement = ( HTMLElement ) => {
|
||||||
|
// Element will need data-x, data-y, data-z, etc dataset
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeElement = ( HTMLElement ) => {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const render = () => {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const moveTo = ( x, y, z, rotationX, rotationY, rotationZ ) => {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
addElement,
|
||||||
|
removeElement,
|
||||||
|
moveTo
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -1,429 +1,7 @@
|
|||||||
/**
|
// File name: rotation.js
|
||||||
* Helper functions for rotation.
|
// Author: Janis Hutz
|
||||||
*
|
// Date created: 2025-10-24 13:54:49
|
||||||
* Tommy Tam (c) 2021
|
// Date modified: 2025-10-24 13:54:50
|
||||||
* MIT License
|
// ------
|
||||||
*/
|
|
||||||
( function( document, window ) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Singleton library variables
|
|
||||||
var roots = [];
|
|
||||||
|
|
||||||
var libraryFactory = function( rootId ) {
|
|
||||||
if ( roots[ "impress-root-" + rootId ] ) {
|
|
||||||
return roots[ "impress-root-" + rootId ];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Round the number to 2 decimals, it's enough for use
|
|
||||||
*/
|
|
||||||
var roundNumber = function( num ) {
|
|
||||||
return Math.round( ( num + Number.EPSILON ) * 100 ) / 100;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the length/norm of a vector.
|
|
||||||
*
|
|
||||||
* https://en.wikipedia.org/wiki/Norm_(mathematics)
|
|
||||||
*/
|
|
||||||
var vectorLength = function( vec ) {
|
|
||||||
return Math.sqrt( vec.x * vec.x + vec.y * vec.y + vec.z * vec.z );
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dot product of two vectors.
|
|
||||||
*
|
|
||||||
* https://en.wikipedia.org/wiki/Dot_product
|
|
||||||
*/
|
|
||||||
var vectorDotProd = function( vec1, vec2 ) {
|
|
||||||
return vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cross product of two vectors.
|
|
||||||
*
|
|
||||||
* https://en.wikipedia.org/wiki/Cross_product
|
|
||||||
*/
|
|
||||||
var vectorCrossProd = function( vec1, vec2 ) {
|
|
||||||
return {
|
|
||||||
x: vec1.y * vec2.z - vec1.z * vec2.y,
|
|
||||||
y: vec1.z * vec2.x - vec1.x * vec2.z,
|
|
||||||
z: vec1.x * vec2.y - vec1.y * vec2.x
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine wheter a vector is a zero vector
|
|
||||||
*/
|
|
||||||
var isZeroVector = function( vec ) {
|
|
||||||
return !roundNumber( vec.x ) && !roundNumber( vec.y ) && !roundNumber( vec.z );
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scalar triple product of three vectors.
|
|
||||||
*
|
|
||||||
* It can be used to determine the handness of vectors.
|
|
||||||
*
|
|
||||||
* https://en.wikipedia.org/wiki/Triple_product#Scalar_triple_product
|
|
||||||
*/
|
|
||||||
var tripleProduct = function( vec1, vec2, vec3 ) {
|
|
||||||
return vectorDotProd( vectorCrossProd( vec1, vec2 ), vec3 );
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The world/absolute unit coordinates.
|
|
||||||
*
|
|
||||||
* This coordinate is used by browser to position objects.
|
|
||||||
* It will not be affected by object rotations.
|
|
||||||
* All relative positions will finally be converted to this
|
|
||||||
* coordinate to be used.
|
|
||||||
*/
|
|
||||||
var worldUnitCoordinate = {
|
|
||||||
x: { x:1, y:0, z:0 },
|
|
||||||
y: { x:0, y:1, z:0 },
|
|
||||||
z: { x:0, y:0, z:1 }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make quaternion from rotation axis and angle.
|
|
||||||
*
|
|
||||||
* q = [ cos(½θ), sin(½θ) axis ]
|
|
||||||
*
|
|
||||||
* If the angle is zero, returns the corresponded quaternion
|
|
||||||
* of axis.
|
|
||||||
*
|
|
||||||
* If the angle is not zero, returns the rotating quaternion
|
|
||||||
* which corresponds to rotation about the axis, by the angle θ.
|
|
||||||
*
|
|
||||||
* https://en.wikipedia.org/wiki/Quaternion
|
|
||||||
* https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
|
|
||||||
*/
|
|
||||||
var makeQuaternion = function( axis, theta = 0 ) {
|
|
||||||
var r = 0;
|
|
||||||
var t = 1;
|
|
||||||
|
|
||||||
if ( theta ) {
|
|
||||||
var radians = theta * Math.PI / 180;
|
|
||||||
r = Math.cos( radians / 2 );
|
|
||||||
t = Math.sin( radians / 2 ) / vectorLength( axis );
|
|
||||||
}
|
|
||||||
|
|
||||||
var q = [ r, axis.x * t, axis.y * t, axis.z * t ];
|
|
||||||
|
|
||||||
return q;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract vector from quaternion
|
|
||||||
*/
|
|
||||||
var quaternionToVector = function( quaternion ) {
|
|
||||||
return {
|
|
||||||
x: roundNumber( quaternion[ 1 ] ),
|
|
||||||
y: roundNumber( quaternion[ 2 ] ),
|
|
||||||
z: roundNumber( quaternion[ 3 ] )
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the conjugate quaternion of a quaternion
|
|
||||||
*
|
|
||||||
* https://en.wikipedia.org/wiki/Quaternion#Conjugation,_the_norm,_and_reciprocal
|
|
||||||
*/
|
|
||||||
var conjugateQuaternion = function( quaternion ) {
|
|
||||||
return [ quaternion[ 0 ], -quaternion[ 1 ], -quaternion[ 2 ], -quaternion[ 3 ] ];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Left multiple two quaternion.
|
|
||||||
*
|
|
||||||
* Is's used to combine two rotating quaternion into one.
|
|
||||||
*/
|
|
||||||
var leftMulQuaternion = function( q1, q2 ) {
|
|
||||||
return [
|
|
||||||
( q1[ 0 ] * q2[ 0 ] - q1[ 1 ] * q2[ 1 ] - q1[ 2 ] * q2[ 2 ] - q1[ 3 ] * q2[ 3 ] ),
|
|
||||||
( q1[ 1 ] * q2[ 0 ] + q1[ 0 ] * q2[ 1 ] - q1[ 3 ] * q2[ 2 ] + q1[ 2 ] * q2[ 3 ] ),
|
|
||||||
( q1[ 2 ] * q2[ 0 ] + q1[ 3 ] * q2[ 1 ] + q1[ 0 ] * q2[ 2 ] - q1[ 1 ] * q2[ 3 ] ),
|
|
||||||
( q1[ 3 ] * q2[ 0 ] - q1[ 2 ] * q2[ 1 ] + q1[ 1 ] * q2[ 2 ] + q1[ 0 ] * q2[ 3 ] )
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a rotation into a quaternion
|
|
||||||
*/
|
|
||||||
var rotationToQuaternion = function( baseCoordinate, rotation ) {
|
|
||||||
var order = rotation.order ? rotation.order : "xyz";
|
|
||||||
var axes = order.split( "" );
|
|
||||||
var result = [ 1, 0, 0, 0 ];
|
|
||||||
|
|
||||||
for ( var i = 0; i < axes.length; i++ ) {
|
|
||||||
var deg = rotation[ axes[ i ] ];
|
|
||||||
if ( !deg || ( Math.abs( deg ) < 0.0001 ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// All CSS rotation is based on the rotated coordinate
|
|
||||||
// So we need to calculate the rotated coordinate first
|
|
||||||
var coordinate = baseCoordinate;
|
|
||||||
if ( i > 0 ) {
|
|
||||||
coordinate = {
|
|
||||||
x: rotateByQuaternion( baseCoordinate.x, result ),
|
|
||||||
y: rotateByQuaternion( baseCoordinate.y, result ),
|
|
||||||
z: rotateByQuaternion( baseCoordinate.z, result )
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
result = leftMulQuaternion(
|
|
||||||
makeQuaternion( coordinate[ axes[ i ] ], deg ),
|
|
||||||
result );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rotate a vector by a quaternion.
|
|
||||||
*/
|
|
||||||
var rotateByQuaternion = function( vec, quaternion ) {
|
|
||||||
var q = makeQuaternion( vec );
|
|
||||||
|
|
||||||
q = leftMulQuaternion(
|
|
||||||
leftMulQuaternion( quaternion, q ),
|
|
||||||
conjugateQuaternion( quaternion ) );
|
|
||||||
|
|
||||||
return quaternionToVector( q );
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rotate a vector by rotaion sequence.
|
|
||||||
*/
|
|
||||||
var rotateVector = function( baseCoordinate, vec, rotation ) {
|
|
||||||
var quaternion = rotationToQuaternion( baseCoordinate, rotation );
|
|
||||||
|
|
||||||
return rotateByQuaternion( vec, quaternion );
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a rotation, return the rotationed coordinate
|
|
||||||
*/
|
|
||||||
var rotateCoordinate = function( coordinate, rotation ) {
|
|
||||||
var quaternion = rotationToQuaternion( coordinate, rotation );
|
|
||||||
|
|
||||||
return {
|
|
||||||
x: rotateByQuaternion( coordinate.x, quaternion ),
|
|
||||||
y: rotateByQuaternion( coordinate.y, quaternion ),
|
|
||||||
z: rotateByQuaternion( coordinate.z, quaternion )
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the angle between two vector.
|
|
||||||
*
|
|
||||||
* The axis is used to determine the rotation direction.
|
|
||||||
*/
|
|
||||||
var angleBetweenTwoVector = function( axis, vec1, vec2 ) {
|
|
||||||
var vecLen1 = vectorLength( vec1 );
|
|
||||||
var vecLen2 = vectorLength( vec2 );
|
|
||||||
|
|
||||||
if ( !vecLen1 || !vecLen2 ) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var cos = vectorDotProd( vec1, vec2 ) / vecLen1 / vecLen2 ;
|
|
||||||
var angle = Math.acos( cos ) * 180 / Math.PI;
|
|
||||||
|
|
||||||
if ( tripleProduct( vec1, vec2, axis ) > 0 ) {
|
|
||||||
return angle;
|
|
||||||
} else {
|
|
||||||
return -angle;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the angle between a vector and a plane.
|
|
||||||
*
|
|
||||||
* The plane is determined by an axis and a vector on the plane.
|
|
||||||
*/
|
|
||||||
var angleBetweenPlaneAndVector = function( axis, planeVec, rotatedVec ) {
|
|
||||||
var norm = vectorCrossProd( axis, planeVec );
|
|
||||||
|
|
||||||
if ( isZeroVector( norm ) ) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 90 - angleBetweenTwoVector( axis, rotatedVec, norm );
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculated a order specified rotation sequence to
|
|
||||||
* transform from the world coordinate to required coordinate.
|
|
||||||
*/
|
|
||||||
var coordinateToOrderedRotation = function( coordinate, order ) {
|
|
||||||
var axis0 = order[ 0 ];
|
|
||||||
var axis1 = order[ 1 ];
|
|
||||||
var axis2 = order[ 2 ];
|
|
||||||
var reversedOrder = order.split( "" ).reverse().join( "" );
|
|
||||||
|
|
||||||
var rotate2 = angleBetweenPlaneAndVector(
|
|
||||||
coordinate[ axis2 ],
|
|
||||||
worldUnitCoordinate[ axis0 ],
|
|
||||||
coordinate[ axis0 ] );
|
|
||||||
|
|
||||||
// The r2 is the reverse of rotate for axis2
|
|
||||||
// The coordinate1 is the coordinate before rotate of axis2
|
|
||||||
var r2 = { order: reversedOrder };
|
|
||||||
r2[ axis2 ] = -rotate2;
|
|
||||||
|
|
||||||
var coordinate1 = rotateCoordinate( coordinate, r2 );
|
|
||||||
|
|
||||||
// Calculate the rotation for axis1
|
|
||||||
var rotate1 = angleBetweenTwoVector(
|
|
||||||
coordinate1[ axis1 ],
|
|
||||||
worldUnitCoordinate[ axis0 ],
|
|
||||||
coordinate1[ axis0 ] );
|
|
||||||
|
|
||||||
// Calculate the rotation for axis0
|
|
||||||
var rotate0 = angleBetweenTwoVector(
|
|
||||||
worldUnitCoordinate[ axis0 ],
|
|
||||||
worldUnitCoordinate[ axis1 ],
|
|
||||||
coordinate1[ axis1 ] );
|
|
||||||
|
|
||||||
var rotation = { };
|
|
||||||
rotation.order = order;
|
|
||||||
rotation[ axis0 ] = roundNumber( rotate0 );
|
|
||||||
rotation[ axis1 ] = roundNumber( rotate1 );
|
|
||||||
rotation[ axis2 ] = roundNumber( rotate2 );
|
|
||||||
|
|
||||||
return rotation;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the possible rotations from unit coordinate
|
|
||||||
* to specified coordinate.
|
|
||||||
*/
|
|
||||||
var possibleRotations = function( coordinate ) {
|
|
||||||
var orders = [ "xyz", "xzy", "yxz", "yzx", "zxy", "zyx" ];
|
|
||||||
var rotations = [ ];
|
|
||||||
|
|
||||||
for ( var i = 0; i < orders.length; ++i ) {
|
|
||||||
rotations.push(
|
|
||||||
coordinateToOrderedRotation( coordinate, orders[ i ] )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rotations;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate a degree which in range (-180, 180] of baseDeg
|
|
||||||
*/
|
|
||||||
var nearestAngle = function( baseDeg, deg ) {
|
|
||||||
while ( deg > baseDeg + 180 ) {
|
|
||||||
deg -= 360;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ( deg < baseDeg - 180 ) {
|
|
||||||
deg += 360;
|
|
||||||
}
|
|
||||||
|
|
||||||
return deg;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a base rotation and multiple rotations, return the best one.
|
|
||||||
*
|
|
||||||
* The best one is the one has least rotate from base.
|
|
||||||
*/
|
|
||||||
var bestRotation = function( baseRotate, rotations ) {
|
|
||||||
var bestScore;
|
|
||||||
var bestRotation;
|
|
||||||
|
|
||||||
for ( var i = 0; i < rotations.length; ++i ) {
|
|
||||||
var rotation = {
|
|
||||||
order: rotations[ i ].order,
|
|
||||||
x: nearestAngle( baseRotate.x, rotations[ i ].x ),
|
|
||||||
y: nearestAngle( baseRotate.y, rotations[ i ].y ),
|
|
||||||
z: nearestAngle( baseRotate.z, rotations[ i ].z )
|
|
||||||
};
|
|
||||||
|
|
||||||
var score = Math.abs( rotation.x - baseRotate.x ) +
|
|
||||||
Math.abs( rotation.y - baseRotate.y ) +
|
|
||||||
Math.abs( rotation.z - baseRotate.z );
|
|
||||||
|
|
||||||
if ( !i || ( score < bestScore ) ) {
|
|
||||||
bestScore = score;
|
|
||||||
bestRotation = rotation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bestRotation;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a coordinate, return the best rotation to achieve it.
|
|
||||||
*
|
|
||||||
* The baseRotate is used to select the near rotation from it.
|
|
||||||
*/
|
|
||||||
var coordinateToRotation = function( baseRotate, coordinate ) {
|
|
||||||
var rotations = possibleRotations( coordinate );
|
|
||||||
|
|
||||||
return bestRotation( baseRotate, rotations );
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply a relative rotation to the base rotation.
|
|
||||||
*
|
|
||||||
* Calculate the coordinate after the rotation on each axis,
|
|
||||||
* and finally find out a one step rotation has the effect
|
|
||||||
* of two rotation.
|
|
||||||
*
|
|
||||||
* If there're multiple way to accomplish, select the one
|
|
||||||
* that is nearest to the base.
|
|
||||||
*
|
|
||||||
* Return one rotation has the same effect.
|
|
||||||
*/
|
|
||||||
var combineRotations = function( rotations ) {
|
|
||||||
|
|
||||||
// No rotation
|
|
||||||
if ( rotations.length <= 0 ) {
|
|
||||||
return { x:0, y:0, z:0, order:"xyz" };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find out the base coordinate
|
|
||||||
var coordinate = worldUnitCoordinate;
|
|
||||||
|
|
||||||
// One by one apply rotations in order
|
|
||||||
for ( var i = 0; i < rotations.length; i++ ) {
|
|
||||||
coordinate = rotateCoordinate( coordinate, rotations[ i ] );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate one rotation from unit coordinate to rotated
|
|
||||||
// coordinate. Because there're multiple possibles,
|
|
||||||
// select the one nearest to the base
|
|
||||||
var rotate = coordinateToRotation( rotations[ 0 ], coordinate );
|
|
||||||
|
|
||||||
return rotate;
|
|
||||||
};
|
|
||||||
|
|
||||||
var translateRelative = function( relative, prevRotation ) {
|
|
||||||
var result = rotateVector(
|
|
||||||
worldUnitCoordinate, relative, prevRotation );
|
|
||||||
result.rotate = combineRotations(
|
|
||||||
[ prevRotation, relative.rotate ] );
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
var lib = {
|
|
||||||
translateRelative: translateRelative
|
|
||||||
};
|
|
||||||
|
|
||||||
roots[ "impress-root-" + rootId ] = lib;
|
|
||||||
return lib;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Let impress core know about the existence of this library
|
|
||||||
window.impress.addLibraryFactory( { rotation: libraryFactory } );
|
|
||||||
|
|
||||||
} )( document, window );
|
|
||||||
|
|||||||
76
src/lib/vectorUtil.js
Normal file
76
src/lib/vectorUtil.js
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/* ! 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-present Henrik Ingo (@henrikingo), 2025-present 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 vectorUtil.js file. This file exposes various functions for use in calculating with vectors
|
||||||
|
|
||||||
|
class Vector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description
|
||||||
|
* @param {number} x The x-coordinate
|
||||||
|
* @param {number} y The y-coordinate
|
||||||
|
* @param {number} z The z-coordinate
|
||||||
|
* @returns {undefined} Returns nothing
|
||||||
|
*/
|
||||||
|
constructor ( x, y, z ) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.impressVectorUtil = () => {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the cross product of two vectors (https://en.wikipedia.org/wiki/Cross_product)
|
||||||
|
* @param {Vector} vec1 The first vector
|
||||||
|
* @param {Vector} vec2 The second vector
|
||||||
|
* @returns {Vector} Returns a vector object
|
||||||
|
*/
|
||||||
|
const vectorProduct = ( vec1, vec2 ) => new Vector(
|
||||||
|
( vec1.y * vec2.z ) - ( vec1.z * vec2.y ),
|
||||||
|
( vec1.z * vec2.x ) - ( vec1.x * vec2.z ),
|
||||||
|
( vec1.x * vec2.y ) - ( vec1.y * vec2.x )
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the dot product of two vectors (https://en.wikipedia.org/wiki/Dot_product)
|
||||||
|
* @param {Vector} vec1 The first vector
|
||||||
|
* @param {Vector} vec2 The second vector
|
||||||
|
* @returns {number} Returns the calculated value of the dot product
|
||||||
|
*/
|
||||||
|
const dotProduct = ( vec1, vec2 ) => ( vec1.x * vec2.x ) + ( vec1.y * vec2.y ) + ( vec1.z * vec2.z );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the norm of a vector (https://en.wikipedia.org/wiki/Norm_(mathematics))
|
||||||
|
* @param {Vector} vec The vector of which to calculate the norm
|
||||||
|
* @returns {number} Returns the norm
|
||||||
|
*/
|
||||||
|
const norm = ( vec ) => Math.sqrt( ( vec.x * vec.x ) + ( vec.y * vec.y ) + ( vec.z * vec.z ) );
|
||||||
|
|
||||||
|
|
||||||
|
const baseChange = ( angle ) => {};
|
||||||
|
|
||||||
|
return {
|
||||||
|
norm,
|
||||||
|
dotProduct,
|
||||||
|
vectorProduct
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -26,18 +26,23 @@ var loadIframe = function( src, assert, callback ) {
|
|||||||
var iframe = document.getElementById( 'presentation-iframe' );
|
var iframe = document.getElementById( 'presentation-iframe' );
|
||||||
|
|
||||||
var onLoad = function() {
|
var onLoad = function() {
|
||||||
assert.ok( true,
|
assert.ok(
|
||||||
'Presentation loaded. iframe.src = ' + iframe.src );
|
true,
|
||||||
|
'Presentation loaded. iframe.src = ' + iframe.src
|
||||||
|
);
|
||||||
try {
|
try {
|
||||||
assert.ok( iframe.contentDocument,
|
assert.ok(
|
||||||
|
iframe.contentDocument,
|
||||||
'Verifying that tests can access the presentation inside the iframe. ' +
|
'Verifying that tests can access the presentation inside the iframe. ' +
|
||||||
'Note: On Firefox this fails when using paths with "../" parts for the iframe.' );
|
'Note: On Firefox this fails when using paths with "../" parts for the iframe.'
|
||||||
}
|
);
|
||||||
catch ( err ) {
|
} catch ( err ) {
|
||||||
assert.ok( false,
|
assert.ok(
|
||||||
|
false,
|
||||||
'Error when trying to access presentation in iframe. Note: When using Chrome with ' +
|
'Error when trying to access presentation in iframe. Note: When using Chrome with ' +
|
||||||
'local files (file:///) this will fail with SecurityError. ' +
|
'local files (file:///) this will fail with SecurityError. ' +
|
||||||
'You can however use Chrome over Karma.' );
|
'You can however use Chrome over Karma.'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
console.log( 'End loadIframe' );
|
console.log( 'End loadIframe' );
|
||||||
callback();
|
callback();
|
||||||
@@ -45,8 +50,10 @@ var loadIframe = function( src, assert, callback ) {
|
|||||||
|
|
||||||
iframe.addEventListener( 'load', onLoad );
|
iframe.addEventListener( 'load', onLoad );
|
||||||
|
|
||||||
assert.ok( iframe.src = src,
|
assert.ok(
|
||||||
'Setting iframe.src = ' + src );
|
iframe.src = src,
|
||||||
|
'Setting iframe.src = ' + src
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
var initPresentation = function( assert, callback, rootId ) {
|
var initPresentation = function( assert, callback, rootId ) {
|
||||||
@@ -104,4 +111,3 @@ var _impressSupported = function() {
|
|||||||
( document.body.dataset ) &&
|
( document.body.dataset ) &&
|
||||||
( ua.search( /(iphone)|(ipod)|(android)/ ) === -1 );
|
( ua.search( /(iphone)|(ipod)|(android)/ ) === -1 );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
9
tsconfig.json
Normal file
9
tsconfig.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./built",
|
||||||
|
"allowJs": true,
|
||||||
|
"target": "ES6",
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
"include": [ "./src/**/*" ],
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user