├── .github
├── FUNDING.yml
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .eslintignore
├── .browserslistrc
├── src
├── utils
│ ├── getCoordinates.js
│ ├── isTouch.js
│ ├── clamp.js
│ ├── getCenter.js
│ ├── orientationElement.js
│ ├── inViewport.js
│ ├── scrollMovement.js
│ ├── mouseMovement.js
│ ├── elementMovement.js
│ ├── cyclicMovement.js
│ └── throttle.js
├── mixins
│ ├── perspective_mixin.js
│ ├── base_mixin.js
│ ├── motion_mixin.js
│ ├── container_events.js
│ ├── transform_mixin.js
│ └── audio_mixin.js
├── components
│ ├── index.js
│ ├── kinesis-audio.vue
│ ├── kinesis-scroll.vue
│ ├── kinesis-element.vue
│ ├── kinesis-distance.vue
│ └── kinesis-container.vue
└── entry.js
├── .editorconfig
├── babel.config.js
├── .gitignore
├── .jsconfig.json
├── LICENSE
├── .eslintrc.js
├── package.json
├── README.md
└── dist
├── vue-kinesis.min.js
├── vue-kinesis.esm.js
└── vue-kinesis.ssr.js
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [aminerman]
2 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist/*
2 |
3 | democomponents/*
4 |
5 | App.vue
--------------------------------------------------------------------------------
/.browserslistrc:
--------------------------------------------------------------------------------
1 | current node
2 | last 2 versions and > 2%
3 | ie > 10
4 |
--------------------------------------------------------------------------------
/src/utils/getCoordinates.js:
--------------------------------------------------------------------------------
1 | export default function (x, y) {
2 | return { x, y, }
3 | }
4 |
--------------------------------------------------------------------------------
/src/utils/isTouch.js:
--------------------------------------------------------------------------------
1 | export default function isTouch() {
2 | try {
3 | return /Mobi|Android/i.test(navigator.userAgent);
4 | } catch (e) {
5 | return true;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/utils/clamp.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-nested-ternary */
2 | export default function (value, min, max) {
3 | return max && value > max ? max : min && value < min ? min : value;
4 | }
5 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{js,jsx,ts,tsx,vue}]
2 | indent_style = space
3 | indent_size = 2
4 | end_of_line = lf
5 | trim_trailing_whitespace = true
6 | insert_final_newline = true
7 | max_line_length = 100
8 | quote_type = single
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | const devPresets = ['@vue/babel-preset-app'];
2 | const buildPresets = ['@babel/preset-env'];
3 | module.exports = {
4 | presets: (process.env.NODE_ENV === 'development' ? devPresets : buildPresets),
5 | };
6 |
--------------------------------------------------------------------------------
/src/utils/getCenter.js:
--------------------------------------------------------------------------------
1 | import getCoordinates from './getCoordinates';
2 |
3 | export default function (element) {
4 | return getCoordinates(
5 | element ? element.width / 2 : 0,
6 | element ? element.height / 2 : 0,
7 | );
8 | }
9 |
--------------------------------------------------------------------------------
/src/mixins/perspective_mixin.js:
--------------------------------------------------------------------------------
1 | export default {
2 | props: {
3 | perspective: {
4 | type: Number,
5 | default: 1000,
6 | },
7 | },
8 | computed: {
9 | style() {
10 | return { perspective: `${this.perspective}px` };
11 | },
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/src/utils/orientationElement.js:
--------------------------------------------------------------------------------
1 | import getCoordinates from './getCoordinates';
2 |
3 | export default function (action) {
4 | const { event, target } = action;
5 | const x = event.gamma / 45;
6 | const y = event.beta / 90;
7 |
8 | return {
9 | ...getCoordinates(x, y),
10 | target,
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 |
4 | # local env files
5 | .env.local
6 | .env.*.local
7 |
8 | # Log files
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 |
13 | # Editor directories and files
14 | .idea
15 | .vscode
16 | *.suo
17 | *.ntvs*
18 | *.njsproj
19 | *.sln
20 | *.sw?
21 |
22 | publish.txt
23 |
24 | # JEST unit test
25 | coverage
26 |
--------------------------------------------------------------------------------
/src/utils/inViewport.js:
--------------------------------------------------------------------------------
1 | export default function inViewport(element) {
2 | const isInViewport = element.bottom >= 0
3 | && element.right >= 0
4 | && element.top
5 | <= (window.innerHeight || document.documentElement.clientHeight)
6 | && element.left <= (window.innerWidth || document.documentElement.clientWidth);
7 |
8 | return isInViewport;
9 | }
10 |
--------------------------------------------------------------------------------
/src/utils/scrollMovement.js:
--------------------------------------------------------------------------------
1 | import getCoordinates from './getCoordinates'
2 |
3 | export default function (shape) {
4 | const { target, } = shape
5 | const x = (target.left - window.innerWidth) / (target.width + window.innerWidth)
6 | const y = (target.top - window.innerHeight) / (target.height + window.innerHeight)
7 | return { ...getCoordinates(x, y), target, }
8 | }
9 |
--------------------------------------------------------------------------------
/.jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": [
3 | "./src/**/*.js",
4 | "./src/**/*.vue"
5 | ],
6 | "compilerOptions": {
7 | "baseUrl": "./",
8 | "paths": {
9 | "@/*": [
10 | "src/*"
11 | ],
12 | "@dev/*": [
13 | "dev/*"
14 | ]
15 | }
16 | },
17 | "exclude": [
18 | "node_modules",
19 | "dist"
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/src/mixins/base_mixin.js:
--------------------------------------------------------------------------------
1 | export default {
2 | props: {
3 | active: {
4 | type: Boolean,
5 | default: true,
6 | },
7 | duration: {
8 | type: Number,
9 | default: 1000,
10 | },
11 | easing: {
12 | type: String,
13 | default: 'cubic-bezier(0.23, 1, 0.32, 1)',
14 | },
15 | tag: {
16 | type: String,
17 | default: 'div',
18 | },
19 | },
20 | }
21 |
--------------------------------------------------------------------------------
/src/utils/mouseMovement.js:
--------------------------------------------------------------------------------
1 | import getCoordinates from './getCoordinates';
2 | import getCenter from './getCenter';
3 |
4 | export default function (action) {
5 | const { target, event } = action;
6 | const x = event.clientX;
7 | const y = event.clientY;
8 |
9 | const relativeX = x - target.left;
10 | const relativeY = y - target.top;
11 |
12 | const center = getCenter(target);
13 |
14 | const mouseMovementX = relativeX / center.x;
15 | const mouseMovementY = relativeY / center.y;
16 |
17 | return {
18 | ...getCoordinates(mouseMovementX, mouseMovementY),
19 | target,
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **vue-kinesis and Vue.js versions
27 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/src/utils/elementMovement.js:
--------------------------------------------------------------------------------
1 | import getCoordinates from './getCoordinates'
2 | import clamp from './clamp'
3 |
4 | export default function (action) {
5 | const {
6 | y, x, target, originX = 50, strength = 10, event = null, minX, minY, maxX, maxY,
7 | } = action
8 |
9 | let { originY = 50, } = action
10 |
11 | if (event === 'scroll') {
12 | originY = -originY / 2
13 | }
14 |
15 | const movementX = clamp(
16 | (x - originX / 50) * strength,
17 | minX,
18 | maxX
19 | )
20 | const movementY = clamp(
21 | (y - originY / 50) * strength,
22 | minY,
23 | maxY
24 | )
25 |
26 | return {
27 | ...getCoordinates(movementX, movementY),
28 | target,
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/utils/cyclicMovement.js:
--------------------------------------------------------------------------------
1 | import getCoordinates from './getCoordinates'
2 |
3 | export default function (cycleData) {
4 | const {
5 | referencePosition,
6 | shape,
7 | event,
8 | cycles,
9 | strength,
10 | } = cycleData
11 |
12 | const spanningRangeX = event === 'scroll' ? window.innerWidth : shape.width
13 | const spanningRangeY = event === 'scroll' ? window.innerHeight : shape.height
14 |
15 | const radialPositionX = ((referencePosition.x - shape.left) * (Math.PI * 2)) / spanningRangeX
16 | const radialPositionY = ((referencePosition.y - shape.top) * (Math.PI * 2)) / spanningRangeY
17 |
18 | const cycleX = spanningRangeX * Math.sin(radialPositionX * cycles)
19 | const cycleY = spanningRangeY * Math.sin(radialPositionY * cycles)
20 |
21 | return getCoordinates(
22 | (cycleX * strength) / (spanningRangeX / 2),
23 | (cycleY * strength) / (spanningRangeY / 2)
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/src/utils/throttle.js:
--------------------------------------------------------------------------------
1 | export default function throttle(callback, delay, type) {
2 | let last
3 | let timer
4 | // eslint-disable-next-line func-names
5 | return function () {
6 | const context = this
7 | let newDelay
8 | if (type === 'scroll') {
9 | newDelay = delay
10 | } else {
11 | newDelay = context.duration > 1000 ? delay : context.duration / 10
12 | }
13 |
14 | const now = +new Date()
15 | // eslint-disable-next-line prefer-rest-params
16 | const args = arguments
17 | if (last && now < last + newDelay) {
18 | clearTimeout(timer)
19 | timer = setTimeout(() => {
20 | requestAnimationFrame(() => {
21 | last = now
22 | callback.apply(context, args)
23 | })
24 | }, newDelay)
25 | } else {
26 | requestAnimationFrame(() => {
27 | last = now
28 | callback.apply(context, args)
29 | })
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/components/index.js:
--------------------------------------------------------------------------------
1 | import KinesisAudio from './kinesis-audio.vue'
2 | import KinesisContainer from './kinesis-container.vue'
3 | import KinesisDistance from './kinesis-distance.vue'
4 | import KinesisElement from './kinesis-element.vue'
5 | import KinesisScroll from './kinesis-scroll.vue'
6 |
7 | const Plugin = {
8 | install(vue) {
9 | vue.component(KinesisAudio.name, KinesisAudio)
10 | vue.component(KinesisContainer.name, KinesisContainer)
11 | vue.component(KinesisDistance.name, KinesisDistance)
12 | vue.component(KinesisElement.name, KinesisElement)
13 | vue.component(KinesisScroll.name, KinesisScroll)
14 | },
15 | }
16 |
17 | let GlobalVue = null
18 |
19 | if (typeof window !== 'undefined') {
20 | GlobalVue = window.vue
21 | } else if (typeof global !== 'undefined') {
22 | GlobalVue = global.vue
23 | }
24 |
25 | if (GlobalVue) {
26 | GlobalVue.use(Plugin)
27 | }
28 |
29 | export default Plugin
30 |
31 | export {
32 | KinesisAudio,
33 | KinesisContainer,
34 | KinesisDistance,
35 | KinesisElement,
36 | KinesisScroll,
37 | }
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Amine Bouyarmane
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/mixins/motion_mixin.js:
--------------------------------------------------------------------------------
1 | export default {
2 | props: {
3 | type: {
4 | type: String,
5 | default: 'translate', // translate, rotate, scale, scaleX, scaleY, depth, depth_inv, custom
6 | },
7 | transformOrigin: {
8 | type: String,
9 | default: 'center',
10 | },
11 | originX: {
12 | type: Number,
13 | default: 50,
14 | },
15 | originY: {
16 | type: Number,
17 | default: 50,
18 | },
19 | strength: {
20 | type: Number,
21 | default: 10,
22 | },
23 | audioIndex: {
24 | type: Number,
25 | default: 50,
26 | },
27 | axis: {
28 | type: String,
29 | default: null,
30 | },
31 | maxX: {
32 | type: Number,
33 | default: null,
34 | },
35 | maxY: {
36 | type: Number,
37 | default: null,
38 | },
39 | minX: {
40 | type: Number,
41 | default: null,
42 | },
43 | minY: {
44 | type: Number,
45 | default: null,
46 | },
47 | cycle: {
48 | type: Number,
49 | default: 0,
50 | },
51 | },
52 | methods: {
53 | strengthManager() {
54 | return this.type === 'depth' || this.type === 'depth_inv'
55 | ? Math.abs(this.strength)
56 | : this.strength
57 | },
58 | },
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/src/entry.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import KinesisContainer from './components/kinesis-container.vue';
3 | import KinesisElement from './components/kinesis-element.vue';
4 | import KinesisAudio from './components/kinesis-audio.vue';
5 | import KinesisScroll from './components/kinesis-scroll.vue';
6 | import KinesisDistance from './components/kinesis-distance.vue';
7 |
8 | import * as components from './components/index';
9 |
10 | const install = function (vue) {
11 | if (install.installed) {
12 | return;
13 | }
14 | install.installed = true;
15 |
16 | for (const name in components) {
17 | vue.use(components[name]);
18 | }
19 |
20 | vue.component('kinesis-container', KinesisContainer);
21 | vue.component('kinesis-element', KinesisElement);
22 | vue.component('kinesis-audio', KinesisAudio);
23 | vue.component('kinesis-scroll', KinesisScroll);
24 | vue.component('kinesis-distance', KinesisDistance);
25 | };
26 |
27 | const Plugin = { install };
28 |
29 | let GlobalVue = null;
30 |
31 | if (typeof window !== 'undefined') {
32 | GlobalVue = window.vue;
33 | } else if (typeof global !== 'undefined') {
34 | GlobalVue = global.vue;
35 | }
36 |
37 | if (GlobalVue) {
38 | GlobalVue.use(Plugin);
39 | }
40 |
41 | export default Plugin;
42 |
43 | export {
44 | KinesisContainer, KinesisElement, KinesisScroll, KinesisAudio, KinesisDistance,
45 | };
46 |
--------------------------------------------------------------------------------
/src/mixins/container_events.js:
--------------------------------------------------------------------------------
1 | import isTouch from '../utils/isTouch'
2 |
3 | export default {
4 | props: {
5 | event: {
6 | type: String,
7 | default: 'move', // move, scroll
8 | },
9 | },
10 | data() {
11 | return {
12 | eventMap: {
13 | orientation: 'deviceorientation',
14 | scroll: 'scroll',
15 | move: isTouch() ? 'deviceorientation' : null,
16 | },
17 | }
18 | },
19 | methods: {
20 | addEvents() {
21 | if (this.eventMap[this.event]) {
22 | window.addEventListener(
23 | this.eventMap[this.event],
24 | this.handleMovement,
25 | true,
26 | )
27 | }
28 | },
29 | removeEvents() {
30 | if (this.eventMap[this.event]) {
31 | window.removeEventListener(
32 | this.eventMap[this.event],
33 | this.handleMovement,
34 | true,
35 | )
36 | }
37 | },
38 | },
39 | watch: {
40 | event(newVal, oldVal) {
41 | if (this.eventMap[newVal]) {
42 | window.addEventListener(
43 | this.eventMap[newVal],
44 | this.handleMovement,
45 | true,
46 | )
47 | }
48 | if (this.eventMap[oldVal]) {
49 | window.addEventListener(
50 | this.eventMap[oldVal],
51 | this.handleMovement,
52 | true,
53 | )
54 | }
55 | },
56 | },
57 | }
58 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | 'extends': [
7 | 'plugin:vue/recommended',
8 | '@vue/airbnb'
9 | ],
10 | parserOptions: {
11 | parser: 'babel-eslint'
12 | },
13 | rules: {
14 | "linebreak-style": ["error", (process.platform === "win32" ? "windows" : "unix")],
15 | "comma-dangle": [1, {
16 | "objects": "always",
17 | "arrays": "ignore",
18 | "imports": "ignore",
19 | "exports": "ignore",
20 | "functions": "ignore"
21 | }],
22 | 'max-len': ['warn', {
23 | code: 100,
24 | ignoreComments: true,
25 | ignoreStrings: true,
26 | // fix for svg icons
27 | ignorePattern: 'd=([s]*?)',
28 | }],
29 | semi: ['error', 'never'],
30 | quotes: ['error', 'single'],
31 | 'no-multiple-empty-lines': ['error', {
32 | max: 1,
33 | maxBOF: 1
34 | }],
35 | 'no-param-reassign': 'off',
36 | 'max-classes-per-file': 'off',
37 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
38 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
39 | 'no-unused-vars': 'warn',
40 | "consistent-return": "off",
41 | 'vue/no-unused-vars': 'off',
42 | 'vue/require-default-prop': 'off',
43 | 'import/prefer-default-export': 'off',
44 | 'import/no-extraneous-dependencies': ['error', {
45 | devDependencies: true
46 | }],
47 | },
48 | }
49 |
--------------------------------------------------------------------------------
/src/mixins/transform_mixin.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable default-case */
2 | export default {
3 | methods: {
4 | transformSwitch(type, x, y, s) {
5 | type = type === 'scaleX' || type === 'scaleY' ? 'scale' : type
6 | let transform
7 | switch (type) {
8 | case 'translate':
9 | transform = this.translateMovement(x, y)
10 | break
11 | case 'rotate':
12 | transform = this.rotateMovement(x, y)
13 | break
14 | case 'depth':
15 | transform = this.depthMovement(x, y, s)
16 | break
17 | case 'depth_inv':
18 | transform = this.depthMovement(-x, -y, s)
19 | break
20 | case 'scale':
21 | transform = this.scaleMovement(x, y)
22 | break
23 | }
24 | return transform
25 | },
26 | translateMovement(x, y) {
27 | return `translate3d(${-x}px, ${-y}px, 0)`
28 | },
29 | rotateMovement(x, y) {
30 | let movement
31 | if (!this.axis) {
32 | movement = x + y
33 | } else if (this.axis === 'x') {
34 | movement = 2 * x
35 | } else if (this.axis === 'y') {
36 | movement = 2 * y
37 | }
38 | return `rotate3d(0,0,1,${movement}deg)`
39 | },
40 | depthMovement(x, y, s) {
41 | return `rotateX(${-y}deg) rotateY(${x}deg) translate3d(0,0,${s * 2}px)`
42 | },
43 | scaleMovement(x, y) {
44 | const { type, } = this
45 | const movement = (Math.sign(this.strength) * (Math.abs(x) + Math.abs(y))) / 10 + 1
46 | return `scale3d(${type === 'scaleX' || type === 'scale' ? movement : 1},
47 | ${type === 'scaleY' || type === 'scale' ? movement : 1},
48 | 1)`
49 | },
50 | },
51 | }
52 |
--------------------------------------------------------------------------------
/src/mixins/audio_mixin.js:
--------------------------------------------------------------------------------
1 | export default {
2 | props: {
3 | audio: {
4 | type: String,
5 | required: false,
6 | },
7 | playAudio: {
8 | type: Boolean,
9 | default: false,
10 | },
11 | },
12 | data() {
13 | return {
14 | analyser: null,
15 | audioArray: null,
16 | audioData: null,
17 | audioRef: null,
18 | wasPlayed: false,
19 | isPlaying: false,
20 | }
21 | },
22 | watch: {
23 | audio() {
24 | this.wasPlayed = false
25 | this.isPlaying = false
26 | },
27 | playAudio(play) {
28 | if (play) {
29 | this.play()
30 | } else {
31 | this.stop()
32 | }
33 | },
34 | },
35 | methods: {
36 | play() {
37 | if (!this.active) return
38 | if (!this.wasPlayed) {
39 | this.handleAudio()
40 | this.wasPlayed = true
41 | }
42 | this.isPlaying = true
43 | this.audioRef.play()
44 | this.getSongData()
45 | },
46 | stop() {
47 | this.isPlaying = false
48 | this.audioRef.pause()
49 | },
50 | handleAudio() {
51 | const { audio, } = this.$refs
52 | this.audioRef = audio
53 | const context = new AudioContext()
54 | const src = context.createMediaElementSource(audio)
55 | const analyser = context.createAnalyser()
56 | src.connect(analyser)
57 | analyser.connect(context.destination)
58 | analyser.fftSize = 256
59 | const bufferLength = analyser.frequencyBinCount
60 | const audioArray = new Uint8Array(bufferLength)
61 | this.audioArray = audioArray
62 | this.analyser = analyser
63 | },
64 | getSongData() {
65 | if (this.isPlaying) {
66 | this.analyser.getByteFrequencyData(this.audioArray)
67 |
68 | this.audioData = new Array(this.audioArray) // @Todo reactivity issue
69 |
70 | requestAnimationFrame(this.getSongData)
71 | }
72 | },
73 | },
74 | }
75 |
--------------------------------------------------------------------------------
/src/components/kinesis-audio.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
87 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-kinesis",
3 | "version": "1.3.3",
4 | "description": "Easily create complexe interactive animations with Vue.js",
5 | "author": {
6 | "name": "Amine Bouyarmane",
7 | "email": "amine.bouyarmane@gmail.com"
8 | },
9 | "scripts": {
10 | "serve": "vue-cli-service serve dev/serve.js",
11 | "build": "cross-env NODE_ENV=production rollup --config build/rollup.config.js",
12 | "lint": "vue-cli-service lint",
13 | "build:es": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format es",
14 | "build:ssr": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format cjs",
15 | "build:unpkg": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format iife"
16 | },
17 | "main": "dist/vue-kinesis.ssr.js",
18 | "module": "dist/vue-kinesis.esm.js",
19 | "browser": "dist/vue-kinesis.esm.js",
20 | "unpkg": "dist/vue-kinesis.min.js",
21 | "files": [
22 | "dist/*",
23 | "src/**/*.vue"
24 | ],
25 | "dependencies": {},
26 | "devDependencies": {
27 | "@babel/core": "^7.14.5",
28 | "@babel/preset-env": "^7.14.5",
29 | "@rollup/plugin-alias": "^2.2.0",
30 | "@rollup/plugin-commonjs": "^11.1.0",
31 | "@rollup/plugin-replace": "^2.4.2",
32 | "@vue/cli-plugin-babel": "^4.5.13",
33 | "@vue/cli-plugin-eslint": "^4.5.13",
34 | "@vue/cli-service": "^4.5.13",
35 | "@vue/eslint-config-airbnb": "^5.0.2",
36 | "babel-eslint": "^10.1.0",
37 | "cross-env": "^7.0.2",
38 | "eslint": "^6.7.2",
39 | "eslint-plugin-import": "^2.23.4",
40 | "eslint-plugin-vue": "^6.2.2",
41 | "lint-staged": "^9.5.0",
42 | "minimist": "^1.2.5",
43 | "rollup": "^2.51.2",
44 | "rollup-plugin-babel": "^4.4.0",
45 | "rollup-plugin-terser": "^5.3.0",
46 | "rollup-plugin-vue": "^5.1.9",
47 | "vue": "^2.6.14",
48 | "vue-template-compiler": "^2.6.14"
49 | },
50 | "peerDependencies": {
51 | "vue": "^2.6.11"
52 | },
53 | "engines": {
54 | "node": ">=10"
55 | },
56 | "gitHooks": {
57 | "pre-commit": "lint-staged"
58 | },
59 | "keywords": [
60 | "frontend",
61 | "animation",
62 | "interaction",
63 | "vue",
64 | "vue.js",
65 | "parallax",
66 | "mouse",
67 | "hover",
68 | "scroll",
69 | "gyroscope",
70 | "audio"
71 | ],
72 | "licence": "MIT",
73 | "lint-staged": {
74 | "*.{js,jsx,vue}": [
75 | "vue-cli-service lint",
76 | "git add"
77 | ]
78 | },
79 | "repository": {
80 | "type": "git",
81 | "url": "https://github.com/Aminerman/vue-kinesis"
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/components/kinesis-scroll.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
125 |
--------------------------------------------------------------------------------
/src/components/kinesis-element.vue:
--------------------------------------------------------------------------------
1 |
146 |
--------------------------------------------------------------------------------
/src/components/kinesis-distance.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
172 |
--------------------------------------------------------------------------------
/src/components/kinesis-container.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
20 |
21 |
180 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # October 2024: A full TS version is now available [KinesisJS](https://kinesisjs.com). You can use it in your vue projects if you need any of the new features. It works with Vue but a dedicated Vue version is in the works.
2 | # March 2024: The project has been on standby for a while now. But good news! I'm working on a brand new version, more robust, with better documentation and more features!
3 | What's in preparation:
4 | - Rewriting everything in TS
5 | - New interactions
6 | - A detailed documentation
7 | - A vanilla TS version
8 |
9 | # vue-kinesis
10 |
11 | [](https://img.shields.io/npm/v/vue-kinesis.svg)
12 | [](https://vuejs.org/)
13 | [](https://vuejs.org/)
14 |
15 | Easy to use Vue.js components for creating interactive animations
16 |
17 | ## Demo
18 |
19 | [Kinesis Demo](https://aminerman.com/kinesis/)
20 |
21 | ## Tutorials
22 |
23 | - [LogRocket - Top 5 Vue Animation Libraries](https://blog.logrocket.com/top-5-vue-animation-libraries-compared/)
24 | - [LogRocket - Interactive Vue Animations with Kinesis](https://blog.logrocket.com/interactive-vue-animations-with-kinesis/)
25 | - [Leonardo Gruppelli - Kinesis Animation for Nuxt](https://medium.com/@leonardo.gruppelli/kinesis-awesome-animations-for-your-vue-nuxt-applications-8c16ae701e92)
26 | - [Coliss - 便利なのが登場!Vue.jsでインタラクティブなアニメーションを簡単に実装できる軽量コンポーネント -Kinesis](https://coliss.com/articles/build-websites/operation/javascript/interactive-animations-with-vue-js-kinesis.html)
27 | - [Kabanoki - コイツ動くぞ?!的なアニメーションが付けられる「vue-kinesis」](https://www.kabanoki.net/5792/)
28 | - [Mebee - Nuxt.js vue-kinesisを使用してアニメーションをかける](https://mebee.info/2020/05/18/post-6592/)
29 | - ... Feel free to open a PR if you want to suggest a tutorial link 🙏
30 |
31 |
32 | # Vue3 - Installation
33 |
34 | ```
35 | npm install --save vue-kinesis@next
36 | ```
37 |
38 | ## Vue3 - Default import
39 |
40 | Install all the components:
41 |
42 | ```javascript
43 | import { createApp } from "vue";
44 | import App from "./App.vue";
45 | import VueKinesis from "vue-kinesis";
46 |
47 | const app = createApp(App);
48 | app.use(VueKinesis);
49 |
50 | app.mount("#app");
51 | ```
52 |
53 | # Vue2 - Installation
54 |
55 | ```
56 | npm install --save vue-kinesis
57 | ```
58 |
59 | ## Vue2 - Default import
60 |
61 | Install all the components:
62 |
63 | ```javascript
64 | import Vue from 'vue'
65 | import VueKinesis from 'vue-kinesis'
66 |
67 | Vue.use(VueKinesis)
68 | ```
69 |
70 | Use specific components:
71 |
72 | ```javascript
73 | import Vue from 'vue'
74 | import { KinesisContainer, KinesisElement } from 'vue-kinesis'
75 |
76 | Vue.component('kinesis-container', KinesisContainer)
77 | Vue.component('kinesis-element', KinesisElement)
78 | ```
79 |
80 | ## Browser
81 |
82 | ```html
83 |
84 |
85 | ```
86 |
87 |
88 | # Usage
89 |
90 | [How to use](https://aminerman.com/kinesis/)
91 |
92 |
93 | ## Props
94 |
95 | ### kinesis-container
96 |
97 | | Prop | Type | Default Value | Description
98 | |----------|:-------------:|------|------|
99 | | active | Boolean | true | To enable or disable the interactions |
100 | | duration | Number | 1000 | Speed of the parallax animation in ms |
101 | | easing | String | "cubic-bezier(0.23, 1, 0.32, 1)" | Easing of the parallax animation |
102 | | tag | String | div | Takes any valid html tag |
103 | | event | String | "move" | Event to which the container will react. Possible values are "move" and "scroll" |
104 | | perspective | Number | 1000 | Effective for the 'depth' parallax type |
105 | | audio | String | | Path towards an audio file |
106 | | playAudio | Boolean | | Start/Stop the attached audio file |
107 |
108 | ### kinesis-element
109 | | Prop | Type | Default Value | Description
110 | |----------|:-------------:|------|------|
111 | | strength | Number | 10 | Strength of the motion effect |
112 | | type | String | "translate" | translate - rotate - scale - scaleX - scaleY - depth - depth_inv |
113 | | tag | String | "div" | Takes any valid html tag |
114 | | transformOrigin | String | "center" | Similar to the CSS transform-origin property |
115 | | originX | Number | 50 | The motion's origin relative to the container, on the X axis. 50 being the center of the container, 0 the left side, 100 the right side. |
116 | | originY | Number | 50 | The motion's origin relative to the container, on the Y axis. 50 being the center of the container, 0 the top side, 100 the bottom side. |
117 | | axis | String | null | Constrain the movement to one axis. Possible values: "x" - "y" |
118 | | maxX | Number | null | Limit the maximum range of the movement on the X axis |
119 | | maxY | Number | null | Limit the maximum range of the movement on the Y axis |
120 | | minX | Number | null | Limit the minimum range of the movement on the X axis |
121 | | minY | Number | null | Limit the minimum range of the movement on the Y axis |
122 | | cycle | Number | 0 | How many times the movement will repeat |
123 |
124 | ### kinesis-audio
125 | | Prop | Type | Default Value | Description
126 | |----------|:-------------:|------|------|
127 | | audioIndex | Number | 50 | To which frequency to react, on a range of integer values that goes from 0 to 127. |
128 | | strength | Number | 10 | Strength of the motion effect |
129 | | type | String | "translate" | translate - rotate - scale - scaleX - scaleY - depth - depth_inv |
130 | | tag | String | "div" | Takes any valid html tag |
131 | | transformOrigin | String | "center" | Similar to the CSS transform-origin property |
132 | | originX | Number | 50 | The motion's origin relative to the container, on the X axis. 50 being the center of the container, 0 the left side, 100 the right side. |
133 | | originY | Number | 50 | The motion's origin relative to the container, on the Y axis. 50 being the center of the container, 0 the top side, 100 the bottom side. |
134 | | axis | String | null | Constrain the movement to one axis. Possible values: "x" - "y" |
135 | | maxX | Number | null | Limit the maximum range of the movement on the X axis |
136 | | maxY | Number | null | Limit the maximum range of the movement on the Y axis |
137 | | minX | Number | null | Limit the minimum range of the movement on the X axis |
138 | | minY | Number | null | Limit the minimum range of the movement on the Y axis |
139 | | cycle | Number | 0 | How many times the movement will repeat |
140 |
141 | ## Migrating from vue-mouse-parallax
142 | Migration from vue-mouse-parallax is quite easy:
143 |
144 | ### Components
145 | - parallax-container -> kinesis-container
146 | - parallax-element -> kinesis-element
147 |
148 | ### Props
149 | - parallaxStrength -> strength
150 | - animationDuration -> duration
151 |
152 | ### Prop values
153 | - translation -> translate
154 | - rotation -> rotate
155 |
156 | ## License
157 |
158 | [MIT](http://opensource.org/licenses/MIT)
159 |
--------------------------------------------------------------------------------
/dist/vue-kinesis.min.js:
--------------------------------------------------------------------------------
1 | var VueKinesis=function(t){"use strict";function e(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,i)}return n}function n(t){for(var n=1;n=0&&t.right>=0&&t.top<=(window.innerHeight||document.documentElement.clientHeight)&&t.left<=(window.innerWidth||document.documentElement.clientWidth)}function u(){try{return/Mobi|Android/i.test(navigator.userAgent)}catch(t){return!0}}function h(t,e,n){var i,r;return function(){var a,o=this;a="scroll"===n||o.duration>1e3?e:o.duration/10;var s=+new Date,c=arguments;i&&sn?n:e&&t0&&(t="x"===this.axis?g:0,e="y"===this.axis?y:0),{transform:this.transformSwitch(this.type,t,e,this.strength)}},strengthManager:function(){return"depth"===this.type||"depth_inv"===this.type?Math.abs(this.strength):this.strength}},render:function(t){return t(this.tag,{style:n(n({},this.transform),this.transformParameters)},this.$slots.default)}},void 0,void 0,void 0,!1,void 0,void 0,void 0),p={props:{type:{type:String,default:"translate"},transformOrigin:{type:String,default:"center"},originX:{type:Number,default:50},originY:{type:Number,default:50},strength:{type:Number,default:10},audioIndex:{type:Number,default:50},axis:{type:String,default:null},maxX:{type:Number,default:null},maxY:{type:Number,default:null},minX:{type:Number,default:null},minY:{type:Number,default:null},cycle:{type:Number,default:0}},methods:{strengthManager:function(){return"depth"===this.type||"depth_inv"===this.type?Math.abs(this.strength):this.strength}}},g=l({render:function(){var t=this.$createElement;return(this._self._c||t)(this.tag,{tag:"component",style:Object.assign({},this.transform,this.transformParameters)},[this._t("default")],2)},staticRenderFns:[]},void 0,{name:"KinesisAudio",inject:["context"],mixins:[p],props:{tag:{type:String,default:"div"},audioIndex:{type:Number,default:50}},computed:{transform:function(){return this.transformAudio()},transformParameters:function(){return{transitionProperty:"transform",transitionDuration:this.transitionDuration,transformOrigin:this.transformOrigin,transitionTimingFunction:this.transitionTimingFunction}},transitionDuration:function(){var t=this.context.duration;return"".concat(t,"ms")},transitionTimingFunction:function(){return this.context.easing}},methods:{transformAudio:function(){var t=this.context.audioData;if(t){var e,n,i=this.type,r=this.strength;switch(i){case"translate":e=t?t[0][this.audioIndex]:0,n="translate3d(".concat(e*r,"px, 0, 0)");break;case"rotate":e=t?t[0][this.audioIndex]:0,n="rotate3d(0,0,1,".concat(e*r/10,"deg)");break;case"scale":e=t?t[0][this.audioIndex]/r<1?1:t[0][this.audioIndex]/(2*r):1,n="scale(".concat(e,")")}return{transform:n}}}}},void 0,!1,void 0,!1,void 0,void 0,void 0),y=l({render:function(){var t=this.$createElement;return(this._self._c||t)(this.tag,{tag:"component",style:Object.assign({},this.transform,this.transformParameters)},[this._t("default")],2)},staticRenderFns:[]},void 0,{name:"KinesisScroll",mixins:[{props:{active:{type:Boolean,default:!0},duration:{type:Number,default:1e3},easing:{type:String,default:"cubic-bezier(0.23, 1, 0.32, 1)"},tag:{type:String,default:"div"}}},{props:{perspective:{type:Number,default:1e3}},computed:{style:function(){return{perspective:"".concat(this.perspective,"px")}}}},p,m],data:function(){return{transform:{}}},computed:{transformParameters:function(){return{transitionProperty:"transform",transitionDuration:this.transitionDuration,transformOrigin:this.transformOrigin,transitionTimingFunction:this.easing}},transitionDuration:function(){return"".concat(this.duration,"ms")}},mounted:function(){window.addEventListener("scroll",this.handleScroll,{passive:!0})},beforeDestroy:function(){window.removeEventListener("scroll",this.handleScroll,{passive:!0})},methods:{getCycleMovement:function(t,e,n,i,r){var a=(t-r.left)*(2*Math.PI)/n,o=(e-r.top)*(2*Math.PI)/i;this.cycleMovement={x:a,y:o,width:n,height:i}},handleScroll:h((function(){if(this.active){var t=this.$el.getBoundingClientRect();c(t)&&t.height&&this.transformBehavior(t)}}),19,"scroll"),transformBehavior:function(t){var e,n,i=(t.top-window.innerHeight)/(t.height+window.innerHeight);if(this.cycle<=0){var r=i*this.strength;e="x"===this.axis?r:0,n="y"!==this.axis&&this.axis?0:r,this.maxX&&(e=Math.min(e,this.maxX)),this.minX&&(e=Math.max(e,this.minX)),this.maxY&&(n=Math.min(n,this.maxY)),this.minY&&(n=Math.max(n,this.minY))}else if(this.cycle>0){var a=this.getCycleMovement(0,0,window.innerWidth,window.innerHeight,t),o=a.x,s=a.y,c=a.width,u=a.height,h=c*Math.sin(o*this.cycle),l=u*Math.sin(s*this.cycle);e="x"===this.axis?h/(c/2)*this.strength:0,n="y"!==this.axis&&this.axis?0:l/(u/2)*this.strength}var d=this.type;d="scaleX"===d||"scaleY"===d?"scale":d;var f=this.transformSwitch(d,e,n,this.strength);this.transform={transform:f}}}},void 0,!1,void 0,!1,void 0,void 0,void 0),b=l({render:function(){var t=this.$createElement;return(this._self._c||t)(this.tag,{tag:"component",style:Object.assign({},this.transform,this.transformParameters)},[this._t("default")],2)},staticRenderFns:[]},void 0,{name:"KinesisDistance",props:{tag:{type:String,default:"div"},type:{type:String,default:"translate"},transformOrigin:{type:String,default:"center"},originX:{type:Number,default:50},originY:{type:Number,default:50},strength:{type:Number,default:10},axis:{type:String,default:null},maxX:{type:Number,default:null},maxY:{type:Number,default:null},minX:{type:Number,default:null},minY:{type:Number,default:null},distance:{type:Number,default:100},cycle:{type:Number,default:0},active:{type:Boolean,default:!0},duration:{type:Number,default:1001},easing:{type:String,default:"cubic-bezier(0.23, 1, 0.32, 1)"},perspective:{type:Number,default:1e3}},data:function(){return{pointer:{x:0,y:0},transform:{},component:"kidistance",throttle:500}},computed:{style:function(){return{perspective:"".concat(this.perspective,"px")}},transformParameters:function(){return{position:"relative",transitionProperty:"transform",transitionDuration:this.transitionDuration,transformOrigin:this.transformOrigin,transitionTimingFunction:this.easing}},transitionDuration:function(){return"".concat(this.duration,"ms")}},mounted:function(){window.addEventListener("scroll",this.handleMovement)},beforeDestroy:function(){window.removeEventListener("scroll",this.handleMovement)},methods:{getCoordinates:function(t,e){var n=this.$el.getBoundingClientRect();return{x:t+n.left,y:e+n.top}},getDistance:function(t,e,n,i){return Math.floor(Math.hypot(e-t,i-n))},handleMovement:h((function(t){window.addEventListener("mousemove",this.handleMovement);var e=this.pointer;e.x=t.clientX,e.y=t.clientY,this.transformBehavior()}),50),transformBehavior:function(){var t=this.$el.getBoundingClientRect(),e=this.getCoordinates(t.width/2,t.height/2),n=this.getDistance(this.pointer.x,e.x,this.pointer.y,e.y);if(n>this.distance)return this.transform={},void(this.throttle=500);this.throttle=50;var i="scale(".concat(n/this.distance,")");this.transform={transform:i}},scaleMovement:function(t,e){var n=this.type,i=Math.sign(this.strength)*(Math.abs(t)+Math.abs(e))/10+1;return"scale3d(".concat("scaleX"===n||"scale"===n?i:1,",\n ").concat("scaleY"===n||"scale"===n?i:1,",\n 1)")}}},void 0,!1,void 0,!1,void 0,void 0,void 0),x={install:function(t){t.component(g.name,g),t.component(d.name,d),t.component(b.name,b),t.component(v.name,v),t.component(y.name,y)}},w=null;"undefined"!=typeof window?w=window.vue:"undefined"!=typeof global&&(w=global.vue),w&&w.use(x);var M=Object.freeze({__proto__:null,default:x,KinesisAudio:g,KinesisContainer:d,KinesisDistance:b,KinesisElement:v,KinesisScroll:y}),S={install:function t(e){if(!t.installed){for(var n in t.installed=!0,M)e.use(M[n]);e.component("kinesis-container",d),e.component("kinesis-element",v),e.component("kinesis-audio",g),e.component("kinesis-scroll",y),e.component("kinesis-distance",b)}}},O=null;return"undefined"!=typeof window?O=window.vue:"undefined"!=typeof global&&(O=global.vue),O&&O.use(S),t.KinesisAudio=g,t.KinesisContainer=d,t.KinesisDistance=b,t.KinesisElement=v,t.KinesisScroll=y,t.default=S,Object.defineProperty(t,"__esModule",{value:!0}),t}({});
--------------------------------------------------------------------------------
/dist/vue-kinesis.esm.js:
--------------------------------------------------------------------------------
1 | function getCoordinates (x, y) {
2 | return {
3 | x,
4 | y
5 | };
6 | }
7 |
8 | function getCenter (element) {
9 | return getCoordinates(element ? element.width / 2 : 0, element ? element.height / 2 : 0);
10 | }
11 |
12 | function mouseMovement (action) {
13 | const {
14 | target,
15 | event
16 | } = action;
17 | const x = event.clientX;
18 | const y = event.clientY;
19 | const relativeX = x - target.left;
20 | const relativeY = y - target.top;
21 | const center = getCenter(target);
22 | const mouseMovementX = relativeX / center.x;
23 | const mouseMovementY = relativeY / center.y;
24 | return { ...getCoordinates(mouseMovementX, mouseMovementY),
25 | target
26 | };
27 | }
28 |
29 | function scrollMovement (shape) {
30 | const {
31 | target
32 | } = shape;
33 | const x = (target.left - window.innerWidth) / (target.width + window.innerWidth);
34 | const y = (target.top - window.innerHeight) / (target.height + window.innerHeight);
35 | return { ...getCoordinates(x, y),
36 | target
37 | };
38 | }
39 |
40 | function orientationElement (action) {
41 | const {
42 | event,
43 | target
44 | } = action;
45 | const x = event.gamma / 45;
46 | const y = event.beta / 90;
47 | return { ...getCoordinates(x, y),
48 | target
49 | };
50 | }
51 |
52 | function inViewport(element) {
53 | const isInViewport = element.bottom >= 0 && element.right >= 0 && element.top <= (window.innerHeight || document.documentElement.clientHeight) && element.left <= (window.innerWidth || document.documentElement.clientWidth);
54 | return isInViewport;
55 | }
56 |
57 | function isTouch() {
58 | try {
59 | return /Mobi|Android/i.test(navigator.userAgent);
60 | } catch (e) {
61 | return true;
62 | }
63 | }
64 |
65 | function throttle(callback, delay, type) {
66 | let last;
67 | let timer; // eslint-disable-next-line func-names
68 |
69 | return function () {
70 | const context = this;
71 | let newDelay;
72 |
73 | if (type === 'scroll') {
74 | newDelay = delay;
75 | } else {
76 | newDelay = context.duration > 1000 ? delay : context.duration / 10;
77 | }
78 |
79 | const now = +new Date(); // eslint-disable-next-line prefer-rest-params
80 |
81 | const args = arguments;
82 |
83 | if (last && now < last + newDelay) {
84 | clearTimeout(timer);
85 | timer = setTimeout(() => {
86 | requestAnimationFrame(() => {
87 | last = now;
88 | callback.apply(context, args);
89 | });
90 | }, newDelay);
91 | } else {
92 | requestAnimationFrame(() => {
93 | last = now;
94 | callback.apply(context, args);
95 | });
96 | }
97 | };
98 | }
99 |
100 | var audioMixin = {
101 | props: {
102 | audio: {
103 | type: String,
104 | required: false
105 | },
106 | playAudio: {
107 | type: Boolean,
108 | default: false
109 | }
110 | },
111 |
112 | data() {
113 | return {
114 | analyser: null,
115 | audioArray: null,
116 | audioData: null,
117 | audioRef: null,
118 | wasPlayed: false,
119 | isPlaying: false
120 | };
121 | },
122 |
123 | watch: {
124 | audio() {
125 | this.wasPlayed = false;
126 | this.isPlaying = false;
127 | },
128 |
129 | playAudio(play) {
130 | if (play) {
131 | this.play();
132 | } else {
133 | this.stop();
134 | }
135 | }
136 |
137 | },
138 | methods: {
139 | play() {
140 | if (!this.active) return;
141 |
142 | if (!this.wasPlayed) {
143 | this.handleAudio();
144 | this.wasPlayed = true;
145 | }
146 |
147 | this.isPlaying = true;
148 | this.audioRef.play();
149 | this.getSongData();
150 | },
151 |
152 | stop() {
153 | this.isPlaying = false;
154 | this.audioRef.pause();
155 | },
156 |
157 | handleAudio() {
158 | const {
159 | audio
160 | } = this.$refs;
161 | this.audioRef = audio;
162 | const context = new AudioContext();
163 | const src = context.createMediaElementSource(audio);
164 | const analyser = context.createAnalyser();
165 | src.connect(analyser);
166 | analyser.connect(context.destination);
167 | analyser.fftSize = 256;
168 | const bufferLength = analyser.frequencyBinCount;
169 | const audioArray = new Uint8Array(bufferLength);
170 | this.audioArray = audioArray;
171 | this.analyser = analyser;
172 | },
173 |
174 | getSongData() {
175 | if (this.isPlaying) {
176 | this.analyser.getByteFrequencyData(this.audioArray);
177 | this.audioData = new Array(this.audioArray); // @Todo reactivity issue
178 |
179 | requestAnimationFrame(this.getSongData);
180 | }
181 | }
182 |
183 | }
184 | };
185 |
186 | //
187 | var script$4 = {
188 | name: 'KinesisContainer',
189 | mixins: [audioMixin],
190 | props: {
191 | tag: {
192 | type: String,
193 | default: 'div'
194 | },
195 | event: {
196 | type: String,
197 | default: 'move'
198 | },
199 | active: {
200 | type: Boolean,
201 | default: true
202 | },
203 | duration: {
204 | type: Number,
205 | default: 1000
206 | },
207 | easing: {
208 | type: String,
209 | default: 'cubic-bezier(0.23, 1, 0.32, 1)'
210 | },
211 | perspective: {
212 | type: Number,
213 | default: 1000
214 | }
215 | },
216 |
217 | provide() {
218 | const context = {};
219 | const providedProps = ['audioData', 'duration', 'easing', 'event', 'eventData', 'isMoving', 'movement', 'shape'];
220 | providedProps.forEach(prop => Object.defineProperty(context, prop, {
221 | enumerable: true,
222 | get: () => this[prop]
223 | }));
224 | return {
225 | context
226 | };
227 | },
228 |
229 | data() {
230 | var _this$$el;
231 |
232 | return {
233 | shape: (_this$$el = this.$el) === null || _this$$el === void 0 ? void 0 : _this$$el.getBoundingClientRect(),
234 | isMoving: false,
235 | leftOnce: false,
236 | movement: {
237 | x: 0,
238 | y: 0
239 | },
240 | eventMap: {
241 | orientation: 'deviceorientation',
242 | scroll: 'scroll',
243 | move: isTouch() ? 'deviceorientation' : null
244 | }
245 | };
246 | },
247 |
248 | computed: {
249 | eventActions() {
250 | var _this$shape;
251 |
252 | return {
253 | move: {
254 | action: mouseMovement,
255 | condition: this.isMoving && !isTouch(),
256 | type: isTouch() ? 'deviceorientation' : null
257 | },
258 | scroll: {
259 | action: scrollMovement,
260 | condition: !!((_this$shape = this.shape) !== null && _this$shape !== void 0 && _this$shape.height),
261 | type: 'scroll'
262 | },
263 | orientation: {
264 | action: orientationElement,
265 | condition: this.event === 'move' && isTouch(),
266 | type: 'deviceorientation'
267 | }
268 | };
269 | },
270 |
271 | style() {
272 | return {
273 | perspective: `${this.perspective}px`
274 | };
275 | }
276 |
277 | },
278 |
279 | mounted() {
280 | this.addEvents();
281 | },
282 |
283 | beforeDestroy() {
284 | this.removeEvents();
285 | },
286 |
287 | methods: {
288 | handleMovementStart() {
289 | if (!this.active) return;
290 | this.isMoving = true;
291 | },
292 |
293 | handleMovementStop() {
294 | if (!this.active) return; // fixes the specific case when mouseenter didn't trigger on page refresh
295 |
296 | this.leftOnce = true;
297 | this.isMoving = false;
298 | },
299 |
300 | // eslint-disable-next-line func-names
301 | handleMovement: throttle(function (event) {
302 | if (!this.active) return;
303 |
304 | if (!this.isMoving && !this.leftOnce) {
305 | // fixes the specific case when mouseenter didn't trigger on page refresh
306 | this.handleMovementStart();
307 | }
308 |
309 | this.shape = this.$el.getBoundingClientRect();
310 | const isInViewport = inViewport(this.shape);
311 | const eventCondition = this.eventActions[this.event].condition;
312 | const eventAction = this.eventActions[this.event].action;
313 |
314 | if (isInViewport && eventCondition) {
315 | this.movement = eventAction({
316 | target: this.shape,
317 | event
318 | });
319 | this.eventData = getCoordinates(event.clientX, event.clientY);
320 | }
321 | }, 100),
322 |
323 | addEvents() {
324 | if (this.eventMap[this.event]) {
325 | window.addEventListener(this.eventMap[this.event], this.handleMovement, true);
326 | }
327 | },
328 |
329 | removeEvents() {
330 | if (this.eventMap[this.event]) {
331 | window.removeEventListener(this.eventMap[this.event], this.handleMovement, true);
332 | }
333 | }
334 |
335 | }
336 | };
337 |
338 | function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
339 | if (typeof shadowMode !== 'boolean') {
340 | createInjectorSSR = createInjector;
341 | createInjector = shadowMode;
342 | shadowMode = false;
343 | }
344 | // Vue.extend constructor export interop.
345 | const options = typeof script === 'function' ? script.options : script;
346 | // render functions
347 | if (template && template.render) {
348 | options.render = template.render;
349 | options.staticRenderFns = template.staticRenderFns;
350 | options._compiled = true;
351 | // functional template
352 | if (isFunctionalTemplate) {
353 | options.functional = true;
354 | }
355 | }
356 | // scopedId
357 | if (scopeId) {
358 | options._scopeId = scopeId;
359 | }
360 | let hook;
361 | if (moduleIdentifier) {
362 | // server build
363 | hook = function (context) {
364 | // 2.3 injection
365 | context =
366 | context || // cached call
367 | (this.$vnode && this.$vnode.ssrContext) || // stateful
368 | (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional
369 | // 2.2 with runInNewContext: true
370 | if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
371 | context = __VUE_SSR_CONTEXT__;
372 | }
373 | // inject component styles
374 | if (style) {
375 | style.call(this, createInjectorSSR(context));
376 | }
377 | // register component module identifier for async chunk inference
378 | if (context && context._registeredComponents) {
379 | context._registeredComponents.add(moduleIdentifier);
380 | }
381 | };
382 | // used by ssr in case component is cached and beforeCreate
383 | // never gets called
384 | options._ssrRegister = hook;
385 | }
386 | else if (style) {
387 | hook = shadowMode
388 | ? function (context) {
389 | style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot));
390 | }
391 | : function (context) {
392 | style.call(this, createInjector(context));
393 | };
394 | }
395 | if (hook) {
396 | if (options.functional) {
397 | // register for functional component in vue file
398 | const originalRender = options.render;
399 | options.render = function renderWithStyleInjection(h, context) {
400 | hook.call(context);
401 | return originalRender(h, context);
402 | };
403 | }
404 | else {
405 | // inject component registration as beforeCreate hook
406 | const existing = options.beforeCreate;
407 | options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
408 | }
409 | }
410 | return script;
411 | }
412 |
413 | /* script */
414 | const __vue_script__$4 = script$4;
415 | /* template */
416 |
417 | var __vue_render__$3 = function () {
418 | var _vm = this;
419 |
420 | var _h = _vm.$createElement;
421 |
422 | var _c = _vm._self._c || _h;
423 |
424 | return _c(_vm.tag, {
425 | tag: "component",
426 | style: _vm.style,
427 | on: {
428 | "mousemove": _vm.handleMovement,
429 | "mouseenter": _vm.handleMovementStart,
430 | "mouseleave": _vm.handleMovementStop
431 | }
432 | }, [_vm._t("default"), _vm._v(" "), _vm.audio ? _c('audio', {
433 | ref: "audio",
434 | attrs: {
435 | "type": "audio/mpeg"
436 | },
437 | on: {
438 | "ended": _vm.stop
439 | }
440 | }, [_c('source', {
441 | attrs: {
442 | "src": _vm.audio
443 | }
444 | })]) : _vm._e()], 2);
445 | };
446 |
447 | var __vue_staticRenderFns__$3 = [];
448 | /* style */
449 |
450 | const __vue_inject_styles__$4 = undefined;
451 | /* scoped */
452 |
453 | const __vue_scope_id__$4 = undefined;
454 | /* module identifier */
455 |
456 | const __vue_module_identifier__$4 = undefined;
457 | /* functional template */
458 |
459 | const __vue_is_functional_template__$4 = false;
460 | /* style inject */
461 |
462 | /* style inject SSR */
463 |
464 | /* style inject shadow dom */
465 |
466 | const __vue_component__$4 = /*#__PURE__*/normalizeComponent({
467 | render: __vue_render__$3,
468 | staticRenderFns: __vue_staticRenderFns__$3
469 | }, __vue_inject_styles__$4, __vue_script__$4, __vue_scope_id__$4, __vue_is_functional_template__$4, __vue_module_identifier__$4, false, undefined, undefined, undefined);
470 |
471 | /* eslint-disable no-nested-ternary */
472 | function clamp (value, min, max) {
473 | return max && value > max ? max : min && value < min ? min : value;
474 | }
475 |
476 | function elementMovement (action) {
477 | const {
478 | y,
479 | x,
480 | target,
481 | originX = 50,
482 | strength = 10,
483 | event = null,
484 | minX,
485 | minY,
486 | maxX,
487 | maxY
488 | } = action;
489 | let {
490 | originY = 50
491 | } = action;
492 |
493 | if (event === 'scroll') {
494 | originY = -originY / 2;
495 | }
496 |
497 | const movementX = clamp((x - originX / 50) * strength, minX, maxX);
498 | const movementY = clamp((y - originY / 50) * strength, minY, maxY);
499 | return { ...getCoordinates(movementX, movementY),
500 | target
501 | };
502 | }
503 |
504 | /* eslint-disable default-case */
505 | var transformMixin = {
506 | methods: {
507 | transformSwitch(type, x, y, s) {
508 | type = type === 'scaleX' || type === 'scaleY' ? 'scale' : type;
509 | let transform;
510 |
511 | switch (type) {
512 | case 'translate':
513 | transform = this.translateMovement(x, y);
514 | break;
515 |
516 | case 'rotate':
517 | transform = this.rotateMovement(x, y);
518 | break;
519 |
520 | case 'depth':
521 | transform = this.depthMovement(x, y, s);
522 | break;
523 |
524 | case 'depth_inv':
525 | transform = this.depthMovement(-x, -y, s);
526 | break;
527 |
528 | case 'scale':
529 | transform = this.scaleMovement(x, y);
530 | break;
531 | }
532 |
533 | return transform;
534 | },
535 |
536 | translateMovement(x, y) {
537 | return `translate3d(${-x}px, ${-y}px, 0)`;
538 | },
539 |
540 | rotateMovement(x, y) {
541 | let movement;
542 |
543 | if (!this.axis) {
544 | movement = x + y;
545 | } else if (this.axis === 'x') {
546 | movement = 2 * x;
547 | } else if (this.axis === 'y') {
548 | movement = 2 * y;
549 | }
550 |
551 | return `rotate3d(0,0,1,${movement}deg)`;
552 | },
553 |
554 | depthMovement(x, y, s) {
555 | return `rotateX(${-y}deg) rotateY(${x}deg) translate3d(0,0,${s * 2}px)`;
556 | },
557 |
558 | scaleMovement(x, y) {
559 | const {
560 | type
561 | } = this;
562 | const movement = Math.sign(this.strength) * (Math.abs(x) + Math.abs(y)) / 10 + 1;
563 | return `scale3d(${type === 'scaleX' || type === 'scale' ? movement : 1},
564 | ${type === 'scaleY' || type === 'scale' ? movement : 1},
565 | 1)`;
566 | }
567 |
568 | }
569 | };
570 |
571 | function cyclicMovement (cycleData) {
572 | const {
573 | referencePosition,
574 | shape,
575 | event,
576 | cycles,
577 | strength
578 | } = cycleData;
579 | const spanningRangeX = event === 'scroll' ? window.innerWidth : shape.width;
580 | const spanningRangeY = event === 'scroll' ? window.innerHeight : shape.height;
581 | const radialPositionX = (referencePosition.x - shape.left) * (Math.PI * 2) / spanningRangeX;
582 | const radialPositionY = (referencePosition.y - shape.top) * (Math.PI * 2) / spanningRangeY;
583 | const cycleX = spanningRangeX * Math.sin(radialPositionX * cycles);
584 | const cycleY = spanningRangeY * Math.sin(radialPositionY * cycles);
585 | return getCoordinates(cycleX * strength / (spanningRangeX / 2), cycleY * strength / (spanningRangeY / 2));
586 | }
587 |
588 | var script$3 = {
589 | name: 'KinesisElement',
590 | mixins: [transformMixin],
591 | props: {
592 | tag: {
593 | type: String,
594 | default: 'div'
595 | },
596 | type: {
597 | type: String,
598 | default: 'translate' // translate, rotate, scale, scaleX, scaleY, depth, depth_inv, custom
599 |
600 | },
601 | transformOrigin: {
602 | type: String,
603 | default: 'center'
604 | },
605 | originX: {
606 | type: Number,
607 | default: 50
608 | },
609 | originY: {
610 | type: Number,
611 | default: 50
612 | },
613 | strength: {
614 | type: Number,
615 | default: 10
616 | },
617 | axis: {
618 | type: String,
619 | default: null
620 | },
621 | maxX: {
622 | type: Number,
623 | default: null
624 | },
625 | maxY: {
626 | type: Number,
627 | default: null
628 | },
629 | minX: {
630 | type: Number,
631 | default: null
632 | },
633 | minY: {
634 | type: Number,
635 | default: null
636 | },
637 | cycle: {
638 | type: Number,
639 | default: 0
640 | }
641 | },
642 | inject: ['context'],
643 | computed: {
644 | transform() {
645 | return this.transformCalculation();
646 | },
647 |
648 | transformParameters() {
649 | return {
650 | transitionProperty: 'transform',
651 | transitionDuration: this.transitionDuration,
652 | transformOrigin: this.transformOrigin,
653 | transitionTimingFunction: this.transitionTimingFunction
654 | };
655 | },
656 |
657 | transitionDuration() {
658 | const {
659 | duration
660 | } = this.context;
661 | return `${duration}ms`;
662 | },
663 |
664 | transitionTimingFunction() {
665 | return this.context.easing;
666 | }
667 |
668 | },
669 | methods: {
670 | transformCalculation() {
671 | const {
672 | context
673 | } = this;
674 | if (!context.shape || !context.isMoving && context.event === 'move') return {};
675 | let movementX;
676 | let movementY;
677 | const {
678 | x,
679 | y
680 | } = this.cycle < 1 ? elementMovement({ ...context.movement,
681 | originX: this.originX,
682 | originY: this.originY,
683 | strength: this.strengthManager(),
684 | event: context.event,
685 | minX: this.minX,
686 | minY: this.minY,
687 | maxX: this.maxX,
688 | maxY: this.maxY
689 | }) : cyclicMovement({
690 | referencePosition: context.event === 'scroll' ? {
691 | x: 0,
692 | y: 0
693 | } : context.eventData,
694 | shape: context.shape,
695 | event: context.event,
696 | cycles: this.cycle,
697 | strength: this.strengthManager()
698 | });
699 |
700 | if (context.event !== 'scroll') {
701 | movementX = this.axis === 'y' ? 0 : x;
702 | movementY = this.axis === 'x' ? 0 : y;
703 | } else if (context.event === 'scroll') {
704 | movementX = this.axis === 'x' ? y : 0;
705 | movementY = this.axis === 'y' || !this.axis ? y : 0;
706 | } else if (this.cycle > 0) {
707 | movementX = this.axis === 'x' ? x : 0;
708 | movementY = this.axis === 'y' ? y : 0;
709 | }
710 |
711 | return {
712 | transform: this.transformSwitch(this.type, movementX, movementY, this.strength)
713 | };
714 | },
715 |
716 | strengthManager() {
717 | return this.type === 'depth' || this.type === 'depth_inv' ? Math.abs(this.strength) : this.strength;
718 | }
719 |
720 | },
721 |
722 | render(createElement) {
723 | const context = this;
724 | return createElement(context.tag, {
725 | style: { ...context.transform,
726 | ...context.transformParameters
727 | }
728 | }, context.$slots.default);
729 | }
730 |
731 | };
732 |
733 | /* script */
734 | const __vue_script__$3 = script$3;
735 | /* template */
736 |
737 | /* style */
738 |
739 | const __vue_inject_styles__$3 = undefined;
740 | /* scoped */
741 |
742 | const __vue_scope_id__$3 = undefined;
743 | /* module identifier */
744 |
745 | const __vue_module_identifier__$3 = undefined;
746 | /* functional template */
747 |
748 | const __vue_is_functional_template__$3 = undefined;
749 | /* style inject */
750 |
751 | /* style inject SSR */
752 |
753 | /* style inject shadow dom */
754 |
755 | const __vue_component__$3 = /*#__PURE__*/normalizeComponent({}, __vue_inject_styles__$3, __vue_script__$3, __vue_scope_id__$3, __vue_is_functional_template__$3, __vue_module_identifier__$3, false, undefined, undefined, undefined);
756 |
757 | var motionMixin = {
758 | props: {
759 | type: {
760 | type: String,
761 | default: 'translate' // translate, rotate, scale, scaleX, scaleY, depth, depth_inv, custom
762 |
763 | },
764 | transformOrigin: {
765 | type: String,
766 | default: 'center'
767 | },
768 | originX: {
769 | type: Number,
770 | default: 50
771 | },
772 | originY: {
773 | type: Number,
774 | default: 50
775 | },
776 | strength: {
777 | type: Number,
778 | default: 10
779 | },
780 | audioIndex: {
781 | type: Number,
782 | default: 50
783 | },
784 | axis: {
785 | type: String,
786 | default: null
787 | },
788 | maxX: {
789 | type: Number,
790 | default: null
791 | },
792 | maxY: {
793 | type: Number,
794 | default: null
795 | },
796 | minX: {
797 | type: Number,
798 | default: null
799 | },
800 | minY: {
801 | type: Number,
802 | default: null
803 | },
804 | cycle: {
805 | type: Number,
806 | default: 0
807 | }
808 | },
809 | methods: {
810 | strengthManager() {
811 | return this.type === 'depth' || this.type === 'depth_inv' ? Math.abs(this.strength) : this.strength;
812 | }
813 |
814 | }
815 | };
816 |
817 | //
818 | var script$2 = {
819 | name: 'KinesisAudio',
820 | inject: ['context'],
821 | mixins: [motionMixin],
822 | props: {
823 | tag: {
824 | type: String,
825 | default: 'div'
826 | },
827 | audioIndex: {
828 | type: Number,
829 | default: 50
830 | }
831 | },
832 | computed: {
833 | transform() {
834 | return this.transformAudio();
835 | },
836 |
837 | transformParameters() {
838 | return {
839 | transitionProperty: 'transform',
840 | transitionDuration: this.transitionDuration,
841 | transformOrigin: this.transformOrigin,
842 | transitionTimingFunction: this.transitionTimingFunction
843 | };
844 | },
845 |
846 | transitionDuration() {
847 | const {
848 | duration
849 | } = this.context;
850 | return `${duration}ms`;
851 | },
852 |
853 | transitionTimingFunction() {
854 | return this.context.easing;
855 | }
856 |
857 | },
858 | methods: {
859 | transformAudio() {
860 | const {
861 | audioData
862 | } = this.context;
863 | if (!audioData) return;
864 | const transformType = this.type;
865 | const {
866 | strength
867 | } = this;
868 | let amplitude;
869 | let transform; // eslint-disable-next-line default-case
870 |
871 | switch (transformType) {
872 | case 'translate':
873 | amplitude = audioData ? audioData[0][this.audioIndex] : 0;
874 | transform = `translate3d(${amplitude * strength}px, 0, 0)`;
875 | break;
876 |
877 | case 'rotate':
878 | amplitude = audioData ? audioData[0][this.audioIndex] : 0;
879 | transform = `rotate3d(0,0,1,${amplitude * strength / 10}deg)`;
880 | break;
881 |
882 | case 'scale':
883 | // eslint-disable-next-line no-nested-ternary
884 | amplitude = audioData ? audioData[0][this.audioIndex] / strength < 1 ? 1 : audioData[0][this.audioIndex] / (strength * 2) : 1;
885 | transform = `scale(${amplitude})`;
886 | break;
887 | } // eslint-disable-next-line consistent-return
888 |
889 |
890 | return {
891 | transform
892 | };
893 | }
894 |
895 | }
896 | };
897 |
898 | /* script */
899 | const __vue_script__$2 = script$2;
900 | /* template */
901 |
902 | var __vue_render__$2 = function () {
903 | var _vm = this;
904 |
905 | var _h = _vm.$createElement;
906 |
907 | var _c = _vm._self._c || _h;
908 |
909 | return _c(_vm.tag, {
910 | tag: "component",
911 | style: Object.assign({}, _vm.transform, _vm.transformParameters)
912 | }, [_vm._t("default")], 2);
913 | };
914 |
915 | var __vue_staticRenderFns__$2 = [];
916 | /* style */
917 |
918 | const __vue_inject_styles__$2 = undefined;
919 | /* scoped */
920 |
921 | const __vue_scope_id__$2 = undefined;
922 | /* module identifier */
923 |
924 | const __vue_module_identifier__$2 = undefined;
925 | /* functional template */
926 |
927 | const __vue_is_functional_template__$2 = false;
928 | /* style inject */
929 |
930 | /* style inject SSR */
931 |
932 | /* style inject shadow dom */
933 |
934 | const __vue_component__$2 = /*#__PURE__*/normalizeComponent({
935 | render: __vue_render__$2,
936 | staticRenderFns: __vue_staticRenderFns__$2
937 | }, __vue_inject_styles__$2, __vue_script__$2, __vue_scope_id__$2, __vue_is_functional_template__$2, __vue_module_identifier__$2, false, undefined, undefined, undefined);
938 |
939 | var baseMixin = {
940 | props: {
941 | active: {
942 | type: Boolean,
943 | default: true
944 | },
945 | duration: {
946 | type: Number,
947 | default: 1000
948 | },
949 | easing: {
950 | type: String,
951 | default: 'cubic-bezier(0.23, 1, 0.32, 1)'
952 | },
953 | tag: {
954 | type: String,
955 | default: 'div'
956 | }
957 | }
958 | };
959 |
960 | var perspectiveMixin = {
961 | props: {
962 | perspective: {
963 | type: Number,
964 | default: 1000
965 | }
966 | },
967 | computed: {
968 | style() {
969 | return {
970 | perspective: `${this.perspective}px`
971 | };
972 | }
973 |
974 | }
975 | };
976 |
977 | //
978 | var script$1 = {
979 | name: 'KinesisScroll',
980 | mixins: [baseMixin, perspectiveMixin, motionMixin, transformMixin],
981 |
982 | data() {
983 | return {
984 | transform: {}
985 | };
986 | },
987 |
988 | computed: {
989 | transformParameters() {
990 | return {
991 | transitionProperty: 'transform',
992 | transitionDuration: this.transitionDuration,
993 | transformOrigin: this.transformOrigin,
994 | transitionTimingFunction: this.easing
995 | };
996 | },
997 |
998 | transitionDuration() {
999 | return `${this.duration}ms`;
1000 | }
1001 |
1002 | },
1003 |
1004 | mounted() {
1005 | window.addEventListener('scroll', this.handleScroll, {
1006 | passive: true
1007 | });
1008 | },
1009 |
1010 | beforeDestroy() {
1011 | window.removeEventListener('scroll', this.handleScroll, {
1012 | passive: true
1013 | });
1014 | },
1015 |
1016 | methods: {
1017 | getCycleMovement(xPos, yPos, width, height, shape) {
1018 | const x = (xPos - shape.left) * (Math.PI * 2) / width;
1019 | const y = (yPos - shape.top) * (Math.PI * 2) / height;
1020 | this.cycleMovement = {
1021 | x,
1022 | y,
1023 | width,
1024 | height
1025 | };
1026 | },
1027 |
1028 | handleScroll: throttle( // eslint-disable-next-line func-names
1029 | function () {
1030 | if (!this.active) return;
1031 | const shape = this.$el.getBoundingClientRect();
1032 | const isInViewport = inViewport(shape);
1033 |
1034 | if (isInViewport && !!shape.height) {
1035 | this.transformBehavior(shape);
1036 | }
1037 | }, 19, 'scroll'),
1038 |
1039 | transformBehavior(shape) {
1040 | let movementX;
1041 | let movementY;
1042 | const scrollPosition = (shape.top - window.innerHeight) / (shape.height + window.innerHeight);
1043 |
1044 | if (this.cycle <= 0) {
1045 | const scrollMovement = scrollPosition * this.strength;
1046 | movementX = this.axis === 'x' ? scrollMovement : 0;
1047 | movementY = this.axis === 'y' || !this.axis ? scrollMovement : 0;
1048 |
1049 | if (this.maxX) {
1050 | movementX = Math.min(movementX, this.maxX);
1051 | }
1052 |
1053 | if (this.minX) {
1054 | movementX = Math.max(movementX, this.minX);
1055 | }
1056 |
1057 | if (this.maxY) {
1058 | movementY = Math.min(movementY, this.maxY);
1059 | }
1060 |
1061 | if (this.minY) {
1062 | movementY = Math.max(movementY, this.minY);
1063 | }
1064 | } else if (this.cycle > 0) {
1065 | const {
1066 | x,
1067 | y,
1068 | width,
1069 | height
1070 | } = this.getCycleMovement(0, 0, window.innerWidth, window.innerHeight, shape);
1071 | const cycleX = width * Math.sin(x * this.cycle);
1072 | const cycleY = height * Math.sin(y * this.cycle);
1073 | movementX = this.axis === 'x' ? cycleX / (width / 2) * this.strength : 0;
1074 | movementY = this.axis === 'y' || !this.axis ? cycleY / (height / 2) * this.strength : 0;
1075 | }
1076 |
1077 | let transformType = this.type;
1078 | transformType = transformType === 'scaleX' || transformType === 'scaleY' ? 'scale' : transformType;
1079 | const transform = this.transformSwitch(transformType, movementX, movementY, this.strength);
1080 | this.transform = {
1081 | transform
1082 | };
1083 | }
1084 |
1085 | }
1086 | };
1087 |
1088 | /* script */
1089 | const __vue_script__$1 = script$1;
1090 | /* template */
1091 |
1092 | var __vue_render__$1 = function () {
1093 | var _vm = this;
1094 |
1095 | var _h = _vm.$createElement;
1096 |
1097 | var _c = _vm._self._c || _h;
1098 |
1099 | return _c(_vm.tag, {
1100 | tag: "component",
1101 | style: Object.assign({}, _vm.transform, _vm.transformParameters)
1102 | }, [_vm._t("default")], 2);
1103 | };
1104 |
1105 | var __vue_staticRenderFns__$1 = [];
1106 | /* style */
1107 |
1108 | const __vue_inject_styles__$1 = undefined;
1109 | /* scoped */
1110 |
1111 | const __vue_scope_id__$1 = undefined;
1112 | /* module identifier */
1113 |
1114 | const __vue_module_identifier__$1 = undefined;
1115 | /* functional template */
1116 |
1117 | const __vue_is_functional_template__$1 = false;
1118 | /* style inject */
1119 |
1120 | /* style inject SSR */
1121 |
1122 | /* style inject shadow dom */
1123 |
1124 | const __vue_component__$1 = /*#__PURE__*/normalizeComponent({
1125 | render: __vue_render__$1,
1126 | staticRenderFns: __vue_staticRenderFns__$1
1127 | }, __vue_inject_styles__$1, __vue_script__$1, __vue_scope_id__$1, __vue_is_functional_template__$1, __vue_module_identifier__$1, false, undefined, undefined, undefined);
1128 |
1129 | //
1130 | var script = {
1131 | name: 'KinesisDistance',
1132 | props: {
1133 | tag: {
1134 | type: String,
1135 | default: 'div'
1136 | },
1137 | type: {
1138 | type: String,
1139 | default: 'translate' // translate, rotate, scale, scaleX, scaleY, depth, custom
1140 |
1141 | },
1142 | transformOrigin: {
1143 | type: String,
1144 | default: 'center'
1145 | },
1146 | originX: {
1147 | type: Number,
1148 | default: 50
1149 | },
1150 | originY: {
1151 | type: Number,
1152 | default: 50
1153 | },
1154 | strength: {
1155 | type: Number,
1156 | default: 10
1157 | },
1158 | axis: {
1159 | type: String,
1160 | default: null
1161 | },
1162 | maxX: {
1163 | type: Number,
1164 | default: null
1165 | },
1166 | maxY: {
1167 | type: Number,
1168 | default: null
1169 | },
1170 | minX: {
1171 | type: Number,
1172 | default: null
1173 | },
1174 | minY: {
1175 | type: Number,
1176 | default: null
1177 | },
1178 | distance: {
1179 | type: Number,
1180 | default: 100
1181 | },
1182 | cycle: {
1183 | type: Number,
1184 | default: 0
1185 | },
1186 | active: {
1187 | type: Boolean,
1188 | default: true
1189 | },
1190 | duration: {
1191 | type: Number,
1192 | default: 1001
1193 | },
1194 | easing: {
1195 | type: String,
1196 | default: 'cubic-bezier(0.23, 1, 0.32, 1)'
1197 | },
1198 | perspective: {
1199 | type: Number,
1200 | default: 1000
1201 | }
1202 | },
1203 |
1204 | data() {
1205 | return {
1206 | pointer: {
1207 | x: 0,
1208 | y: 0
1209 | },
1210 | transform: {},
1211 | component: 'kidistance',
1212 | throttle: 500
1213 | };
1214 | },
1215 |
1216 | computed: {
1217 | style() {
1218 | return {
1219 | perspective: `${this.perspective}px`
1220 | };
1221 | },
1222 |
1223 | transformParameters() {
1224 | return {
1225 | position: 'relative',
1226 | transitionProperty: 'transform',
1227 | transitionDuration: this.transitionDuration,
1228 | transformOrigin: this.transformOrigin,
1229 | transitionTimingFunction: this.easing
1230 | };
1231 | },
1232 |
1233 | transitionDuration() {
1234 | return `${this.duration}ms`;
1235 | }
1236 |
1237 | },
1238 |
1239 | mounted() {
1240 | window.addEventListener('scroll', this.handleMovement);
1241 | },
1242 |
1243 | beforeDestroy() {
1244 | window.removeEventListener('scroll', this.handleMovement);
1245 | },
1246 |
1247 | methods: {
1248 | getCoordinates(x, y) {
1249 | const shape = this.$el.getBoundingClientRect();
1250 | return {
1251 | x: x + shape.left,
1252 | y: y + shape.top
1253 | };
1254 | },
1255 |
1256 | getDistance(x1, x2, y1, y2) {
1257 | return Math.floor(Math.hypot(x2 - x1, y2 - y1));
1258 | },
1259 |
1260 | // eslint-disable-next-line func-names
1261 | handleMovement: throttle(function (event) {
1262 | window.addEventListener('mousemove', this.handleMovement);
1263 | const {
1264 | pointer
1265 | } = this;
1266 | pointer.x = event.clientX;
1267 | pointer.y = event.clientY;
1268 | this.transformBehavior();
1269 | }, 50),
1270 |
1271 | transformBehavior() {
1272 | const shape = this.$el.getBoundingClientRect();
1273 | const center = this.getCoordinates(shape.width / 2, shape.height / 2);
1274 | const distance = this.getDistance(this.pointer.x, center.x, this.pointer.y, center.y);
1275 |
1276 | if (distance > this.distance) {
1277 | this.transform = {};
1278 | this.throttle = 500;
1279 | return;
1280 | }
1281 |
1282 | this.throttle = 50;
1283 | const transform = `scale(${distance / this.distance})`; // Add radius from which the transfrom will start
1284 |
1285 | this.transform = {
1286 | transform
1287 | };
1288 | },
1289 |
1290 | scaleMovement(x, y) {
1291 | const {
1292 | type
1293 | } = this;
1294 | const movement = Math.sign(this.strength) * (Math.abs(x) + Math.abs(y)) / 10 + 1;
1295 | return `scale3d(${type === 'scaleX' || type === 'scale' ? movement : 1},
1296 | ${type === 'scaleY' || type === 'scale' ? movement : 1},
1297 | 1)`;
1298 | }
1299 |
1300 | }
1301 | };
1302 |
1303 | /* script */
1304 | const __vue_script__ = script;
1305 | /* template */
1306 |
1307 | var __vue_render__ = function () {
1308 | var _vm = this;
1309 |
1310 | var _h = _vm.$createElement;
1311 |
1312 | var _c = _vm._self._c || _h;
1313 |
1314 | return _c(_vm.tag, {
1315 | tag: "component",
1316 | style: Object.assign({}, _vm.transform, _vm.transformParameters)
1317 | }, [_vm._t("default")], 2);
1318 | };
1319 |
1320 | var __vue_staticRenderFns__ = [];
1321 | /* style */
1322 |
1323 | const __vue_inject_styles__ = undefined;
1324 | /* scoped */
1325 |
1326 | const __vue_scope_id__ = undefined;
1327 | /* module identifier */
1328 |
1329 | const __vue_module_identifier__ = undefined;
1330 | /* functional template */
1331 |
1332 | const __vue_is_functional_template__ = false;
1333 | /* style inject */
1334 |
1335 | /* style inject SSR */
1336 |
1337 | /* style inject shadow dom */
1338 |
1339 | const __vue_component__ = /*#__PURE__*/normalizeComponent({
1340 | render: __vue_render__,
1341 | staticRenderFns: __vue_staticRenderFns__
1342 | }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, false, undefined, undefined, undefined);
1343 |
1344 | const Plugin$1 = {
1345 | install(vue) {
1346 | vue.component(__vue_component__$2.name, __vue_component__$2);
1347 | vue.component(__vue_component__$4.name, __vue_component__$4);
1348 | vue.component(__vue_component__.name, __vue_component__);
1349 | vue.component(__vue_component__$3.name, __vue_component__$3);
1350 | vue.component(__vue_component__$1.name, __vue_component__$1);
1351 | }
1352 |
1353 | };
1354 | let GlobalVue$1 = null;
1355 |
1356 | if (typeof window !== 'undefined') {
1357 | GlobalVue$1 = window.vue;
1358 | } else if (typeof global !== 'undefined') {
1359 | GlobalVue$1 = global.vue;
1360 | }
1361 |
1362 | if (GlobalVue$1) {
1363 | GlobalVue$1.use(Plugin$1);
1364 | }
1365 |
1366 | var components = /*#__PURE__*/Object.freeze({
1367 | __proto__: null,
1368 | 'default': Plugin$1,
1369 | KinesisAudio: __vue_component__$2,
1370 | KinesisContainer: __vue_component__$4,
1371 | KinesisDistance: __vue_component__,
1372 | KinesisElement: __vue_component__$3,
1373 | KinesisScroll: __vue_component__$1
1374 | });
1375 |
1376 | /* eslint-disable */
1377 |
1378 | const install = function (vue) {
1379 | if (install.installed) {
1380 | return;
1381 | }
1382 |
1383 | install.installed = true;
1384 |
1385 | for (const name in components) {
1386 | vue.use(components[name]);
1387 | }
1388 |
1389 | vue.component('kinesis-container', __vue_component__$4);
1390 | vue.component('kinesis-element', __vue_component__$3);
1391 | vue.component('kinesis-audio', __vue_component__$2);
1392 | vue.component('kinesis-scroll', __vue_component__$1);
1393 | vue.component('kinesis-distance', __vue_component__);
1394 | };
1395 |
1396 | const Plugin = {
1397 | install
1398 | };
1399 | let GlobalVue = null;
1400 |
1401 | if (typeof window !== 'undefined') {
1402 | GlobalVue = window.vue;
1403 | } else if (typeof global !== 'undefined') {
1404 | GlobalVue = global.vue;
1405 | }
1406 |
1407 | if (GlobalVue) {
1408 | GlobalVue.use(Plugin);
1409 | }
1410 |
1411 | export default Plugin;
1412 | export { __vue_component__$2 as KinesisAudio, __vue_component__$4 as KinesisContainer, __vue_component__ as KinesisDistance, __vue_component__$3 as KinesisElement, __vue_component__$1 as KinesisScroll };
1413 |
--------------------------------------------------------------------------------
/dist/vue-kinesis.ssr.js:
--------------------------------------------------------------------------------
1 | 'use strict';Object.defineProperty(exports,'__esModule',{value:true});function ownKeys(object, enumerableOnly) {
2 | var keys = Object.keys(object);
3 |
4 | if (Object.getOwnPropertySymbols) {
5 | var symbols = Object.getOwnPropertySymbols(object);
6 |
7 | if (enumerableOnly) {
8 | symbols = symbols.filter(function (sym) {
9 | return Object.getOwnPropertyDescriptor(object, sym).enumerable;
10 | });
11 | }
12 |
13 | keys.push.apply(keys, symbols);
14 | }
15 |
16 | return keys;
17 | }
18 |
19 | function _objectSpread2(target) {
20 | for (var i = 1; i < arguments.length; i++) {
21 | var source = arguments[i] != null ? arguments[i] : {};
22 |
23 | if (i % 2) {
24 | ownKeys(Object(source), true).forEach(function (key) {
25 | _defineProperty(target, key, source[key]);
26 | });
27 | } else if (Object.getOwnPropertyDescriptors) {
28 | Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
29 | } else {
30 | ownKeys(Object(source)).forEach(function (key) {
31 | Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
32 | });
33 | }
34 | }
35 |
36 | return target;
37 | }
38 |
39 | function _defineProperty(obj, key, value) {
40 | if (key in obj) {
41 | Object.defineProperty(obj, key, {
42 | value: value,
43 | enumerable: true,
44 | configurable: true,
45 | writable: true
46 | });
47 | } else {
48 | obj[key] = value;
49 | }
50 |
51 | return obj;
52 | }function getCoordinates (x, y) {
53 | return {
54 | x: x,
55 | y: y
56 | };
57 | }function getCenter (element) {
58 | return getCoordinates(element ? element.width / 2 : 0, element ? element.height / 2 : 0);
59 | }function mouseMovement (action) {
60 | var target = action.target,
61 | event = action.event;
62 | var x = event.clientX;
63 | var y = event.clientY;
64 | var relativeX = x - target.left;
65 | var relativeY = y - target.top;
66 | var center = getCenter(target);
67 | var mouseMovementX = relativeX / center.x;
68 | var mouseMovementY = relativeY / center.y;
69 | return _objectSpread2(_objectSpread2({}, getCoordinates(mouseMovementX, mouseMovementY)), {}, {
70 | target: target
71 | });
72 | }function scrollMovement (shape) {
73 | var target = shape.target;
74 | var x = (target.left - window.innerWidth) / (target.width + window.innerWidth);
75 | var y = (target.top - window.innerHeight) / (target.height + window.innerHeight);
76 | return _objectSpread2(_objectSpread2({}, getCoordinates(x, y)), {}, {
77 | target: target
78 | });
79 | }function orientationElement (action) {
80 | var event = action.event,
81 | target = action.target;
82 | var x = event.gamma / 45;
83 | var y = event.beta / 90;
84 | return _objectSpread2(_objectSpread2({}, getCoordinates(x, y)), {}, {
85 | target: target
86 | });
87 | }function inViewport(element) {
88 | var isInViewport = element.bottom >= 0 && element.right >= 0 && element.top <= (window.innerHeight || document.documentElement.clientHeight) && element.left <= (window.innerWidth || document.documentElement.clientWidth);
89 | return isInViewport;
90 | }function isTouch() {
91 | try {
92 | return /Mobi|Android/i.test(navigator.userAgent);
93 | } catch (e) {
94 | return true;
95 | }
96 | }function throttle(callback, delay, type) {
97 | var last;
98 | var timer; // eslint-disable-next-line func-names
99 |
100 | return function () {
101 | var context = this;
102 | var newDelay;
103 |
104 | if (type === 'scroll') {
105 | newDelay = delay;
106 | } else {
107 | newDelay = context.duration > 1000 ? delay : context.duration / 10;
108 | }
109 |
110 | var now = +new Date(); // eslint-disable-next-line prefer-rest-params
111 |
112 | var args = arguments;
113 |
114 | if (last && now < last + newDelay) {
115 | clearTimeout(timer);
116 | timer = setTimeout(function () {
117 | requestAnimationFrame(function () {
118 | last = now;
119 | callback.apply(context, args);
120 | });
121 | }, newDelay);
122 | } else {
123 | requestAnimationFrame(function () {
124 | last = now;
125 | callback.apply(context, args);
126 | });
127 | }
128 | };
129 | }var audioMixin = {
130 | props: {
131 | audio: {
132 | type: String,
133 | required: false
134 | },
135 | playAudio: {
136 | type: Boolean,
137 | default: false
138 | }
139 | },
140 | data: function data() {
141 | return {
142 | analyser: null,
143 | audioArray: null,
144 | audioData: null,
145 | audioRef: null,
146 | wasPlayed: false,
147 | isPlaying: false
148 | };
149 | },
150 | watch: {
151 | audio: function audio() {
152 | this.wasPlayed = false;
153 | this.isPlaying = false;
154 | },
155 | playAudio: function playAudio(play) {
156 | if (play) {
157 | this.play();
158 | } else {
159 | this.stop();
160 | }
161 | }
162 | },
163 | methods: {
164 | play: function play() {
165 | if (!this.active) return;
166 |
167 | if (!this.wasPlayed) {
168 | this.handleAudio();
169 | this.wasPlayed = true;
170 | }
171 |
172 | this.isPlaying = true;
173 | this.audioRef.play();
174 | this.getSongData();
175 | },
176 | stop: function stop() {
177 | this.isPlaying = false;
178 | this.audioRef.pause();
179 | },
180 | handleAudio: function handleAudio() {
181 | var audio = this.$refs.audio;
182 | this.audioRef = audio;
183 | var context = new AudioContext();
184 | var src = context.createMediaElementSource(audio);
185 | var analyser = context.createAnalyser();
186 | src.connect(analyser);
187 | analyser.connect(context.destination);
188 | analyser.fftSize = 256;
189 | var bufferLength = analyser.frequencyBinCount;
190 | var audioArray = new Uint8Array(bufferLength);
191 | this.audioArray = audioArray;
192 | this.analyser = analyser;
193 | },
194 | getSongData: function getSongData() {
195 | if (this.isPlaying) {
196 | this.analyser.getByteFrequencyData(this.audioArray);
197 | this.audioData = new Array(this.audioArray); // @Todo reactivity issue
198 |
199 | requestAnimationFrame(this.getSongData);
200 | }
201 | }
202 | }
203 | };//
204 | var script$4 = {
205 | name: 'KinesisContainer',
206 | mixins: [audioMixin],
207 | props: {
208 | tag: {
209 | type: String,
210 | default: 'div'
211 | },
212 | event: {
213 | type: String,
214 | default: 'move'
215 | },
216 | active: {
217 | type: Boolean,
218 | default: true
219 | },
220 | duration: {
221 | type: Number,
222 | default: 1000
223 | },
224 | easing: {
225 | type: String,
226 | default: 'cubic-bezier(0.23, 1, 0.32, 1)'
227 | },
228 | perspective: {
229 | type: Number,
230 | default: 1000
231 | }
232 | },
233 | provide: function provide() {
234 | var _this = this;
235 |
236 | var context = {};
237 | var providedProps = ['audioData', 'duration', 'easing', 'event', 'eventData', 'isMoving', 'movement', 'shape'];
238 | providedProps.forEach(function (prop) {
239 | return Object.defineProperty(context, prop, {
240 | enumerable: true,
241 | get: function get() {
242 | return _this[prop];
243 | }
244 | });
245 | });
246 | return {
247 | context: context
248 | };
249 | },
250 | data: function data() {
251 | var _this$$el;
252 |
253 | return {
254 | shape: (_this$$el = this.$el) === null || _this$$el === void 0 ? void 0 : _this$$el.getBoundingClientRect(),
255 | isMoving: false,
256 | leftOnce: false,
257 | movement: {
258 | x: 0,
259 | y: 0
260 | },
261 | eventMap: {
262 | orientation: 'deviceorientation',
263 | scroll: 'scroll',
264 | move: isTouch() ? 'deviceorientation' : null
265 | }
266 | };
267 | },
268 | computed: {
269 | eventActions: function eventActions() {
270 | var _this$shape;
271 |
272 | return {
273 | move: {
274 | action: mouseMovement,
275 | condition: this.isMoving && !isTouch(),
276 | type: isTouch() ? 'deviceorientation' : null
277 | },
278 | scroll: {
279 | action: scrollMovement,
280 | condition: !!((_this$shape = this.shape) !== null && _this$shape !== void 0 && _this$shape.height),
281 | type: 'scroll'
282 | },
283 | orientation: {
284 | action: orientationElement,
285 | condition: this.event === 'move' && isTouch(),
286 | type: 'deviceorientation'
287 | }
288 | };
289 | },
290 | style: function style() {
291 | return {
292 | perspective: "".concat(this.perspective, "px")
293 | };
294 | }
295 | },
296 | mounted: function mounted() {
297 | this.addEvents();
298 | },
299 | beforeDestroy: function beforeDestroy() {
300 | this.removeEvents();
301 | },
302 | methods: {
303 | handleMovementStart: function handleMovementStart() {
304 | if (!this.active) return;
305 | this.isMoving = true;
306 | },
307 | handleMovementStop: function handleMovementStop() {
308 | if (!this.active) return; // fixes the specific case when mouseenter didn't trigger on page refresh
309 |
310 | this.leftOnce = true;
311 | this.isMoving = false;
312 | },
313 | // eslint-disable-next-line func-names
314 | handleMovement: throttle(function (event) {
315 | if (!this.active) return;
316 |
317 | if (!this.isMoving && !this.leftOnce) {
318 | // fixes the specific case when mouseenter didn't trigger on page refresh
319 | this.handleMovementStart();
320 | }
321 |
322 | this.shape = this.$el.getBoundingClientRect();
323 | var isInViewport = inViewport(this.shape);
324 | var eventCondition = this.eventActions[this.event].condition;
325 | var eventAction = this.eventActions[this.event].action;
326 |
327 | if (isInViewport && eventCondition) {
328 | this.movement = eventAction({
329 | target: this.shape,
330 | event: event
331 | });
332 | this.eventData = getCoordinates(event.clientX, event.clientY);
333 | }
334 | }, 100),
335 | addEvents: function addEvents() {
336 | if (this.eventMap[this.event]) {
337 | window.addEventListener(this.eventMap[this.event], this.handleMovement, true);
338 | }
339 | },
340 | removeEvents: function removeEvents() {
341 | if (this.eventMap[this.event]) {
342 | window.removeEventListener(this.eventMap[this.event], this.handleMovement, true);
343 | }
344 | }
345 | }
346 | };function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
347 | if (typeof shadowMode !== 'boolean') {
348 | createInjectorSSR = createInjector;
349 | createInjector = shadowMode;
350 | shadowMode = false;
351 | }
352 | // Vue.extend constructor export interop.
353 | const options = typeof script === 'function' ? script.options : script;
354 | // render functions
355 | if (template && template.render) {
356 | options.render = template.render;
357 | options.staticRenderFns = template.staticRenderFns;
358 | options._compiled = true;
359 | // functional template
360 | if (isFunctionalTemplate) {
361 | options.functional = true;
362 | }
363 | }
364 | // scopedId
365 | if (scopeId) {
366 | options._scopeId = scopeId;
367 | }
368 | let hook;
369 | if (moduleIdentifier) {
370 | // server build
371 | hook = function (context) {
372 | // 2.3 injection
373 | context =
374 | context || // cached call
375 | (this.$vnode && this.$vnode.ssrContext) || // stateful
376 | (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional
377 | // 2.2 with runInNewContext: true
378 | if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
379 | context = __VUE_SSR_CONTEXT__;
380 | }
381 | // inject component styles
382 | if (style) {
383 | style.call(this, createInjectorSSR(context));
384 | }
385 | // register component module identifier for async chunk inference
386 | if (context && context._registeredComponents) {
387 | context._registeredComponents.add(moduleIdentifier);
388 | }
389 | };
390 | // used by ssr in case component is cached and beforeCreate
391 | // never gets called
392 | options._ssrRegister = hook;
393 | }
394 | else if (style) {
395 | hook = shadowMode
396 | ? function (context) {
397 | style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot));
398 | }
399 | : function (context) {
400 | style.call(this, createInjector(context));
401 | };
402 | }
403 | if (hook) {
404 | if (options.functional) {
405 | // register for functional component in vue file
406 | const originalRender = options.render;
407 | options.render = function renderWithStyleInjection(h, context) {
408 | hook.call(context);
409 | return originalRender(h, context);
410 | };
411 | }
412 | else {
413 | // inject component registration as beforeCreate hook
414 | const existing = options.beforeCreate;
415 | options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
416 | }
417 | }
418 | return script;
419 | }/* script */
420 | var __vue_script__$4 = script$4;
421 | /* template */
422 |
423 | var __vue_render__$3 = function __vue_render__() {
424 | var _vm = this;
425 |
426 | var _h = _vm.$createElement;
427 |
428 | var _c = _vm._self._c || _h;
429 |
430 | return _c(_vm.tag, {
431 | tag: "component",
432 | style: _vm.style,
433 | on: {
434 | "mousemove": _vm.handleMovement,
435 | "mouseenter": _vm.handleMovementStart,
436 | "mouseleave": _vm.handleMovementStop
437 | }
438 | }, [_vm._t("default"), _vm._v(" "), _vm.audio ? _c('audio', {
439 | ref: "audio",
440 | attrs: {
441 | "type": "audio/mpeg"
442 | },
443 | on: {
444 | "ended": _vm.stop
445 | }
446 | }, [_c('source', {
447 | attrs: {
448 | "src": _vm.audio
449 | }
450 | })]) : _vm._e()], 2);
451 | };
452 |
453 | var __vue_staticRenderFns__$3 = [];
454 | /* style */
455 |
456 | var __vue_inject_styles__$4 = undefined;
457 | /* scoped */
458 |
459 | var __vue_scope_id__$4 = undefined;
460 | /* module identifier */
461 |
462 | var __vue_module_identifier__$4 = "data-v-5b4afee6";
463 | /* functional template */
464 |
465 | var __vue_is_functional_template__$4 = false;
466 | /* style inject */
467 |
468 | /* style inject SSR */
469 |
470 | /* style inject shadow dom */
471 |
472 | var __vue_component__$4 = /*#__PURE__*/normalizeComponent({
473 | render: __vue_render__$3,
474 | staticRenderFns: __vue_staticRenderFns__$3
475 | }, __vue_inject_styles__$4, __vue_script__$4, __vue_scope_id__$4, __vue_is_functional_template__$4, __vue_module_identifier__$4, false, undefined, undefined, undefined);/* eslint-disable no-nested-ternary */
476 | function clamp (value, min, max) {
477 | return max && value > max ? max : min && value < min ? min : value;
478 | }function elementMovement (action) {
479 | var y = action.y,
480 | x = action.x,
481 | target = action.target,
482 | _action$originX = action.originX,
483 | originX = _action$originX === void 0 ? 50 : _action$originX,
484 | _action$strength = action.strength,
485 | strength = _action$strength === void 0 ? 10 : _action$strength,
486 | _action$event = action.event,
487 | event = _action$event === void 0 ? null : _action$event,
488 | minX = action.minX,
489 | minY = action.minY,
490 | maxX = action.maxX,
491 | maxY = action.maxY;
492 | var _action$originY = action.originY,
493 | originY = _action$originY === void 0 ? 50 : _action$originY;
494 |
495 | if (event === 'scroll') {
496 | originY = -originY / 2;
497 | }
498 |
499 | var movementX = clamp((x - originX / 50) * strength, minX, maxX);
500 | var movementY = clamp((y - originY / 50) * strength, minY, maxY);
501 | return _objectSpread2(_objectSpread2({}, getCoordinates(movementX, movementY)), {}, {
502 | target: target
503 | });
504 | }/* eslint-disable default-case */
505 | var transformMixin = {
506 | methods: {
507 | transformSwitch: function transformSwitch(type, x, y, s) {
508 | type = type === 'scaleX' || type === 'scaleY' ? 'scale' : type;
509 | var transform;
510 |
511 | switch (type) {
512 | case 'translate':
513 | transform = this.translateMovement(x, y);
514 | break;
515 |
516 | case 'rotate':
517 | transform = this.rotateMovement(x, y);
518 | break;
519 |
520 | case 'depth':
521 | transform = this.depthMovement(x, y, s);
522 | break;
523 |
524 | case 'depth_inv':
525 | transform = this.depthMovement(-x, -y, s);
526 | break;
527 |
528 | case 'scale':
529 | transform = this.scaleMovement(x, y);
530 | break;
531 | }
532 |
533 | return transform;
534 | },
535 | translateMovement: function translateMovement(x, y) {
536 | return "translate3d(".concat(-x, "px, ").concat(-y, "px, 0)");
537 | },
538 | rotateMovement: function rotateMovement(x, y) {
539 | var movement;
540 |
541 | if (!this.axis) {
542 | movement = x + y;
543 | } else if (this.axis === 'x') {
544 | movement = 2 * x;
545 | } else if (this.axis === 'y') {
546 | movement = 2 * y;
547 | }
548 |
549 | return "rotate3d(0,0,1,".concat(movement, "deg)");
550 | },
551 | depthMovement: function depthMovement(x, y, s) {
552 | return "rotateX(".concat(-y, "deg) rotateY(").concat(x, "deg) translate3d(0,0,").concat(s * 2, "px)");
553 | },
554 | scaleMovement: function scaleMovement(x, y) {
555 | var type = this.type;
556 | var movement = Math.sign(this.strength) * (Math.abs(x) + Math.abs(y)) / 10 + 1;
557 | return "scale3d(".concat(type === 'scaleX' || type === 'scale' ? movement : 1, ",\n ").concat(type === 'scaleY' || type === 'scale' ? movement : 1, ",\n 1)");
558 | }
559 | }
560 | };function cyclicMovement (cycleData) {
561 | var referencePosition = cycleData.referencePosition,
562 | shape = cycleData.shape,
563 | event = cycleData.event,
564 | cycles = cycleData.cycles,
565 | strength = cycleData.strength;
566 | var spanningRangeX = event === 'scroll' ? window.innerWidth : shape.width;
567 | var spanningRangeY = event === 'scroll' ? window.innerHeight : shape.height;
568 | var radialPositionX = (referencePosition.x - shape.left) * (Math.PI * 2) / spanningRangeX;
569 | var radialPositionY = (referencePosition.y - shape.top) * (Math.PI * 2) / spanningRangeY;
570 | var cycleX = spanningRangeX * Math.sin(radialPositionX * cycles);
571 | var cycleY = spanningRangeY * Math.sin(radialPositionY * cycles);
572 | return getCoordinates(cycleX * strength / (spanningRangeX / 2), cycleY * strength / (spanningRangeY / 2));
573 | }var script$3 = {
574 | name: 'KinesisElement',
575 | mixins: [transformMixin],
576 | props: {
577 | tag: {
578 | type: String,
579 | default: 'div'
580 | },
581 | type: {
582 | type: String,
583 | default: 'translate' // translate, rotate, scale, scaleX, scaleY, depth, depth_inv, custom
584 |
585 | },
586 | transformOrigin: {
587 | type: String,
588 | default: 'center'
589 | },
590 | originX: {
591 | type: Number,
592 | default: 50
593 | },
594 | originY: {
595 | type: Number,
596 | default: 50
597 | },
598 | strength: {
599 | type: Number,
600 | default: 10
601 | },
602 | axis: {
603 | type: String,
604 | default: null
605 | },
606 | maxX: {
607 | type: Number,
608 | default: null
609 | },
610 | maxY: {
611 | type: Number,
612 | default: null
613 | },
614 | minX: {
615 | type: Number,
616 | default: null
617 | },
618 | minY: {
619 | type: Number,
620 | default: null
621 | },
622 | cycle: {
623 | type: Number,
624 | default: 0
625 | }
626 | },
627 | inject: ['context'],
628 | computed: {
629 | transform: function transform() {
630 | return this.transformCalculation();
631 | },
632 | transformParameters: function transformParameters() {
633 | return {
634 | transitionProperty: 'transform',
635 | transitionDuration: this.transitionDuration,
636 | transformOrigin: this.transformOrigin,
637 | transitionTimingFunction: this.transitionTimingFunction
638 | };
639 | },
640 | transitionDuration: function transitionDuration() {
641 | var duration = this.context.duration;
642 | return "".concat(duration, "ms");
643 | },
644 | transitionTimingFunction: function transitionTimingFunction() {
645 | return this.context.easing;
646 | }
647 | },
648 | methods: {
649 | transformCalculation: function transformCalculation() {
650 | var context = this.context;
651 | if (!context.shape || !context.isMoving && context.event === 'move') return {};
652 | var movementX;
653 | var movementY;
654 |
655 | var _ref = this.cycle < 1 ? elementMovement(_objectSpread2(_objectSpread2({}, context.movement), {}, {
656 | originX: this.originX,
657 | originY: this.originY,
658 | strength: this.strengthManager(),
659 | event: context.event,
660 | minX: this.minX,
661 | minY: this.minY,
662 | maxX: this.maxX,
663 | maxY: this.maxY
664 | })) : cyclicMovement({
665 | referencePosition: context.event === 'scroll' ? {
666 | x: 0,
667 | y: 0
668 | } : context.eventData,
669 | shape: context.shape,
670 | event: context.event,
671 | cycles: this.cycle,
672 | strength: this.strengthManager()
673 | }),
674 | x = _ref.x,
675 | y = _ref.y;
676 |
677 | if (context.event !== 'scroll') {
678 | movementX = this.axis === 'y' ? 0 : x;
679 | movementY = this.axis === 'x' ? 0 : y;
680 | } else if (context.event === 'scroll') {
681 | movementX = this.axis === 'x' ? y : 0;
682 | movementY = this.axis === 'y' || !this.axis ? y : 0;
683 | } else if (this.cycle > 0) {
684 | movementX = this.axis === 'x' ? x : 0;
685 | movementY = this.axis === 'y' ? y : 0;
686 | }
687 |
688 | return {
689 | transform: this.transformSwitch(this.type, movementX, movementY, this.strength)
690 | };
691 | },
692 | strengthManager: function strengthManager() {
693 | return this.type === 'depth' || this.type === 'depth_inv' ? Math.abs(this.strength) : this.strength;
694 | }
695 | },
696 | render: function render(createElement) {
697 | var context = this;
698 | return createElement(context.tag, {
699 | style: _objectSpread2(_objectSpread2({}, context.transform), context.transformParameters)
700 | }, context.$slots.default);
701 | }
702 | };/* script */
703 | var __vue_script__$3 = script$3;
704 | /* template */
705 |
706 | /* style */
707 |
708 | var __vue_inject_styles__$3 = undefined;
709 | /* scoped */
710 |
711 | var __vue_scope_id__$3 = undefined;
712 | /* module identifier */
713 |
714 | var __vue_module_identifier__$3 = "data-v-2ae8e75a";
715 | /* functional template */
716 |
717 | var __vue_is_functional_template__$3 = undefined;
718 | /* style inject */
719 |
720 | /* style inject SSR */
721 |
722 | /* style inject shadow dom */
723 |
724 | var __vue_component__$3 = /*#__PURE__*/normalizeComponent({}, __vue_inject_styles__$3, __vue_script__$3, __vue_scope_id__$3, __vue_is_functional_template__$3, __vue_module_identifier__$3, false, undefined, undefined, undefined);var motionMixin = {
725 | props: {
726 | type: {
727 | type: String,
728 | default: 'translate' // translate, rotate, scale, scaleX, scaleY, depth, depth_inv, custom
729 |
730 | },
731 | transformOrigin: {
732 | type: String,
733 | default: 'center'
734 | },
735 | originX: {
736 | type: Number,
737 | default: 50
738 | },
739 | originY: {
740 | type: Number,
741 | default: 50
742 | },
743 | strength: {
744 | type: Number,
745 | default: 10
746 | },
747 | audioIndex: {
748 | type: Number,
749 | default: 50
750 | },
751 | axis: {
752 | type: String,
753 | default: null
754 | },
755 | maxX: {
756 | type: Number,
757 | default: null
758 | },
759 | maxY: {
760 | type: Number,
761 | default: null
762 | },
763 | minX: {
764 | type: Number,
765 | default: null
766 | },
767 | minY: {
768 | type: Number,
769 | default: null
770 | },
771 | cycle: {
772 | type: Number,
773 | default: 0
774 | }
775 | },
776 | methods: {
777 | strengthManager: function strengthManager() {
778 | return this.type === 'depth' || this.type === 'depth_inv' ? Math.abs(this.strength) : this.strength;
779 | }
780 | }
781 | };//
782 | var script$2 = {
783 | name: 'KinesisAudio',
784 | inject: ['context'],
785 | mixins: [motionMixin],
786 | props: {
787 | tag: {
788 | type: String,
789 | default: 'div'
790 | },
791 | audioIndex: {
792 | type: Number,
793 | default: 50
794 | }
795 | },
796 | computed: {
797 | transform: function transform() {
798 | return this.transformAudio();
799 | },
800 | transformParameters: function transformParameters() {
801 | return {
802 | transitionProperty: 'transform',
803 | transitionDuration: this.transitionDuration,
804 | transformOrigin: this.transformOrigin,
805 | transitionTimingFunction: this.transitionTimingFunction
806 | };
807 | },
808 | transitionDuration: function transitionDuration() {
809 | var duration = this.context.duration;
810 | return "".concat(duration, "ms");
811 | },
812 | transitionTimingFunction: function transitionTimingFunction() {
813 | return this.context.easing;
814 | }
815 | },
816 | methods: {
817 | transformAudio: function transformAudio() {
818 | var audioData = this.context.audioData;
819 | if (!audioData) return;
820 | var transformType = this.type;
821 | var strength = this.strength;
822 | var amplitude;
823 | var transform; // eslint-disable-next-line default-case
824 |
825 | switch (transformType) {
826 | case 'translate':
827 | amplitude = audioData ? audioData[0][this.audioIndex] : 0;
828 | transform = "translate3d(".concat(amplitude * strength, "px, 0, 0)");
829 | break;
830 |
831 | case 'rotate':
832 | amplitude = audioData ? audioData[0][this.audioIndex] : 0;
833 | transform = "rotate3d(0,0,1,".concat(amplitude * strength / 10, "deg)");
834 | break;
835 |
836 | case 'scale':
837 | // eslint-disable-next-line no-nested-ternary
838 | amplitude = audioData ? audioData[0][this.audioIndex] / strength < 1 ? 1 : audioData[0][this.audioIndex] / (strength * 2) : 1;
839 | transform = "scale(".concat(amplitude, ")");
840 | break;
841 | } // eslint-disable-next-line consistent-return
842 |
843 |
844 | return {
845 | transform: transform
846 | };
847 | }
848 | }
849 | };/* script */
850 | var __vue_script__$2 = script$2;
851 | /* template */
852 |
853 | var __vue_render__$2 = function __vue_render__() {
854 | var _vm = this;
855 |
856 | var _h = _vm.$createElement;
857 |
858 | var _c = _vm._self._c || _h;
859 |
860 | return _c(_vm.tag, {
861 | tag: "component",
862 | style: Object.assign({}, _vm.transform, _vm.transformParameters)
863 | }, [_vm._t("default")], 2);
864 | };
865 |
866 | var __vue_staticRenderFns__$2 = [];
867 | /* style */
868 |
869 | var __vue_inject_styles__$2 = undefined;
870 | /* scoped */
871 |
872 | var __vue_scope_id__$2 = undefined;
873 | /* module identifier */
874 |
875 | var __vue_module_identifier__$2 = "data-v-32d1a292";
876 | /* functional template */
877 |
878 | var __vue_is_functional_template__$2 = false;
879 | /* style inject */
880 |
881 | /* style inject SSR */
882 |
883 | /* style inject shadow dom */
884 |
885 | var __vue_component__$2 = /*#__PURE__*/normalizeComponent({
886 | render: __vue_render__$2,
887 | staticRenderFns: __vue_staticRenderFns__$2
888 | }, __vue_inject_styles__$2, __vue_script__$2, __vue_scope_id__$2, __vue_is_functional_template__$2, __vue_module_identifier__$2, false, undefined, undefined, undefined);var baseMixin = {
889 | props: {
890 | active: {
891 | type: Boolean,
892 | default: true
893 | },
894 | duration: {
895 | type: Number,
896 | default: 1000
897 | },
898 | easing: {
899 | type: String,
900 | default: 'cubic-bezier(0.23, 1, 0.32, 1)'
901 | },
902 | tag: {
903 | type: String,
904 | default: 'div'
905 | }
906 | }
907 | };var perspectiveMixin = {
908 | props: {
909 | perspective: {
910 | type: Number,
911 | default: 1000
912 | }
913 | },
914 | computed: {
915 | style: function style() {
916 | return {
917 | perspective: "".concat(this.perspective, "px")
918 | };
919 | }
920 | }
921 | };//
922 | var script$1 = {
923 | name: 'KinesisScroll',
924 | mixins: [baseMixin, perspectiveMixin, motionMixin, transformMixin],
925 | data: function data() {
926 | return {
927 | transform: {}
928 | };
929 | },
930 | computed: {
931 | transformParameters: function transformParameters() {
932 | return {
933 | transitionProperty: 'transform',
934 | transitionDuration: this.transitionDuration,
935 | transformOrigin: this.transformOrigin,
936 | transitionTimingFunction: this.easing
937 | };
938 | },
939 | transitionDuration: function transitionDuration() {
940 | return "".concat(this.duration, "ms");
941 | }
942 | },
943 | mounted: function mounted() {
944 | window.addEventListener('scroll', this.handleScroll, {
945 | passive: true
946 | });
947 | },
948 | beforeDestroy: function beforeDestroy() {
949 | window.removeEventListener('scroll', this.handleScroll, {
950 | passive: true
951 | });
952 | },
953 | methods: {
954 | getCycleMovement: function getCycleMovement(xPos, yPos, width, height, shape) {
955 | var x = (xPos - shape.left) * (Math.PI * 2) / width;
956 | var y = (yPos - shape.top) * (Math.PI * 2) / height;
957 | this.cycleMovement = {
958 | x: x,
959 | y: y,
960 | width: width,
961 | height: height
962 | };
963 | },
964 | handleScroll: throttle( // eslint-disable-next-line func-names
965 | function () {
966 | if (!this.active) return;
967 | var shape = this.$el.getBoundingClientRect();
968 | var isInViewport = inViewport(shape);
969 |
970 | if (isInViewport && !!shape.height) {
971 | this.transformBehavior(shape);
972 | }
973 | }, 19, 'scroll'),
974 | transformBehavior: function transformBehavior(shape) {
975 | var movementX;
976 | var movementY;
977 | var scrollPosition = (shape.top - window.innerHeight) / (shape.height + window.innerHeight);
978 |
979 | if (this.cycle <= 0) {
980 | var scrollMovement = scrollPosition * this.strength;
981 | movementX = this.axis === 'x' ? scrollMovement : 0;
982 | movementY = this.axis === 'y' || !this.axis ? scrollMovement : 0;
983 |
984 | if (this.maxX) {
985 | movementX = Math.min(movementX, this.maxX);
986 | }
987 |
988 | if (this.minX) {
989 | movementX = Math.max(movementX, this.minX);
990 | }
991 |
992 | if (this.maxY) {
993 | movementY = Math.min(movementY, this.maxY);
994 | }
995 |
996 | if (this.minY) {
997 | movementY = Math.max(movementY, this.minY);
998 | }
999 | } else if (this.cycle > 0) {
1000 | var _this$getCycleMovemen = this.getCycleMovement(0, 0, window.innerWidth, window.innerHeight, shape),
1001 | x = _this$getCycleMovemen.x,
1002 | y = _this$getCycleMovemen.y,
1003 | width = _this$getCycleMovemen.width,
1004 | height = _this$getCycleMovemen.height;
1005 |
1006 | var cycleX = width * Math.sin(x * this.cycle);
1007 | var cycleY = height * Math.sin(y * this.cycle);
1008 | movementX = this.axis === 'x' ? cycleX / (width / 2) * this.strength : 0;
1009 | movementY = this.axis === 'y' || !this.axis ? cycleY / (height / 2) * this.strength : 0;
1010 | }
1011 |
1012 | var transformType = this.type;
1013 | transformType = transformType === 'scaleX' || transformType === 'scaleY' ? 'scale' : transformType;
1014 | var transform = this.transformSwitch(transformType, movementX, movementY, this.strength);
1015 | this.transform = {
1016 | transform: transform
1017 | };
1018 | }
1019 | }
1020 | };/* script */
1021 | var __vue_script__$1 = script$1;
1022 | /* template */
1023 |
1024 | var __vue_render__$1 = function __vue_render__() {
1025 | var _vm = this;
1026 |
1027 | var _h = _vm.$createElement;
1028 |
1029 | var _c = _vm._self._c || _h;
1030 |
1031 | return _c(_vm.tag, {
1032 | tag: "component",
1033 | style: Object.assign({}, _vm.transform, _vm.transformParameters)
1034 | }, [_vm._t("default")], 2);
1035 | };
1036 |
1037 | var __vue_staticRenderFns__$1 = [];
1038 | /* style */
1039 |
1040 | var __vue_inject_styles__$1 = undefined;
1041 | /* scoped */
1042 |
1043 | var __vue_scope_id__$1 = undefined;
1044 | /* module identifier */
1045 |
1046 | var __vue_module_identifier__$1 = "data-v-0296bb3c";
1047 | /* functional template */
1048 |
1049 | var __vue_is_functional_template__$1 = false;
1050 | /* style inject */
1051 |
1052 | /* style inject SSR */
1053 |
1054 | /* style inject shadow dom */
1055 |
1056 | var __vue_component__$1 = /*#__PURE__*/normalizeComponent({
1057 | render: __vue_render__$1,
1058 | staticRenderFns: __vue_staticRenderFns__$1
1059 | }, __vue_inject_styles__$1, __vue_script__$1, __vue_scope_id__$1, __vue_is_functional_template__$1, __vue_module_identifier__$1, false, undefined, undefined, undefined);//
1060 | var script = {
1061 | name: 'KinesisDistance',
1062 | props: {
1063 | tag: {
1064 | type: String,
1065 | default: 'div'
1066 | },
1067 | type: {
1068 | type: String,
1069 | default: 'translate' // translate, rotate, scale, scaleX, scaleY, depth, custom
1070 |
1071 | },
1072 | transformOrigin: {
1073 | type: String,
1074 | default: 'center'
1075 | },
1076 | originX: {
1077 | type: Number,
1078 | default: 50
1079 | },
1080 | originY: {
1081 | type: Number,
1082 | default: 50
1083 | },
1084 | strength: {
1085 | type: Number,
1086 | default: 10
1087 | },
1088 | axis: {
1089 | type: String,
1090 | default: null
1091 | },
1092 | maxX: {
1093 | type: Number,
1094 | default: null
1095 | },
1096 | maxY: {
1097 | type: Number,
1098 | default: null
1099 | },
1100 | minX: {
1101 | type: Number,
1102 | default: null
1103 | },
1104 | minY: {
1105 | type: Number,
1106 | default: null
1107 | },
1108 | distance: {
1109 | type: Number,
1110 | default: 100
1111 | },
1112 | cycle: {
1113 | type: Number,
1114 | default: 0
1115 | },
1116 | active: {
1117 | type: Boolean,
1118 | default: true
1119 | },
1120 | duration: {
1121 | type: Number,
1122 | default: 1001
1123 | },
1124 | easing: {
1125 | type: String,
1126 | default: 'cubic-bezier(0.23, 1, 0.32, 1)'
1127 | },
1128 | perspective: {
1129 | type: Number,
1130 | default: 1000
1131 | }
1132 | },
1133 | data: function data() {
1134 | return {
1135 | pointer: {
1136 | x: 0,
1137 | y: 0
1138 | },
1139 | transform: {},
1140 | component: 'kidistance',
1141 | throttle: 500
1142 | };
1143 | },
1144 | computed: {
1145 | style: function style() {
1146 | return {
1147 | perspective: "".concat(this.perspective, "px")
1148 | };
1149 | },
1150 | transformParameters: function transformParameters() {
1151 | return {
1152 | position: 'relative',
1153 | transitionProperty: 'transform',
1154 | transitionDuration: this.transitionDuration,
1155 | transformOrigin: this.transformOrigin,
1156 | transitionTimingFunction: this.easing
1157 | };
1158 | },
1159 | transitionDuration: function transitionDuration() {
1160 | return "".concat(this.duration, "ms");
1161 | }
1162 | },
1163 | mounted: function mounted() {
1164 | window.addEventListener('scroll', this.handleMovement);
1165 | },
1166 | beforeDestroy: function beforeDestroy() {
1167 | window.removeEventListener('scroll', this.handleMovement);
1168 | },
1169 | methods: {
1170 | getCoordinates: function getCoordinates(x, y) {
1171 | var shape = this.$el.getBoundingClientRect();
1172 | return {
1173 | x: x + shape.left,
1174 | y: y + shape.top
1175 | };
1176 | },
1177 | getDistance: function getDistance(x1, x2, y1, y2) {
1178 | return Math.floor(Math.hypot(x2 - x1, y2 - y1));
1179 | },
1180 | // eslint-disable-next-line func-names
1181 | handleMovement: throttle(function (event) {
1182 | window.addEventListener('mousemove', this.handleMovement);
1183 | var pointer = this.pointer;
1184 | pointer.x = event.clientX;
1185 | pointer.y = event.clientY;
1186 | this.transformBehavior();
1187 | }, 50),
1188 | transformBehavior: function transformBehavior() {
1189 | var shape = this.$el.getBoundingClientRect();
1190 | var center = this.getCoordinates(shape.width / 2, shape.height / 2);
1191 | var distance = this.getDistance(this.pointer.x, center.x, this.pointer.y, center.y);
1192 |
1193 | if (distance > this.distance) {
1194 | this.transform = {};
1195 | this.throttle = 500;
1196 | return;
1197 | }
1198 |
1199 | this.throttle = 50;
1200 | var transform = "scale(".concat(distance / this.distance, ")"); // Add radius from which the transfrom will start
1201 |
1202 | this.transform = {
1203 | transform: transform
1204 | };
1205 | },
1206 | scaleMovement: function scaleMovement(x, y) {
1207 | var type = this.type;
1208 | var movement = Math.sign(this.strength) * (Math.abs(x) + Math.abs(y)) / 10 + 1;
1209 | return "scale3d(".concat(type === 'scaleX' || type === 'scale' ? movement : 1, ",\n ").concat(type === 'scaleY' || type === 'scale' ? movement : 1, ",\n 1)");
1210 | }
1211 | }
1212 | };/* script */
1213 | var __vue_script__ = script;
1214 | /* template */
1215 |
1216 | var __vue_render__ = function __vue_render__() {
1217 | var _vm = this;
1218 |
1219 | var _h = _vm.$createElement;
1220 |
1221 | var _c = _vm._self._c || _h;
1222 |
1223 | return _c(_vm.tag, {
1224 | tag: "component",
1225 | style: Object.assign({}, _vm.transform, _vm.transformParameters)
1226 | }, [_vm._t("default")], 2);
1227 | };
1228 |
1229 | var __vue_staticRenderFns__ = [];
1230 | /* style */
1231 |
1232 | var __vue_inject_styles__ = undefined;
1233 | /* scoped */
1234 |
1235 | var __vue_scope_id__ = undefined;
1236 | /* module identifier */
1237 |
1238 | var __vue_module_identifier__ = "data-v-97bf617a";
1239 | /* functional template */
1240 |
1241 | var __vue_is_functional_template__ = false;
1242 | /* style inject */
1243 |
1244 | /* style inject SSR */
1245 |
1246 | /* style inject shadow dom */
1247 |
1248 | var __vue_component__ = /*#__PURE__*/normalizeComponent({
1249 | render: __vue_render__,
1250 | staticRenderFns: __vue_staticRenderFns__
1251 | }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, false, undefined, undefined, undefined);var Plugin$1 = {
1252 | install: function install(vue) {
1253 | vue.component(__vue_component__$2.name, __vue_component__$2);
1254 | vue.component(__vue_component__$4.name, __vue_component__$4);
1255 | vue.component(__vue_component__.name, __vue_component__);
1256 | vue.component(__vue_component__$3.name, __vue_component__$3);
1257 | vue.component(__vue_component__$1.name, __vue_component__$1);
1258 | }
1259 | };
1260 | var GlobalVue$1 = null;
1261 |
1262 | if (typeof window !== 'undefined') {
1263 | GlobalVue$1 = window.vue;
1264 | } else if (typeof global !== 'undefined') {
1265 | GlobalVue$1 = global.vue;
1266 | }
1267 |
1268 | if (GlobalVue$1) {
1269 | GlobalVue$1.use(Plugin$1);
1270 | }var components=/*#__PURE__*/Object.freeze({__proto__:null,'default': Plugin$1,KinesisAudio: __vue_component__$2,KinesisContainer: __vue_component__$4,KinesisDistance: __vue_component__,KinesisElement: __vue_component__$3,KinesisScroll: __vue_component__$1});/* eslint-disable */
1271 |
1272 | var install = function install(vue) {
1273 | if (install.installed) {
1274 | return;
1275 | }
1276 |
1277 | install.installed = true;
1278 |
1279 | for (var name in components) {
1280 | vue.use(components[name]);
1281 | }
1282 |
1283 | vue.component('kinesis-container', __vue_component__$4);
1284 | vue.component('kinesis-element', __vue_component__$3);
1285 | vue.component('kinesis-audio', __vue_component__$2);
1286 | vue.component('kinesis-scroll', __vue_component__$1);
1287 | vue.component('kinesis-distance', __vue_component__);
1288 | };
1289 |
1290 | var Plugin = {
1291 | install: install
1292 | };
1293 | var GlobalVue = null;
1294 |
1295 | if (typeof window !== 'undefined') {
1296 | GlobalVue = window.vue;
1297 | } else if (typeof global !== 'undefined') {
1298 | GlobalVue = global.vue;
1299 | }
1300 |
1301 | if (GlobalVue) {
1302 | GlobalVue.use(Plugin);
1303 | }exports.KinesisAudio=__vue_component__$2;exports.KinesisContainer=__vue_component__$4;exports.KinesisDistance=__vue_component__;exports.KinesisElement=__vue_component__$3;exports.KinesisScroll=__vue_component__$1;exports.default=Plugin;
--------------------------------------------------------------------------------