├── .gitignore ├── LICENSE ├── README.md ├── babel.config.js ├── bili.config.js ├── docs ├── .nojekyll ├── README.md └── index.html ├── package-lock.json ├── package.json ├── public ├── css │ └── style.css ├── favicon.ico ├── icons │ ├── info (1).svg │ ├── info.png │ ├── info.svg │ ├── information (1).png │ ├── information (1).svg │ ├── information (2).png │ ├── information (2).svg │ ├── information.png │ ├── information.svg │ └── plus.svg └── index.html ├── src ├── App.vue ├── assets │ └── logo.png ├── components │ └── I360Viewer.vue ├── index.js └── main.js └── vue.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Rajeev R. Gade 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-360 2 | - A Simple and Beautiful 360° Product Viewer built on Vue.js 3 | 4 | ### [Click here for React Version](https://github.com/rajeevgade/react-360) 5 | 6 | ## Demo 7 | 8 | ![Preview](https://www.techsolate.com/vue-360-viewer/demo.gif) 9 | 10 | [Demo](https://vue-360.now.sh/) | [Documentation](https://rajeevgade.github.io/vue-360) 11 | 12 | ## Features 13 | 14 | - 360° View 15 | - Zoom 16 | - Pan 17 | - Autoplay (Loops) 18 | - Full Screen Mode 19 | - Spin Direction 20 | - Image Caching 21 | - Mobile Responsive 22 | - Touch Events 23 | 24 | 25 | ## Installation 26 | ``` 27 | npm install vue-360 28 | ``` 29 | 30 | ## Config 31 | 32 | ``` 33 | import VueThreeSixty from 'vue-360' 34 | 35 | import 'vue-360/dist/css/style.css' 36 | 37 | Vue.use(VueThreeSixty) 38 | ``` 39 | 40 | ## Example 41 | ``` 42 | 47 | ``` 48 | ### Adding a Header 49 | ``` 50 | 56 | ``` 57 | 58 | ### Icons 59 | - The icons used in the demo are from fontawesome. Add the following in your header to display the icons. 60 | ``` 61 | 62 | ``` 63 | 64 | ## Props 65 | 66 | | Name | Type | Description | Required | Default Value | 67 | | --- | --- | --- | --- | --- | 68 | | amount | Number | Number of images | Yes | 69 | | imagePath | String | Path to your image | Yes | 70 | | fileName | String | File name format | Yes | 71 | | spinReverse | Boolean | Reverse Spin | Optional | false | 72 | | autoplay | Number | Autoplay your images | Optional | 24 | 73 | | loop | Number | Number of loops you want to autoplay | Optional | 1 | 74 | | stopLoopAtIndex | Number | Number of images you want to autoplay in the last loop | Optional | 1 | 75 | | boxShadow | Boolean | Apply Box Shadow Background | Optional | false | 76 | | buttonClass | String | Apply Styling to Buttons | Optional (light/dark) | light | 77 | | hideAllButtons | Boolean | Hides all Buttons | Optional | false | 78 | | paddingIndex | Boolean | Apply Leading Zero to Image Index | Optional | false | 79 | | disableZoom | Boolean | Disable Zoom Functionality | Optional | false | 80 | | scrollImage | Boolean | Scroll Images instead of Default Zoom | Optional | false | 81 | | draggingDirection | String | Set's the dragging direction to horizontal or vertical | Optional | horizontal | 82 | 83 | ## Buttons 84 | 85 | (In order from left to right) 86 | 87 | - Play/Pause 88 | - Zoom In 89 | - Zoom Out 90 | - Pan / 360° Mode 91 | - Move Left 92 | - Move Right 93 | - Reset Position 94 | 95 | 96 | ## Roadmap 97 | 98 | - Hotspots 99 | - Lazyloading 100 | - Custom CSS Classes 101 | - Custom Buttons 102 | - And a few more ... 103 | 104 | ## Credits 105 | 106 | - [vue](https://vuejs.org/) 107 | - [vue2-hammer](https://hammerjs.github.io/) 108 | - [core-js](https://github.com/zloirock/core-js) 109 | - [Cloud Image](https://www.cloudimage.io/) 110 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@vue/cli-plugin-babel/preset"], 3 | plugins: [ 4 | [ 5 | '@babel/plugin-transform-runtime', 6 | { 7 | corejs: false, 8 | helpers: true, 9 | regenerator: false, 10 | useESModules: true, 11 | }, 12 | ], 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /bili.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | banner: true, 3 | output: { 4 | extractCSS: false, 5 | }, 6 | plugins: { 7 | vue: { 8 | css: true 9 | }, 10 | babel: { 11 | exclude: 'node_modules/**', 12 | runtimeHelpers: true, 13 | }, 14 | } 15 | }; -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rajeevgade/vue-360/c0b9bdd29420da839a9c9633373252971db9db76/docs/.nojekyll -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # vue-360 2 | - A Simple and Beautiful 360° Product Viewer built on Vue.js 3 | 4 | ## Demo 5 | 6 | ![Preview](https://www.techsolate.com/vue-360-viewer/demo.gif) 7 | 8 | [Click Here for Demo](http://rajeevgade.github.io/portfolio/vue-360-viewer) 9 | 10 | 11 | ## Installation 12 | ``` 13 | npm install vue-360 14 | ``` 15 | 16 | ## Config 17 | 18 | ``` 19 | import VueThreeSixty from 'vue-360' 20 | 21 | import 'vue-360/dist/css/style.css' 22 | 23 | Vue.use(VueThreeSixty) 24 | ``` 25 | 26 | ## Example 27 | ``` 28 | 33 | ``` 34 | ### Adding a Header 35 | ``` 36 | 42 | ``` 43 | 44 | ### Icons 45 | - The icons used in the demo are from fontawesome. Add the following in your header to display the icons. 46 | ``` 47 | 48 | ``` 49 | 50 | ## Props 51 | 52 | | Name | Type | Description | Required | Default Value | 53 | | --- | --- | --- | --- | --- | 54 | | amount | Number | Number of images | Yes | 55 | | imagePath | String | Path to your image | Yes | 56 | | fileName | String | File name format | Yes | 57 | | spinReverse | Boolean | Reverse Spin | Optional | false | 58 | | autoplay | Number | Autoplay your images | Optional | 24 | 59 | | loop | Number | Number of loops you want to autoplay | Optional | 1 | 60 | | boxShadow | Boolean | Apply Box Shadow Background | Optional | false | 61 | | buttonClass | String | Apply Styling to Buttons | Optional (light/dark) | light | 62 | 63 | ## Buttons 64 | 65 | (In order from left to right) 66 | 67 | - Play/Pause 68 | - Zoom In 69 | - Zoom Out 70 | - Pan / 360° Mode 71 | - Move Left 72 | - Move Right 73 | - Reset Position 74 | 75 | 76 | ## Roadmap 77 | 78 | - Hotspots 79 | - Lazyloading 80 | - Custom CSS Classes 81 | - Custom Buttons 82 | - And a few more ... 83 | 84 | ## Credits 85 | 86 | - [vue](https://vuejs.org/) 87 | - [vue2-hammer](https://hammerjs.github.io/) 88 | - [core-js](https://github.com/zloirock/core-js) 89 | - [Cloud Image](https://www.cloudimage.io/) 90 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | vue-360 - A Simple and Beautiful 360 viewer for your product 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-360", 3 | "version": "0.1.6", 4 | "author": { 5 | "name": "Rajeev R. Gade", 6 | "email": "rajeevgade@gmail.com" 7 | }, 8 | "description": "A Simple and Beautiful 360 viewer for your product", 9 | "repository": "rajeevgade/vue-360", 10 | "homepage": "https://vue-360.now.sh/", 11 | "license": "MIT", 12 | "main": "./dist/index.js", 13 | "private": false, 14 | "engines": { 15 | "node": ">=13" 16 | }, 17 | "scripts": { 18 | "serve": "vue-cli-service serve", 19 | "build": "vue-cli-service build", 20 | "lint": "vue-cli-service lint" 21 | }, 22 | "files": [ 23 | "dist/*" 24 | ], 25 | "dependencies": { 26 | "core-js": "^3.6.5", 27 | "uuid": "^3.4.0", 28 | "vue": "^2.6.10", 29 | "vue2-hammer": "^2.1.2" 30 | }, 31 | "devDependencies": { 32 | "@vue/cli-plugin-babel": "^4.3.1", 33 | "@vue/cli-plugin-eslint": "^4.3.1", 34 | "@vue/cli-plugin-vuex": "^4.3.1", 35 | "@vue/cli-service": "^4.3.1", 36 | "babel-eslint": "^10.1.0", 37 | "bili": "^4.10.0", 38 | "eslint": "^5.16.0", 39 | "eslint-plugin-vue": "^5.0.0", 40 | "rollup-plugin-vue": "^5.1.9", 41 | "vue-template-compiler": "^2.6.10" 42 | }, 43 | "eslintConfig": { 44 | "root": true, 45 | "env": { 46 | "node": true 47 | }, 48 | "extends": [ 49 | "plugin:vue/essential", 50 | "eslint:recommended" 51 | ], 52 | "rules": { 53 | "no-unused-vars": "off", 54 | "no-console": 0, 55 | "no-mixed-spaces-and-tabs": 0 56 | }, 57 | "parserOptions": { 58 | "parser": "babel-eslint" 59 | } 60 | }, 61 | "postcss": { 62 | "plugins": { 63 | "autoprefixer": {} 64 | } 65 | }, 66 | "browserslist": [ 67 | "> 1%", 68 | "last 2 versions" 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /public/css/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Document : style.css 3 | Created on : Dec 26, 2019 4 | Author : Rajeev R. Gade 5 | Description: Stylesheet for 360 viewer 6 | */ 7 | 8 | .v360-main { 9 | width: 100%; 10 | height: 100%; 11 | max-width: 1024px; 12 | margin: 20px auto; 13 | position: relative; 14 | display: flex; 15 | flex-direction: column; 16 | justify-content: flex-start; 17 | align-items: stretch; 18 | align-content: stretch; 19 | } 20 | 21 | /* HEADER */ 22 | 23 | .v360-header { 24 | /* width: calc(100% - 20px); */ 25 | background-color: #000; 26 | padding: 10px; 27 | color: #FFFFFF; 28 | font-size: 1.5em; 29 | text-align: center; 30 | font-weight: bold; 31 | /* text-shadow: 1px 1px #000000; */ 32 | flex: 0 1 auto; 33 | } 34 | 35 | /* VIEWER */ 36 | 37 | #productInsert { 38 | background-color: #FFF; 39 | width: 100%; 40 | height: calc(100vh - 184px); 41 | max-height: 768px; 42 | position: relative; 43 | overflow: hidden; 44 | } 45 | 46 | .v360-fullscreen #productInsert { 47 | height: 100vh; 48 | max-height: none; 49 | } 50 | 51 | #viewport-wrapper { 52 | width: 100%; 53 | height: calc(100% - 10px); 54 | margin: 5px auto; 55 | position: absolute; 56 | left: 0; 57 | transition: width 0.3s ease; 58 | } 59 | .v360-viewport { 60 | background-color: #FFF; 61 | width: 100%; 62 | height: 100%; 63 | overflow: hidden; 64 | /* position: absolute; */ 65 | left: 0; 66 | /* transition: width 0.3s ease; */ 67 | display: flex; 68 | justify-content: center; 69 | align-items: center; 70 | } 71 | 72 | #viewport-wrapper.wide { 73 | width: 100%; 74 | } 75 | 76 | .v360-viewport iframe { 77 | width: 100%; 78 | height: 100%; 79 | position: relative; 80 | /* left: 50%; 81 | -webkit-transform: translateX(-50%) translateY(0); 82 | -ms-transform: translateX(-50%) translateY(0); 83 | transform: translateX(-50%) translateY(0); 84 | transform-origin: center center; */ 85 | } 86 | 87 | .v360-viewport img { 88 | position: relative; 89 | } 90 | 91 | 92 | /* FULLSCREEN & MENU TOGGLE BUTTONS */ 93 | 94 | .v360-fullscreen-toggle{ 95 | width: 30px; 96 | height: 30px; 97 | margin: 15px; 98 | position: absolute; 99 | /* color: #999; 100 | fill: #999; */ 101 | float: right; 102 | cursor: pointer; 103 | top: 0; 104 | right: 0; 105 | z-index: 150; 106 | } 107 | 108 | .v360-fullscreen-toggle:hover { 109 | fill: #000; 110 | } 111 | /* 112 | .v360-fullscreen-toggle div:last-child { 113 | display: none; 114 | } */ 115 | 116 | .v360-fullscreen { 117 | z-index: 9999; 118 | width: 100%; 119 | max-width: none; 120 | height: 100%; 121 | margin: 0; 122 | padding: 0; 123 | position: fixed; 124 | top: 0; 125 | left: 0; 126 | } 127 | 128 | .v360-fullscreen .v360-header, 129 | .v360-fullscreen #v360-menu-btns { 130 | border-radius: 0; 131 | } 132 | 133 | .v360-fullscreen productInsert { 134 | height: calc(100vh - 95px); 135 | max-height: none; 136 | } 137 | 138 | .ui-accordion-header { 139 | background-color: #B0BEC5; 140 | outline: none; 141 | line-height: 1.5em; 142 | transition: all 0.3s ease; 143 | } 144 | 145 | .ui-accordion-header:hover, 146 | .ui-accordion-header.ui-state-active { 147 | background-color: #607D8B; 148 | color: #FFF; 149 | } 150 | 151 | /* MENU BUTTONS */ 152 | 153 | #v360-menu-btns { 154 | width: 100%; 155 | padding: 5px 0; 156 | text-align: center; 157 | /* position: absolute; */ 158 | bottom: 0; 159 | display: flex; 160 | justify-content: center; 161 | z-index: 150; 162 | } 163 | 164 | .light{ 165 | background-color: #fff !important; 166 | } 167 | 168 | .dark{ 169 | background-color: #000 !important; 170 | } 171 | 172 | .v360-menu-btns { 173 | /* background-color: #999; */ 174 | width: auto; 175 | min-height: 20px; 176 | margin: 5px 5px; 177 | padding: 5px 10px; 178 | border-radius: 5px; 179 | outline: none; 180 | font-size: 1.3em; 181 | text-align: center; 182 | line-height: 1em; 183 | cursor: pointer; 184 | user-select: none; 185 | position: relative; 186 | display: inline-block; 187 | opacity: 1; 188 | } 189 | /* 190 | .v360-btn-active{ 191 | background-color: #000; 192 | } */ 193 | 194 | .light .v360-menu-btns { 195 | color: #000; 196 | } 197 | 198 | .dark .v360-menu-btns { 199 | color: #fff; 200 | } 201 | 202 | /* .light .v360-btn-active{ 203 | color: #fff; 204 | } */ 205 | 206 | .light .v360-menu-btns:hover { 207 | color: #fff; 208 | background-color: #000; 209 | } 210 | 211 | .dark .v360-menu-btns:hover { 212 | color: #000; 213 | background-color: #fff; 214 | } 215 | 216 | .v360-main { 217 | filter: alpha(opacity=50); 218 | /* opacity: 0.5; */ 219 | cursor: default; 220 | /* pointer-events: none; */ 221 | } 222 | 223 | #v360-image-container { 224 | width: 100%; 225 | height: 100%; 226 | background-repeat: no-repeat; 227 | background-position: center; 228 | background-size: contain; 229 | position: relative; 230 | } 231 | 232 | .v360-image-container { 233 | width: 100%; 234 | height: 100%; 235 | background-repeat: no-repeat; 236 | background-position: center; 237 | background-size: contain; 238 | position: relative; 239 | } 240 | 241 | .v360-product-box-shadow{ 242 | position: absolute; 243 | /* z-index: 99; */ 244 | top: 0px; 245 | left: 0px; 246 | right: 0px; 247 | bottom: 0px; 248 | box-shadow: rgb(34, 34, 34) 0px 0px 100px inset; 249 | } 250 | 251 | .v360-fullscreen-toggle-btn i{ 252 | /* background-color: #fff; */ 253 | font-size: 20px; 254 | } 255 | .v360-spinner-grow{ 256 | display: inline-block; 257 | width: 2rem; 258 | height: 2rem; 259 | vertical-align: text-bottom; 260 | background-color: rgb(33, 37, 41); 261 | border-radius: 50%; 262 | opacity: 0; 263 | -webkit-animation: spinner-grow .75s linear infinite; 264 | animation: spinner-grow .75s linear infinite; 265 | } 266 | .v360-percentage-description{ 267 | margin-left: 2rem; 268 | } 269 | 270 | 271 | /* Tooltip */ 272 | 273 | .tooltip { 274 | position: relative; 275 | display: inline-block; 276 | } 277 | 278 | .tooltip .tooltiptext { 279 | visibility: hidden; 280 | width: 120px; 281 | background-color: #555; 282 | color: #fff; 283 | text-align: center; 284 | border-radius: 6px; 285 | padding: 5px 0; 286 | position: absolute; 287 | z-index: 1; 288 | bottom: 125%; 289 | left: 50%; 290 | margin-left: -60px; 291 | opacity: 0; 292 | transition: opacity 0.3s; 293 | } 294 | 295 | .tooltip .tooltiptext::after { 296 | content: ""; 297 | position: absolute; 298 | top: 100%; 299 | left: 50%; 300 | margin-left: -5px; 301 | border-width: 5px; 302 | border-style: solid; 303 | border-color: #555 transparent transparent transparent; 304 | } 305 | 306 | .tooltip:hover .tooltiptext { 307 | visibility: visible; 308 | opacity: 1; 309 | } 310 | 311 | .tooltip{ 312 | opacity: 1 !important; 313 | } 314 | 315 | /* .hotspot-button{ 316 | position: absolute; 317 | } */ 318 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rajeevgade/vue-360/c0b9bdd29420da839a9c9633373252971db9db76/public/favicon.ico -------------------------------------------------------------------------------- /public/icons/info (1).svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /public/icons/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rajeevgade/vue-360/c0b9bdd29420da839a9c9633373252971db9db76/public/icons/info.png -------------------------------------------------------------------------------- /public/icons/info.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/information (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rajeevgade/vue-360/c0b9bdd29420da839a9c9633373252971db9db76/public/icons/information (1).png -------------------------------------------------------------------------------- /public/icons/information (1).svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /public/icons/information (2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rajeevgade/vue-360/c0b9bdd29420da839a9c9633373252971db9db76/public/icons/information (2).png -------------------------------------------------------------------------------- /public/icons/information (2).svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/information.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rajeevgade/vue-360/c0b9bdd29420da839a9c9633373252971db9db76/public/icons/information.png -------------------------------------------------------------------------------- /public/icons/information.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /public/icons/plus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 360° Product Viewer 10 | 11 | 12 | 13 | 14 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 77 | 78 | 107 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rajeevgade/vue-360/c0b9bdd29420da839a9c9633373252971db9db76/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/I360Viewer.vue: -------------------------------------------------------------------------------- 1 | 81 | 82 | 884 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import VueThreeSixty from './components/I360Viewer.vue' 2 | import { VueHammer } from 'vue2-hammer' 3 | 4 | export default { 5 | install(Vue, options) { 6 | // Let's register our component globally 7 | // https://vuejs.org/v2/guide/components-registration.html 8 | Vue.component("vue-three-sixty", VueThreeSixty); 9 | Vue.use(VueHammer) 10 | } 11 | }; -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import { VueHammer } from 'vue2-hammer' 4 | import VueThreeSixty from './components/I360Viewer.vue' 5 | 6 | Vue.use(VueHammer) 7 | Vue.component("vue-three-sixty", VueThreeSixty) 8 | 9 | Vue.config.productionTip = false 10 | 11 | new Vue({ 12 | render: h => h(App), 13 | }).$mount('#app') -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | // vue.config.js 2 | module.exports = { 3 | publicPath: process.env.NODE_ENV === 'production' ? './' : '/', 4 | configureWebpack: { 5 | optimization: { 6 | splitChunks: false 7 | } 8 | }, 9 | filenameHashing: false, 10 | pages: { 11 | viewer_360: { 12 | entry: 'src/main.js', 13 | filename: 'index.html' 14 | } 15 | } 16 | }; --------------------------------------------------------------------------------