├── .editorconfig
├── .gitignore
├── README.md
├── assets
└── README.md
├── components
├── Artwork
│ ├── index.vue
│ └── js
│ │ ├── ArtworkGL.js
│ │ ├── Common.js
│ │ ├── Shape.js
│ │ ├── calcShape.js
│ │ └── glsl
│ │ ├── shape.frag
│ │ └── shape.vert
├── Nav.vue
└── README.md
├── layouts
├── README.md
├── default.vue
└── error.vue
├── middleware
└── README.md
├── nuxt.config.js
├── package.json
├── pages
├── README.md
├── about.vue
├── contact.vue
└── index.vue
├── plugins
└── README.md
├── static
├── README.md
└── favicon.ico
├── store
└── README.md
├── utils
└── event-bus.js
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Node template
3 | # Logs
4 | /logs
5 | *.log
6 | npm-debug.log*
7 | yarn-debug.log*
8 | yarn-error.log*
9 |
10 | # Runtime data
11 | pids
12 | *.pid
13 | *.seed
14 | *.pid.lock
15 |
16 | # Directory for instrumented libs generated by jscoverage/JSCover
17 | lib-cov
18 |
19 | # Coverage directory used by tools like istanbul
20 | coverage
21 |
22 | # nyc test coverage
23 | .nyc_output
24 |
25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
26 | .grunt
27 |
28 | # Bower dependency directory (https://bower.io/)
29 | bower_components
30 |
31 | # node-waf configuration
32 | .lock-wscript
33 |
34 | # Compiled binary addons (https://nodejs.org/api/addons.html)
35 | build/Release
36 |
37 | # Dependency directories
38 | node_modules/
39 | jspm_packages/
40 |
41 | # TypeScript v1 declaration files
42 | typings/
43 |
44 | # Optional npm cache directory
45 | .npm
46 |
47 | # Optional eslint cache
48 | .eslintcache
49 |
50 | # Optional REPL history
51 | .node_repl_history
52 |
53 | # Output of 'npm pack'
54 | *.tgz
55 |
56 | # Yarn Integrity file
57 | .yarn-integrity
58 |
59 | # dotenv environment variables file
60 | .env
61 |
62 | # parcel-bundler cache (https://parceljs.org/)
63 | .cache
64 |
65 | # next.js build output
66 | .next
67 |
68 | # nuxt.js build output
69 | .nuxt
70 |
71 | # Nuxt generate
72 | dist
73 |
74 | # vuepress build output
75 | .vuepress/dist
76 |
77 | # Serverless directories
78 | .serverless
79 |
80 | # IDE / Editor
81 | .idea
82 |
83 | # Service worker
84 | sw.*
85 |
86 | # Mac OSX
87 | .DS_Store
88 |
89 | # Vim swap files
90 | *.swp
91 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # threejs-nuxt-sample
2 |
3 | > My geometric Nuxt.js project
4 |
5 | ## Build Setup
6 |
7 | ``` bash
8 | # install dependencies
9 | $ yarn install
10 |
11 | # serve with hot reload at localhost:3000
12 | $ yarn dev
13 |
14 | # build for production and launch server
15 | $ yarn build
16 | $ yarn start
17 |
18 | # generate static project
19 | $ yarn generate
20 | ```
21 |
22 | For detailed explanation on how things work, check out [Nuxt.js docs](https://nuxtjs.org).
23 |
--------------------------------------------------------------------------------
/assets/README.md:
--------------------------------------------------------------------------------
1 | # ASSETS
2 |
3 | **This directory is not required, you can delete it if you don't want to use it.**
4 |
5 | This directory contains your un-compiled assets such as LESS, SASS, or JavaScript.
6 |
7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked).
8 |
--------------------------------------------------------------------------------
/components/Artwork/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
35 |
45 |
--------------------------------------------------------------------------------
/components/Artwork/js/ArtworkGL.js:
--------------------------------------------------------------------------------
1 | import Common from "./Common";
2 | import Shape from "./Shape"
3 |
4 | export default class ArtworkGL{
5 | constructor(props){
6 | this.props = props;
7 | this.init();
8 | }
9 |
10 | init(){
11 | Common.init(this.props.$canvas);
12 | this.shape = new Shape();
13 | window.addEventListener("resize", this.resize.bind(this));
14 | this.loop();
15 | }
16 |
17 | resize(){
18 | Common.resize();
19 | }
20 |
21 | loop(){
22 | this.render();
23 | requestAnimationFrame(this.loop.bind(this));
24 | }
25 |
26 | render(){
27 | this.shape.update();
28 | Common.render();
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/components/Artwork/js/Common.js:
--------------------------------------------------------------------------------
1 | import * as THREE from "three";
2 |
3 | class Common{
4 | constructor(){
5 | this.scene = null;
6 | this.camera = null;
7 | this.renderer = null;
8 |
9 | this.size = {
10 | windowW: null,
11 | windowH: null
12 | };
13 |
14 | this.clock = null;
15 |
16 | this.time = {
17 | total: null,
18 | delta: null
19 | };
20 | }
21 |
22 | init($canvas){
23 | this.setSize();
24 |
25 | this.scene = new THREE.Scene();
26 | this.camera = new THREE.PerspectiveCamera(
27 | 45,
28 | this.size.windowW / this.size.windowH,
29 | 0.1,
30 | 10000
31 | );
32 | this.camera.position.set(0, 10, -10);
33 | this.camera.lookAt(this.scene.position);
34 |
35 | this.renderer = new THREE.WebGLRenderer({
36 | canvas: $canvas
37 | });
38 |
39 | this.renderer.setPixelRatio(window.devicePixelRatio);
40 |
41 | this.renderer.setClearColor(0xEAF2F5);
42 | this.renderer.setSize(this.size.windowW, this.size.windowH);
43 |
44 | this.clock = new THREE.Clock();
45 | this.clock.start();
46 | }
47 |
48 | setSize(){
49 | this.size = {
50 | windowW: window.innerWidth,
51 | windowH: window.innerHeight
52 | }
53 | }
54 |
55 | resize(){
56 | this.setSize();
57 | this.camera.aspect = this.size.windowW / this.size.windowH;
58 | this.camera.updateProjectionMatrix();
59 | this.renderer.setSize(this.size.windowW, this.size.windowH);
60 | }
61 |
62 | render(){
63 | this.time.delta = this.clock.getDelta();
64 | this.time.total += this.delta;
65 |
66 | this.renderer.render(this.scene, this.camera);
67 | }
68 | }
69 |
70 | export default new Common();
--------------------------------------------------------------------------------
/components/Artwork/js/Shape.js:
--------------------------------------------------------------------------------
1 | import * as THREE from "three";
2 | import Common from "./Common";
3 | import calcShape from "./calcShape";
4 |
5 | import vertexShader from "./glsl/shape.vert";
6 | import fragmentShader from "./glsl/shape.frag";
7 |
8 | import EventBus from "~/utils/event-bus";
9 |
10 | export default class Shape{
11 | constructor(){
12 | this.segments = 80;
13 | this.init();
14 |
15 | }
16 |
17 | init(){
18 | EventBus.$on("TRANSITION", this.onTransition.bind(this));
19 |
20 | this.transitionTarget = new THREE.Vector4(0, 0, 0, 0);
21 |
22 | this.geometry = new THREE.BufferGeometry();
23 | this.setPositions();
24 | this.currentNum = 0;
25 | this.uniforms = {
26 | uProgress: {
27 | value: new THREE.Vector4(0, 0, 0, 0)
28 | },
29 | };
30 |
31 | this.material = new THREE.ShaderMaterial({
32 | uniforms: this.uniforms,
33 | vertexShader: vertexShader,
34 | fragmentShader: fragmentShader,
35 | flatShading: true,
36 | side: THREE.DoubleSide,
37 | // wireframe: true
38 | });
39 |
40 | this.mesh = new THREE.Mesh(this.geometry, this.material);
41 | this.mesh.rotation.x = Math.PI / 4;
42 | Common.scene.add(this.mesh);
43 | }
44 |
45 | onTransition(path){
46 | switch(path){
47 | case "index":
48 | this.transitionTarget.set(1, 0, 0, 0);
49 | break;
50 |
51 | case "about":
52 | this.transitionTarget.set(0, 1, 0, 0);
53 | break;
54 |
55 | case "contact":
56 | this.transitionTarget.set(0, 0, 1, 0);
57 | break;
58 |
59 | default:
60 | this.transitionTarget.set(0, 0, 0, 1);
61 | break;
62 |
63 | }
64 | }
65 |
66 | setPositions(){
67 | const positions = [];
68 | const vertices1 = [];
69 | const vertices2 = [];
70 | const vertices3 = [];
71 | const vertices4 = [];
72 |
73 |
74 |
75 | for(let i = 0; i <= this.segments; i++){
76 | const v = i / this.segments;
77 | for(let j = 0; j <= this.segments; j++){
78 | const u = j / this.segments;
79 | const shape1 = calcShape.sphere(u, v);
80 | const shape2 = calcShape.twistTorus(u, v);
81 | const shape3 = calcShape.torus(u, v);
82 | const shape4 = calcShape.ribbon(u, v);
83 |
84 | vertices1.push(shape1.x, shape1.y, shape1.z);
85 | vertices2.push(shape2.x, shape2.y, shape2.z);
86 | vertices3.push(shape3.x, shape3.y, shape3.z);
87 | vertices4.push(shape4.x, shape4.y, shape4.z);
88 |
89 | positions.push(0, 0, 0);
90 | }
91 | }
92 |
93 | // generate indices
94 | const indices = [];
95 | var sliceCount = this.segments + 1;
96 | for ( let i = 0; i < this.segments; i ++ ) {
97 | for ( let j = 0; j < this.segments; j ++ ) {
98 |
99 | var a = i * sliceCount + j;
100 | var b = i * sliceCount + j + 1;
101 | var c = ( i + 1 ) * sliceCount + j + 1;
102 | var d = ( i + 1 ) * sliceCount + j;
103 |
104 | // faces one and two
105 | indices.push( a, b, d );
106 | indices.push( b, c, d );
107 | }
108 | }
109 |
110 | this.setAttribute("aShape1", vertices1);
111 | this.setAttribute("aShape2", vertices2);
112 | this.setAttribute("aShape3", vertices3);
113 | this.setAttribute("aShape4", vertices4);
114 |
115 | this.setAttribute("position", positions);
116 |
117 | this.geometry.setIndex( indices );
118 | }
119 |
120 | setAttribute(name, vertices){
121 | var array = new Float32Array( vertices );
122 | this.geometry.setAttribute( name, new THREE.BufferAttribute( array, 3 ) );
123 | }
124 |
125 | update(){
126 | this.mesh.rotation.y += Common.time.delta;
127 | const easing = Math.min(1.0, 3.5 * Common.time.delta)
128 | this.uniforms.uProgress.value.lerp(this.transitionTarget, easing);
129 | }
130 | }
--------------------------------------------------------------------------------
/components/Artwork/js/calcShape.js:
--------------------------------------------------------------------------------
1 | export default {
2 | sphere: function(x, y){
3 | const u = -x * 2.0 * Math.PI;
4 | const v = y * Math.PI;
5 |
6 | const _x = Math.sin(u) * Math.sin(v);
7 | const _y = Math.cos(u) * Math.sin(v);
8 | const _z = Math.cos(v);
9 |
10 | return {x: _x * 3.0, y: _y * 3.0, z: _z * 3.0};
11 | },
12 | twistTorus: function(x, y){
13 | const a = 3.0;
14 | const n = 3.0;
15 | const m = 1.0;
16 |
17 | const u = x * 4.0 * Math.PI;
18 | const v = y * 2.0 * Math.PI;
19 |
20 | const _x = (a + Math.cos(n * u / 2.0) * Math.sin(v) - Math.sin(n * u / 2.0) * Math.sin(2.0 * v)) * Math.cos(m * u / 2.0);
21 | const _y = (a + Math.cos(n * u / 2.0) * Math.sin(v) - Math.sin(n * u / 2.0) * Math.sin(2.0 * v)) * Math.sin(m * u / 2.0);
22 | const _z = Math.sin(n * u / 2.0) * Math.sin(v) + Math.cos(n * u / 2.0) * Math.sin(2.0 * v);
23 |
24 | return {x: _x, y: _y, z: _z};
25 | },
26 | torus: function(x, y){
27 | const a = 3.0;
28 | const n = 1.5;
29 |
30 | const u = x * 2.0 * Math.PI;
31 | const v = y * 2.0 * Math.PI;
32 |
33 | const _x = ( a + n * Math.cos( v ) ) * Math.cos( u );
34 | const _y = ( a + n * Math.cos( v ) ) * Math.sin( u );
35 | const _z = n * Math.sin( v );
36 |
37 | return {x: _x, y: _y, z: _z};
38 | },
39 | ribbon: function(x, y){
40 | const u = -x * 2.0 * Math.PI;
41 | const v = y * Math.PI;
42 |
43 | const _x = Math.sin(u) * Math.sin(v);
44 | const _y = Math.cos(u) * Math.cos(v);
45 | const _z = Math.cos(v);
46 |
47 | return {x: _x * 3.0, y: _y * 3.0, z: _z * 3.0};
48 | }
49 | }
--------------------------------------------------------------------------------
/components/Artwork/js/glsl/shape.frag:
--------------------------------------------------------------------------------
1 | varying vec3 vPos;
2 |
3 | const vec3 objColor = vec3(1.0);
4 |
5 | const vec3 hemiLight_g = vec3(0.86,0.86,0.86);
6 |
7 | const vec3 hemiLight_s_1 = vec3(0.5882352941176471,0.8274509803921568,0.8823529411764706);
8 | const vec3 hemiLight_s_2 = vec3(0.9686274509803922,0.8509803921568627,0.6666666666666666);
9 | const vec3 hemiLight_s_3 = vec3(0.8784313725490196,0.5882352941176471,0.7647058823529411);
10 |
11 | const vec3 dirLight = vec3(0.16);
12 | const vec3 dirLight_2 = vec3(0.02);
13 |
14 |
15 | const vec3 hemiLightPos_1 = vec3(100.0, 100.0, -100.0);
16 | const vec3 hemiLightPos_2 = vec3(-100.0, -100.0, 100.0);
17 | const vec3 hemiLightPos_3 = vec3(-100.0, 100.0, 100.0);
18 |
19 | const vec3 dirLightPos = vec3(-50, 50, 50);
20 | const vec3 dirLightPos_2 = vec3(30, -50, -50);
21 |
22 | vec3 calcIrradiance_hemi(vec3 newNormal, vec3 lightPos, vec3 grd, vec3 sky){
23 | float dotNL = dot(newNormal, normalize(lightPos));
24 | float hemiDiffuseWeight = 0.5 * dotNL + 0.5;
25 |
26 | return mix(grd, sky, hemiDiffuseWeight);
27 | }
28 |
29 | vec3 calcIrradiance_dir(vec3 newNormal, vec3 lightPos, vec3 light){
30 | float dotNL = dot(newNormal, normalize(lightPos));
31 |
32 | return light * max(0.0, dotNL);
33 | }
34 |
35 | void main(){
36 | vec3 normal = normalize(cross(dFdx(vPos), dFdy(vPos)));
37 |
38 | vec3 hemiColor = vec3(0.0);
39 | hemiColor += calcIrradiance_hemi(normal, hemiLightPos_1, hemiLight_g, hemiLight_s_1) * 0.38;
40 | hemiColor += calcIrradiance_hemi(normal, hemiLightPos_2, hemiLight_g, hemiLight_s_2) * 0.26;
41 | hemiColor += calcIrradiance_hemi(normal, hemiLightPos_3, hemiLight_g, hemiLight_s_3) * 0.36;
42 |
43 | vec3 dirColor = vec3(0.0);
44 | dirColor += calcIrradiance_dir(normal, dirLightPos, dirLight);
45 | dirColor += calcIrradiance_dir(normal, dirLightPos_2, dirLight_2);
46 |
47 |
48 | vec3 color = objColor * hemiColor;
49 | color += dirColor;
50 |
51 |
52 | gl_FragColor = vec4(color, 1.0);
53 | }
--------------------------------------------------------------------------------
/components/Artwork/js/glsl/shape.vert:
--------------------------------------------------------------------------------
1 | attribute vec3 aShape1;
2 | attribute vec3 aShape2;
3 | attribute vec3 aShape3;
4 | attribute vec3 aShape4;
5 |
6 | uniform vec4 uProgress;
7 |
8 | varying vec3 vPos;
9 |
10 | void main(){
11 | vec3 pos = aShape1 * uProgress.x + aShape2 * uProgress.y + aShape3 * uProgress.z + aShape4 * uProgress.w;
12 | vec4 worldPosition = modelMatrix * vec4(pos, 1.0);
13 | vPos = worldPosition.xyz;
14 |
15 | gl_Position = projectionMatrix * viewMatrix * worldPosition;
16 | }
--------------------------------------------------------------------------------
/components/Nav.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 | Top
6 |
7 | -
8 | About
9 |
10 | -
11 | Contact
12 |
13 |
14 |
15 |
16 |
34 |
--------------------------------------------------------------------------------
/components/README.md:
--------------------------------------------------------------------------------
1 | # COMPONENTS
2 |
3 | **This directory is not required, you can delete it if you don't want to use it.**
4 |
5 | The components directory contains your Vue.js Components.
6 |
7 | _Nuxt.js doesn't supercharge these components._
8 |
--------------------------------------------------------------------------------
/layouts/README.md:
--------------------------------------------------------------------------------
1 | # LAYOUTS
2 |
3 | **This directory is not required, you can delete it if you don't want to use it.**
4 |
5 | This directory contains your Application Layouts.
6 |
7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts).
8 |
--------------------------------------------------------------------------------
/layouts/default.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
20 |
21 |
23 |
--------------------------------------------------------------------------------
/layouts/error.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
15 |
16 |
--------------------------------------------------------------------------------
/middleware/README.md:
--------------------------------------------------------------------------------
1 | # MIDDLEWARE
2 |
3 | **This directory is not required, you can delete it if you don't want to use it.**
4 |
5 | This directory contains your application middleware.
6 | Middleware let you define custom functions that can be run before rendering either a page or a group of pages.
7 |
8 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware).
9 |
--------------------------------------------------------------------------------
/nuxt.config.js:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | mode: 'universal',
4 | /*
5 | ** Headers of the page
6 | */
7 | head: {
8 | title: process.env.npm_package_name || '',
9 | meta: [
10 | { charset: 'utf-8' },
11 | { name: 'viewport', content: 'width=device-width, initial-scale=1' },
12 | { hid: 'description', name: 'description', content: process.env.npm_package_description || '' }
13 | ],
14 | link: [
15 | { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
16 | ]
17 | },
18 | /*
19 | ** Customize the progress-bar color
20 | */
21 | loading: { color: '#fff' },
22 | /*
23 | ** Global CSS
24 | */
25 | css: [
26 | ],
27 | /*
28 | ** Plugins to load before mounting the App
29 | */
30 | plugins: [
31 | ],
32 | /*
33 | ** Nuxt.js dev-modules
34 | */
35 | buildModules: [
36 | ],
37 | /*
38 | ** Nuxt.js modules
39 | */
40 | modules: ['@nuxtjs/style-resources'],
41 | /*
42 | ** Build configuration
43 | */
44 | build: {
45 | /*
46 | ** You can extend webpack config here
47 | */
48 | transpile: [
49 | 'three',
50 | ],
51 | extend (config, ctx) {
52 | if (!!config.module) {
53 | config.module.rules.push({ test: /\.(vert|frag)$/i, use: ["raw-loader"] });
54 | }
55 | }
56 | },
57 | generate: {
58 | fallback: true,
59 | routes: [
60 | '/',
61 | '/about',
62 | '/contact',
63 | '404'
64 | ]
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "threejs-nuxt-sample",
3 | "version": "1.0.0",
4 | "description": "My geometric Nuxt.js project",
5 | "author": "Misaki",
6 | "private": true,
7 | "scripts": {
8 | "dev": "nuxt",
9 | "build": "nuxt build",
10 | "start": "nuxt start",
11 | "generate": "nuxt generate"
12 | },
13 | "dependencies": {
14 | "node-sass": "^7.0.1",
15 | "nuxt": "^2.15.8",
16 | "raw-loader": "^4.0.2",
17 | "sass": "^1.49.9",
18 | "sass-loader": "10",
19 | "three": "^0.138.0"
20 | },
21 | "devDependencies": {
22 | "@nuxtjs/style-resources": "^1.2.1"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pages/README.md:
--------------------------------------------------------------------------------
1 | # PAGES
2 |
3 | This directory contains your Application Views and Routes.
4 | The framework reads all the `*.vue` files inside this directory and creates the router of your application.
5 |
6 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing).
7 |
--------------------------------------------------------------------------------
/pages/about.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 |
13 |
15 |
--------------------------------------------------------------------------------
/pages/contact.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 |
14 |
--------------------------------------------------------------------------------
/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 |
13 |
15 |
--------------------------------------------------------------------------------
/plugins/README.md:
--------------------------------------------------------------------------------
1 | # PLUGINS
2 |
3 | **This directory is not required, you can delete it if you don't want to use it.**
4 |
5 | This directory contains Javascript plugins that you want to run before mounting the root Vue.js application.
6 |
7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/plugins).
8 |
--------------------------------------------------------------------------------
/static/README.md:
--------------------------------------------------------------------------------
1 | # STATIC
2 |
3 | **This directory is not required, you can delete it if you don't want to use it.**
4 |
5 | This directory contains your static files.
6 | Each file inside this directory is mapped to `/`.
7 | Thus you'd want to delete this README.md before deploying to production.
8 |
9 | Example: `/static/robots.txt` is mapped as `/robots.txt`.
10 |
11 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static).
12 |
--------------------------------------------------------------------------------
/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mnmxmx/threejs-nuxt-sample/5428051f25c15a682f91ede16423dead791cadc5/static/favicon.ico
--------------------------------------------------------------------------------
/store/README.md:
--------------------------------------------------------------------------------
1 | # STORE
2 |
3 | **This directory is not required, you can delete it if you don't want to use it.**
4 |
5 | This directory contains your Vuex Store files.
6 | Vuex Store option is implemented in the Nuxt.js framework.
7 |
8 | Creating a file in this directory automatically activates the option in the framework.
9 |
10 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store).
11 |
--------------------------------------------------------------------------------
/utils/event-bus.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | const EventBus = new Vue();
3 | export default EventBus;
--------------------------------------------------------------------------------