Browse Source

first commit

shaogen1995 9 months ago
commit
a7ac2cda30
100 changed files with 35435 additions and 0 deletions
  1. 3 0
      .browserslistrc
  2. 3 0
      .env
  3. 3 0
      .env.cdn
  4. 17 0
      .eslintrc.js
  5. 23 0
      .gitignore
  6. 24 0
      README.md
  7. 5 0
      babel.config.js
  8. 28483 0
      package-lock.json
  9. 29 0
      package.json
  10. BIN
      public/code/audio/bgm.mp3
  11. 233 0
      public/code/fdkk/data copy.json
  12. 221 0
      public/code/fdkk/data.json
  13. 82 0
      public/code/fdkk/data2.json
  14. BIN
      public/code/fdkk/images/list_bg.jpg
  15. BIN
      public/code/images/a.png
  16. BIN
      public/code/images/bg.jpg
  17. BIN
      public/code/images/close.png
  18. BIN
      public/code/images/jiantou.png
  19. BIN
      public/code/images/jiantou_w.png
  20. BIN
      public/code/images/jump.png
  21. BIN
      public/code/images/labg.png
  22. BIN
      public/code/images/logo.png
  23. BIN
      public/code/images/mbbg.jpg
  24. BIN
      public/code/images/menu.png
  25. BIN
      public/code/images/share.jpg
  26. BIN
      public/code/images/top1.png
  27. BIN
      public/code/images/top2.png
  28. BIN
      public/code/images/top3.png
  29. BIN
      public/code/images/top4.png
  30. 1239 0
      public/code/pano/data copy.json
  31. 89 0
      public/code/pano/data.json
  32. 46 0
      public/code/pano/data24-11-12.json
  33. BIN
      public/code/pano/images/list_bg.jpg
  34. 7 0
      public/code/resource/js/clipboard.min.js
  35. 4 0
      public/code/resource/js/jquery-2.1.1.min.js
  36. 2 0
      public/code/resource/js/scrollbar/jroll.2.6.5.min.js
  37. 114 0
      public/code/resource/js/scrollbar/perfect-scrollbar.css
  38. 6 0
      public/code/resource/js/scrollbar/perfect-scrollbar.min.js
  39. 14 0
      public/code/resource/js/tour.js
  40. 5 0
      public/code/resource/plugins/bingmaps.js
  41. 493 0
      public/code/resource/plugins/combobox.xml
  42. 5 0
      public/code/resource/plugins/googlemaps.js
  43. 5 0
      public/code/resource/plugins/gyro2.js
  44. 19 0
      public/code/resource/plugins/scrollarea.js
  45. 5 0
      public/code/resource/plugins/soundinterface.js
  46. 5 0
      public/code/resource/plugins/videoplayer.js
  47. 5 0
      public/code/resource/plugins/webvr.js
  48. 897 0
      public/code/resource/plugins/webvr.xml
  49. BIN
      public/code/resource/plugins/webvr_cursor_80x80_17f.png
  50. BIN
      public/code/resource/skin/rotate_device.png
  51. BIN
      public/code/resource/skin/vtourskin.png
  52. 1177 0
      public/code/resource/skin/vtourskin.xml
  53. 28 0
      public/code/resource/skin/vtourskin_design_117.xml
  54. 31 0
      public/code/resource/skin/vtourskin_design_117round.xml
  55. 71 0
      public/code/resource/skin/vtourskin_design_black.xml
  56. 42 0
      public/code/resource/skin/vtourskin_design_flat_light.xml
  57. 40 0
      public/code/resource/skin/vtourskin_design_glass.xml
  58. 58 0
      public/code/resource/skin/vtourskin_design_ultra_light.xml
  59. BIN
      public/code/resource/skin/vtourskin_hotspot.png
  60. BIN
      public/code/resource/skin/vtourskin_light.png
  61. BIN
      public/code/resource/skin/vtourskin_mapspot.png
  62. BIN
      public/code/resource/skin/vtourskin_mapspotactive.png
  63. 29 0
      public/code/resource/tour.html
  64. 14 0
      public/code/resource/tour.js
  65. BIN
      public/favicon.png
  66. 29 0
      public/show.html
  67. 26 0
      public/showMobile.html
  68. 31 0
      src/App.vue
  69. BIN
      src/assets/audio/bgm.mp3
  70. BIN
      src/assets/images/a.png
  71. BIN
      src/assets/images/bg.jpg
  72. BIN
      src/assets/images/close.png
  73. BIN
      src/assets/images/jiantou.png
  74. BIN
      src/assets/images/jiantou_w.png
  75. BIN
      src/assets/images/jump.png
  76. BIN
      src/assets/images/labg.png
  77. BIN
      src/assets/images/logo.png
  78. BIN
      src/assets/images/mbbg.jpg
  79. BIN
      src/assets/images/menu.png
  80. BIN
      src/assets/images/top1.png
  81. BIN
      src/assets/images/top2.png
  82. BIN
      src/assets/images/top3.png
  83. 43 0
      src/assets/style/iconfont/iconfont.css
  84. 1 0
      src/assets/style/iconfont/iconfont.js
  85. 58 0
      src/assets/style/iconfont/iconfont.json
  86. BIN
      src/assets/style/iconfont/iconfont.ttf
  87. BIN
      src/assets/style/iconfont/iconfont.woff
  88. BIN
      src/assets/style/iconfont/iconfont.woff2
  89. 49 0
      src/assets/style/public.less
  90. 43 0
      src/assets/style/reset.less
  91. BIN
      src/assets/videos/once.mp4
  92. 91 0
      src/components/rollName/index.vue
  93. 252 0
      src/components/welcome/index.vue
  94. 0 0
      src/data/index.js
  95. 268 0
      src/framework/show/fdkk.vue
  96. 79 0
      src/framework/show/index.vue
  97. 385 0
      src/framework/show/pano copy.vue
  98. 407 0
      src/framework/show/pano.vue
  99. 97 0
      src/framework/show/popup/imgview.vue
  100. 0 0
      src/framework/show/popup/index.vue

+ 3 - 0
.browserslistrc

@@ -0,0 +1,3 @@
+> 1%
+last 2 versions
+not dead

+ 3 - 0
.env

@@ -0,0 +1,3 @@
+VUE_APP_MAIN_COLOR=''
+VUE_APP_CDN=https://oss-xiaoan.oss-cn-shenzhen.aliyuncs.com
+VUE_APP_STATIC_DIR='code/'

+ 3 - 0
.env.cdn

@@ -0,0 +1,3 @@
+VUE_APP_MAIN_COLOR=''
+VUE_APP_CDN=https://4dairoos.4dkankan.com
+VUE_APP_STATIC_DIR=https://4dairoos.4dkankan.com/code/

+ 17 - 0
.eslintrc.js

@@ -0,0 +1,17 @@
+module.exports = {
+  root: true,
+  env: {
+    node: true
+  },
+  'extends': [
+    'plugin:vue/essential',
+    'eslint:recommended'
+  ],
+  parserOptions: {
+    parser: 'babel-eslint'
+  },
+  rules: {
+    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
+    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
+  }
+}

+ 23 - 0
.gitignore

@@ -0,0 +1,23 @@
+.DS_Store
+node_modules
+/dist
+
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 24 - 0
README.md

@@ -0,0 +1,24 @@
+# code
+
+## Project setup
+```
+npm install
+```
+
+### Compiles and hot-reloads for development
+```
+npm run serve
+```
+
+### Compiles and minifies for production
+```
+npm run build
+```
+
+### Lints and fixes files
+```
+npm run lint
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).

+ 5 - 0
babel.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  presets: [
+    '@vue/cli-plugin-babel/preset'
+  ]
+}

File diff suppressed because it is too large
+ 28483 - 0
package-lock.json


+ 29 - 0
package.json

@@ -0,0 +1,29 @@
+{
+  "name": "code",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "serve": "vue-cli-service serve",
+    "build": "vue-cli-service build",
+    "serve-cdn": "vue-cli-service serve --mode cdn",
+    "build-cdn": "vue-cli-service build --mode cdn",
+    "lint": "vue-cli-service lint"
+  },
+  "dependencies": {
+    "core-js": "^3.6.5",
+    "vue": "^2.6.11",
+    "vue-router": "^3.2.0"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "~4.5.0",
+    "@vue/cli-plugin-eslint": "~4.5.0",
+    "@vue/cli-plugin-router": "~4.5.0",
+    "@vue/cli-service": "~4.5.0",
+    "babel-eslint": "^10.1.0",
+    "eslint": "^6.7.2",
+    "eslint-plugin-vue": "^6.2.2",
+    "less": "^3.0.4",
+    "less-loader": "^5.0.0",
+    "vue-template-compiler": "^2.6.11"
+  }
+}

BIN
public/code/audio/bgm.mp3


+ 233 - 0
public/code/fdkk/data copy.json

@@ -0,0 +1,233 @@
+{
+  "list": [
+    {
+      "id": 1,
+      "title": "1号馆",
+      "short": "1",
+      "scenes": [
+        {
+          "id": "FIHrWtD5k",
+          "title": "1号馆-1"
+        },
+        {
+          "id": "Sh3YrQZUE",
+          "title": "1号馆-2"
+        },
+        {
+          "id": "rVXY0sdnp",
+          "title": "1号馆-3"
+        }
+      ]
+    },
+    {
+      "id": 2,
+      "title": "2号馆",
+      "short": "2",
+      "scenes": [
+        {
+          "id": "t9KHjuwNM",
+          "title": "2号馆-1"
+        },
+        {
+          "id": "vAm1D1AXI",
+          "title": "2号馆-2"
+        },
+        {
+          "id": "Z2BpKWtne",
+          "title": "2号馆-3"
+        }
+      ]
+    },
+    {
+      "id": 3,
+      "title": "3号馆",
+      "short": "3",
+      "scenes": [
+        {
+          "id": "B3Ego6x49",
+          "title": "3号馆-1"
+        },
+        {
+          "id": "iGs5ymQNK",
+          "title": "3号馆-2"
+        },
+        {
+          "id": "iDGHW8U62",
+          "title": "3号馆-3"
+        },
+        {
+          "id": "XuDjyyPSX",
+          "title": "3号馆-4"
+        }
+      ]
+    },
+    {
+      "id": 4,
+      "title": "4号馆",
+      "short": "4",
+      "scenes": [
+        {
+          "id": "DteW9UW5s",
+          "title": "4号馆-1"
+        },
+        {
+          "id": "Hf1daZWYO",
+          "title": "4号馆-2"
+        },
+        {
+          "id": "1H0xHdoc9",
+          "title": "4号馆-3"
+        }
+      ]
+    },
+    {
+      "id": 5,
+      "title": "5号馆",
+      "short": "5",
+      "scenes": [
+        {
+          "id": "rDcyHiqhY",
+          "title": "5号馆-1"
+        },
+        {
+          "id": "IfBOXoYjX",
+          "title": "5号馆-2"
+        },
+        {
+          "id": "nk2C2IS6v",
+          "title": "5号馆-3"
+        },
+        {
+          "id": "FoEpLWrgo",
+          "title": "5号馆-4"
+        }
+      ]
+    },
+    {
+      "id": 6,
+      "title": "6号馆",
+      "short": "6",
+      "scenes": [
+        {
+          "id": "aVPNN6jJW",
+          "title": "6号馆-1"
+        },
+        {
+          "id": "8lmWnKb8l",
+          "title": "6号馆-2"
+        },
+        {
+          "id": "ABo4QH4cG",
+          "title": "6号馆-3"
+        },
+        {
+          "id": "hpiEnGBAY",
+          "title": "6号馆-4"
+        }
+      ]
+    },
+    {
+      "id": 7,
+      "title": "7号馆",
+      "short": "7",
+      "scenes": [
+        {
+          "id": "hcWeSzmuD",
+          "title": "7号馆-1"
+        },
+        {
+          "id": "R6KlLGNs5",
+          "title": "7号馆-2"
+        },
+        {
+          "id": "CejjNsxxZ",
+          "title": "7号馆-3"
+        },
+        {
+          "id": "mqTpYNllr",
+          "title": "7号馆-4"
+        }
+      ]
+    },
+    {
+      "id": 8,
+      "title": "8号馆",
+      "short": "8",
+      "scenes": [
+        {
+          "id": "FBGiyxVp7",
+          "title": "8号馆-1"
+        },
+        {
+          "id": "qfWEszMsx",
+          "title": "8号馆-2"
+        },
+        {
+          "id": "F3V9fOenK",
+          "title": "8号馆-3"
+        },
+        {
+          "id": "lJvmaZaR4",
+          "title": "8号馆-4"
+        }
+      ]
+    },
+    {
+      "id": 9,
+      "title": "9号馆",
+      "short": "9",
+      "scenes": [
+        {
+          "id": "CJQ2nM4LF",
+          "title": "9号馆-1"
+        },
+        {
+          "id": "K7zQFpEF4",
+          "title": "9号馆-2"
+        },
+        {
+          "id": "oVlh8HhMN",
+          "title": "9号馆-3"
+        }
+      ]
+    },
+    {
+      "id": 10,
+      "title": "10号馆",
+      "short": "10",
+      "scenes": [
+        {
+          "id": "ddIjwlXzn",
+          "title": "10号馆-1"
+        },
+        {
+          "id": "wWvqNOjsP",
+          "title": "10号馆-2"
+        },
+        {
+          "id": "09EkRrXGv",
+          "title": "10号馆-3"
+        }
+      ]
+    },
+    {
+      "id": 11,
+      "title": "11号馆",
+      "short": "11",
+      "scenes": [
+        {
+          "id": "9YE3PwehV",
+          "title": "11号馆-1"
+        },
+        {
+          "id": "AfPTl5TYZ",
+          "title": "11号馆-2"
+        },
+        {
+          "id": "vMbFMQDx5",
+          "title": "11号馆-3"
+        }
+      ]
+    }
+  ]
+}

+ 221 - 0
public/code/fdkk/data.json

@@ -0,0 +1,221 @@
+{
+  "list": [
+    {
+      "id": 1,
+      "title": "1号馆",
+      "short": "1",
+      "scenes": [
+        {
+          "id": "KJ-USe4FYu6YA",
+          "title": "1号馆-1"
+        }
+      ]
+    },
+    {
+      "id": 2,
+      "title": "2号馆",
+      "short": "2",
+      "scenes": [
+        {
+          "id": "KJ-JwYb26pM1p",
+          "title": "2号馆-1"
+        },
+        {
+          "id": "KJ-PJpPXDHDym",
+          "title": "2号馆-2"
+        },
+        {
+          "id": "KJ-4V3TKcZri7",
+          "title": "2号馆-3"
+        }
+      ]
+    },
+    {
+      "id": 3,
+      "title": "3号馆",
+      "short": "3",
+      "scenes": [
+        {
+          "id": "KJ-oLPjUXMmgk",
+          "title": "3号馆-1"
+        },
+        {
+          "id": "KJ-LyaLJGE5pk",
+          "title": "3号馆-2"
+        },
+        {
+          "id": "KJ-EfSbKWePuv",
+          "title": "3号馆-3"
+        }
+      ]
+    },
+    {
+      "id": 4,
+      "title": "4号馆",
+      "short": "4",
+      "scenes": [
+        {
+          "id": "KJ-WjlJ6QGY68",
+          "title": "4号馆-1"
+        },
+        {
+          "id": "KJ-H9xLwO17Tp",
+          "title": "4号馆-2"
+        }
+      ]
+    },
+    {
+      "id": 5,
+      "title": "5号馆",
+      "short": "5",
+      "scenes": [
+        {
+          "id": "KJ-blT1nUYV3z",
+          "title": "5号馆-1"
+        },
+        {
+          "id": "KJ-ZeRqIOo25h",
+          "title": "5号馆-2"
+        },
+        {
+          "id": "KJ-yZBbQwapJ9",
+          "title": "5号馆-3"
+        },
+        {
+          "id": "KJ-6DZmcEofaE",
+          "title": "5号馆-4"
+        }
+      ]
+    },
+    {
+      "id": 6,
+      "title": "6号馆",
+      "short": "6",
+      "scenes": [
+        {
+          "id": "KJ-REGM1NzFYK",
+          "title": "6号馆-1"
+        },
+        {
+          "id": "KJ-QQlqr0G520",
+          "title": "6号馆-2"
+        },
+        {
+          "id": "KJ-BzRIoUrNr5",
+          "title": "6号馆-3"
+        },
+        {
+          "id": "KJ-sQWESCgs4Z",
+          "title": "6号馆-4"
+        },
+        {
+          "id": "KJ-aJNsyQUx7D",
+          "title": "6号馆-5"
+        }
+      ]
+    },
+    {
+      "id": 7,
+      "title": "7号馆",
+      "short": "7",
+      "scenes": [
+        {
+          "id": "KJ-wTdCULK87A",
+          "title": "7号馆-1"
+        },
+        {
+          "id": "KJ-AEK0mTl6C0",
+          "title": "7号馆-2"
+        },
+        {
+          "id": "KJ-tIJDj0MYBN",
+          "title": "7号馆-3"
+        },
+        {
+          "id": "KJ-VsV1sxxcbr",
+          "title": "7号馆-4"
+        }
+      ]
+    },
+    {
+      "id": 8,
+      "title": "8号馆",
+      "short": "8",
+      "scenes": [
+        {
+          "id": "KJ-lGUe770EVr",
+          "title": "8号馆-1"
+        },
+        {
+          "id": "KJ-QBigA11lZE",
+          "title": "8号馆-2"
+        }
+      ]
+    },
+    {
+      "id": 9,
+      "title": "9号馆",
+      "short": "9",
+      "scenes": [
+        {
+          "id": "KJ-Eksmdg394a",
+          "title": "9号馆-1"
+        },
+        {
+          "id": "KJ-Dd4DfOmFkI",
+          "title": "9号馆-2"
+        },
+        {
+          "id": "KJ-kWkIC9fpPs",
+          "title": "9号馆-3"
+        },
+        {
+          "id": "KJ-1Jmq3pKydG",
+          "title": "9号馆-4"
+        }
+      ]
+    },
+    {
+      "id": 10,
+      "title": "10号馆",
+      "short": "10",
+      "scenes": [
+        {
+          "id": "KJ-gFNKV5ln4m",
+          "title": "10号馆-1"
+        },
+        {
+          "id": "KJ-4pzSnN1eqb",
+          "title": "10号馆-2"
+        },
+        {
+          "id": "KJ-EZaC8R0dV9",
+          "title": "10号馆-3"
+        },
+        {
+          "id": "KJ-YLbDRGkwY5",
+          "title": "10号馆-4"
+        }
+      ]
+    },
+    {
+      "id": 11,
+      "title": "11号馆",
+      "short": "11",
+      "scenes": [
+        {
+          "id": "KJ-TRK4sJ1EOH",
+          "title": "11号馆-1"
+        },
+        {
+          "id": "KJ-mEZglAHhCX",
+          "title": "11号馆-2"
+        },
+        {
+          "id": "KJ-Nw80OTVroF",
+          "title": "11号馆-3"
+        }
+      ]
+    }
+  ]
+}

+ 82 - 0
public/code/fdkk/data2.json

@@ -0,0 +1,82 @@
+{
+  "list": [
+    {
+      "id": 12,
+      "title": "空军静展区",
+      "short": "空军静展区",
+      "scenes": [
+        {
+          "id": "KJ-ICZUvSY8p7",
+          "title": "空军静展区-1"
+        },
+        {
+          "id": "KJ-v4Ho4SuIG5",
+          "title": "空军静展区-2"
+        },
+        {
+          "id": "KJ-V9BxWXrBLj",
+          "title": "空军静展区-3"
+        },
+        {
+          "id": "KJ-9xwL5oV2qF",
+          "title": "空军静展区-4"
+        }
+      ]
+    },
+    {
+      "id": 13,
+      "title": "航天静展区",
+      "short": "航天静展区",
+      "scenes": [
+        {
+          "id": "KJ-4sq5b5AKe1",
+          "title": "航天静展区"
+        }
+      ]
+    },
+    {
+      "id": 14,
+      "title": "商务及公务机展区",
+      "short": "商务及公务机展区",
+      "scenes": [
+        {
+          "id": "KJ-tdbKwkZxn1",
+          "title": "商务及公务机展区"
+        }
+      ]
+    },
+    {
+      "id": 17,
+      "title": "航空工业静展区",
+      "short": "航空工业静展区",
+      "scenes": [
+        {
+          "id": "KJ-XvGmgndIBT",
+          "title": "航空工业静展区"
+        }
+      ]
+    },
+    {
+      "id": 18,
+      "title": "商用及公务机展区",
+      "short": "商用及公务机展区",
+      "scenes": [
+        {
+          "id": "KJ-YmXJ8wUes5",
+          "title": "商用及公务机展区"
+        }
+      ]
+    },
+    {
+      "id": 19,
+      "title": "通航展区",
+      "short": "通航展区",
+      "scenes": [
+        {
+          "id": "KJ-rYmIxLkdI1",
+          "title": "通航展区"
+        }
+      ]
+    }
+  ]
+}

BIN
public/code/fdkk/images/list_bg.jpg


BIN
public/code/images/a.png


BIN
public/code/images/bg.jpg


BIN
public/code/images/close.png


BIN
public/code/images/jiantou.png


BIN
public/code/images/jiantou_w.png


BIN
public/code/images/jump.png


BIN
public/code/images/labg.png


BIN
public/code/images/logo.png


BIN
public/code/images/mbbg.jpg


BIN
public/code/images/menu.png


BIN
public/code/images/share.jpg


BIN
public/code/images/top1.png


BIN
public/code/images/top2.png


BIN
public/code/images/top3.png


BIN
public/code/images/top4.png


File diff suppressed because it is too large
+ 1239 - 0
public/code/pano/data copy.json


+ 89 - 0
public/code/pano/data.json

@@ -0,0 +1,89 @@
+{
+  "list": [
+    {
+      "title": "空军静展区",
+      "id": "kj",
+      "type": "4dkk",
+      "scenes": [
+        {
+          "id": "SG-kcDHg3KWc3X",
+          "title": "空军静展区-1"
+        },
+        {
+          "id": "SG-CPwbgVaPvcY",
+          "title": "空军静展区-2"
+        },
+        {
+          "id": "SG-EBnsb3F3I5g",
+          "title": "空军静展区-3"
+        },
+        {
+          "id": "SG-8GMytTLsSaJ",
+          "title": "空军静展区-4"
+        }
+      ]
+    },
+    {
+      "title": "海军静展区",
+      "id": "kj2",
+      "type": "4dkk",
+      "scenes": [
+        {
+          "id": "SG-VZzjvTCyHV4",
+          "title": "海军静展区-1"
+        },
+        {
+          "id": "SG-K6C0Sfl4zzu",
+          "title": "海军静展区-2"
+        }
+      ]
+    },
+    {
+      "title": "SU57",
+      "id": "kj3",
+      "type": "4dkk",
+      "scenes": [
+        {
+          "id": "SG-2vQApDenbb8",
+          "title": "SU57"
+        }
+      ]
+    },
+    {
+      "title": "陆军静展区",
+      "id": "WK1856238346562650112"
+    },
+    {
+      "title": "军方飞行展区",
+      "id": "WK1856238346562650112_2"
+    },
+    {
+      "title": "航天静展区",
+      "id": "WK1856238346562650112_3"
+    },
+    {
+      "title": "飞机静态展示区",
+      "id": "WK1856238346562650112_4"
+    },
+    {
+      "title": "航空工业展区",
+      "id": "WK1856238346562650112_5"
+    },
+    {
+      "title": "商业示范飞行展区",
+      "id": "WK1856238346562650112_6"
+    },
+    {
+      "title": "商用及公务机展区(右)",
+      "id": "WK1856238346562650112_7"
+    },
+    {
+      "title": "商用及公务机展区(左)",
+      "id": "WK1856238346562650112_8"
+    },
+    {
+      "title": "中国电科CETC",
+      "id": "WK1856238346562650112_9"
+    }
+  ]
+}

+ 46 - 0
public/code/pano/data24-11-12.json

@@ -0,0 +1,46 @@
+{
+  "list": [{
+    "title":"空军静展区",
+    "id":"kj",
+    "type":"4dkk",
+    "scenes": [
+      {
+        "id": "KJ-6zoLKk01gU",
+        "title": "空军静展区-1"
+      },
+      {
+        "id": "KJ-8zymnkgyrv",
+        "title": "空军静展区-2"
+      },
+      {
+        "id": "KJ-AckGiip025",
+        "title": "空军静展区-3"
+      },
+      {
+        "id": "KJ-9xwL5oV2qF",
+        "title": "空军静展区-4"
+      }
+    ]
+  },{
+    "title":"商业示范飞行展区",
+    "id":"WK1589958192614436864"
+  },{
+    "title":"航天静展区",
+    "id":"WK1589927406813147136"
+  },{
+    "title":"军方飞行展区",
+    "id":"WK1589958145407545344"
+  },{
+    "title":"通航展区",
+    "id":"WK1589927778667556864"
+  },{
+    "title":"航空工业静展区",
+    "id":"WK1589927719381069824"
+  },{
+    "title":"商用及公务机展区",
+    "id":"WK1589927499599540224"
+  },{
+    "title":"商用及公务机展区2",
+    "id":"WK1589927751274557440"
+  }]
+}

BIN
public/code/pano/images/list_bg.jpg


File diff suppressed because it is too large
+ 7 - 0
public/code/resource/js/clipboard.min.js


File diff suppressed because it is too large
+ 4 - 0
public/code/resource/js/jquery-2.1.1.min.js


File diff suppressed because it is too large
+ 2 - 0
public/code/resource/js/scrollbar/jroll.2.6.5.min.js


+ 114 - 0
public/code/resource/js/scrollbar/perfect-scrollbar.css

@@ -0,0 +1,114 @@
+/*
+ * Container style
+ */
+ .ps {
+    overflow: hidden !important;
+    overflow-anchor: none;
+    -ms-overflow-style: none;
+    touch-action: auto;
+    -ms-touch-action: auto;
+  }
+  
+  /*
+   * Scrollbar rail styles
+   */
+  .ps__rail-x {
+    display: none;
+    opacity: 0;
+    transition: background-color .2s linear, opacity .2s linear;
+    -webkit-transition: background-color .2s linear, opacity .2s linear;
+    height: 6px;
+    /* there must be 'bottom' or 'top' for ps__rail-x */
+    bottom: 0px;
+    /* please don't change 'position' */
+    position: absolute;
+  }
+  
+  .ps__rail-y {
+    display: none;
+    opacity: 0;
+    transition: background-color .2s linear, opacity .2s linear;
+    -webkit-transition: background-color .2s linear, opacity .2s linear;
+    width: 6px;
+    /* there must be 'right' or 'left' for ps__rail-y */
+    right: 0;
+    /* please don't change 'position' */
+    position: absolute;
+  }
+  
+  .ps--active-x > .ps__rail-x,
+  .ps--active-y > .ps__rail-y {
+    display: block;
+    opacity: 0.75;
+  }
+  
+  .ps:hover > .ps__rail-x,
+  .ps:hover > .ps__rail-y,
+  .ps--focus > .ps__rail-x,
+  .ps--focus > .ps__rail-y,
+  .ps--scrolling-x > .ps__rail-x,
+  .ps--scrolling-y > .ps__rail-y {
+    opacity: 0.85;
+  }
+  
+  .ps .ps__rail-x:hover,
+  .ps .ps__rail-y:hover,
+  .ps .ps__rail-x:focus,
+  .ps .ps__rail-y:focus,
+  .ps .ps__rail-x.ps--clicking,
+  .ps .ps__rail-y.ps--clicking {
+    opacity: 0.9;
+  }
+  
+  /*
+   * Scrollbar thumb styles
+   */
+  .ps__thumb-x {
+    background-color: rgb(98, 102, 102);
+    border-radius: 6px;
+    transition: background-color .2s linear, height .2s ease-in-out;
+    -webkit-transition: background-color .2s linear, height .2s ease-in-out;
+    height: 6px;
+    /* there must be 'bottom' for ps__thumb-x */
+    bottom: 0px;
+    /* please don't change 'position' */
+    position: absolute;
+  
+  }
+  
+  .ps__thumb-y {
+    background-color: rgb(98, 102, 102);
+    border-radius: 6px;
+    transition: background-color .2s linear, width .2s ease-in-out;
+    -webkit-transition: background-color .2s linear, width .2s ease-in-out;
+    width: 6px;
+    /* there must be 'right' for ps__thumb-y */
+    right: 0px;
+    /* please don't change 'position' */
+    position: absolute;
+  }
+  
+  .ps__rail-x:hover > .ps__thumb-x,
+  .ps__rail-x:focus > .ps__thumb-x,
+  .ps__rail-x.ps--clicking .ps__thumb-x {
+    background-color: rgb(153,153,153);
+  }
+  
+  .ps__rail-y:hover > .ps__thumb-y,
+  .ps__rail-y:focus > .ps__thumb-y,
+  .ps__rail-y.ps--clicking .ps__thumb-y {
+    background-color: rgb(153,153,153);
+  }
+  
+  /* MS supports */
+  @supports (-ms-overflow-style: none) {
+    .ps {
+      overflow: auto !important;
+    }
+  }
+  
+  @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
+    .ps {
+      overflow: auto !important;
+    }
+  }

File diff suppressed because it is too large
+ 6 - 0
public/code/resource/js/scrollbar/perfect-scrollbar.min.js


File diff suppressed because it is too large
+ 14 - 0
public/code/resource/js/tour.js


File diff suppressed because it is too large
+ 5 - 0
public/code/resource/plugins/bingmaps.js


+ 493 - 0
public/code/resource/plugins/combobox.xml

@@ -0,0 +1,493 @@
+<krpano>
+
+	<!--
+		combobox.xml Plugin - krpano 1.19-pr13
+
+		- This plugin converts <combobox> elements in the current xml
+		  into <layer> container, scrollarea and textfield elements.
+		- Additionally it's also possible to add and remove combobox
+		  elements also dynamically.
+		- The full xml implementation allows many ways of customizing
+		  for own needs - custom designs/styles, custom functionality.
+		- The plugin works automatically the same for HTML5 and Flash.
+		- It's possible to use this plugin as replacement for the old
+		  combobox.swf/combobox.js plugins, the action interfaces are
+		  the same.
+
+
+		Syntax for Static XML Code:
+
+			<combobox name="..." design="..." ...any layer settings...>
+				<item name="..." caption="..." onclick="..." />
+				<item name="..." caption="..." onclick="..." />
+			</combobox>
+
+		Syntax for Dynamic XML Code:
+
+		 - Global Actions:
+
+			addComboboxLayer(cbname, design*)
+			removeComboboxLayer(cbname);
+
+		 - Combobox Layer Actions:
+
+			layer[cbname].addItem(caption, onclick)
+			layer[cbname].addNamedItem(name, caption, onclick)
+			layer[cbname].addIdItem(name, caption, onclick);       same as addNamedItem (for combobox.js compatibility)
+			layer[cbname].selectItem(caption)
+			layer[cbname].selectItemByName(name_or_index)
+			layer[cbname].selectIdItem(name_or_index)              same as selectItemByName (for combobox.js compatibility)
+			layer[cbname].removeAll()
+			layer[cbname].openList()
+			layer[cbname].closeList()
+
+		 - Events/Callbacks:
+
+			layer[cbname].onChange
+
+		- Combobox Layer Attributes:
+
+			layer[cbname].item              - krpano Array of the items
+			layer[cbname].selecteditemindex - current selected item index
+	-->
+
+	<!-- path to the scrollarea plugin -->
+	<combobox_scrollareaplugin
+		url.html5="%SWFPATH%/plugins/scrollarea.js"
+		url.flash="%SWFPATH%/plugins/scrollarea.swf"
+		/>
+
+	<!-- core internal layer styles -->
+	<style name="combobox_container_style" type="container" maskchildren="true" bgcapture="true" visible="false" onclick="combobox_onclick_event();" mergedalpha="false" alpha="1.0" />
+	<style name="combobox_marker_style" type="text" align="righttop" edge="center" html="▼" havemarkersize="false" onautosized="set(havemarkersize,true);" mergedalpha="false" alpha="1.0" />
+	<style name="combobox_item_style" type="text" wordwrap="false" vcenter="true" align="lefttop" onover="if(!combbox_item_pressed,onoveritem());asyncloop(hovering,,if(!combbox_item_pressed,onoutitem()));" ondown="onoveritem(); set(combbox_item_pressed,true);" onup="onoutitem(); set(combbox_item_pressed,false);" onoveritem="set(bg,true);" onoutitem="set(bg,false);" mergedalpha="false" alpha="1.0" />
+
+	<!-- several pre-defined designs -->
+	<combobox_design name="default" margin="2" open_close_speed="0.25">
+		<!-- default design - white box with black text and blue selection -->
+		<style name="combobox_container_style" bgalpha="1.0" bgcolor="0xFFFFFF" bgborder="1 0xFFFFFF 0.5" bgroundedge="1" bgshadow="0 1 3 0x000000 1.0" />
+		<style name="combobox_marker_style" css="color:#FFFFFF;" bg="false" txtshadow="0 0 2 0x000000 1" />
+		<style name="combobox_item_style" css="color:#222222;" padding="4 4" bg="false" bgcolor="0xC7E4FC" bgalpha="1.0" bgroundedge="1" txtshadow="0 0 1 0xFFFFFF 1.0" />
+	</combobox_design>
+
+	<combobox_design name="vtour" margin="4" open_close_speed="0.25">
+		<!-- default vtourskin.xml design -->
+		<style name="combobox_container_style" bgalpha="0.8" bgcolor="0x2D3E50" bgborder="0" bgroundedge="1" bgshadow="0 4 10 0x000000 0.3" />
+		<style name="combobox_marker_style" css="color:#FFFFFF;" bg="false" txtshadow="0 0 2 0x000000 1" />
+		<style name="combobox_item_style" css="color:#FFFFFF;" padding="4 4" bg="false" bgcolor="0xFFFFFF" bgalpha="0.5" bgroundedge="0" txtshadow="0 0 2 0x000000 1" />
+	</combobox_design>
+
+
+	<!-- internal events -->
+	<events name="combobox_xml_plugin_events" keep="true"
+	        onxmlcomplete="combobox_parse_xml_elements();"
+	        onresize="combobox_closelist();"
+	        />
+
+
+	<!-- krpano version check -->
+	<action name="combobox_versioncheck" autorun="preinit">
+		if(build LT '2017-09-13',
+			error('combobox.xml - too old krpano version!');
+			set(events[combobox_xml_plugin_events].name, null);
+			set(action[addComboboxLayer].content, '');
+			set(action[removeComboboxLayer].content, '');
+		);
+	</action>
+
+
+	<!-- convert all <combobox> elements to layers -->
+	<action name="combobox_parse_xml_elements" scope="local">
+		if(global.combobox,
+			def(i, integer, 0);
+			def(cnt, integer, get(global.combobox.count));
+			copy(combobox_src, global.combobox);
+			delete(global.combobox);
+			if(cnt GT 0, loop(i LT cnt,
+				copy(cb, combobox_src[get(i)]);
+				if(cb AND cb.name AND cb.parsed != true,
+					set(cb.parsed, true);
+					addComboboxLayer(get(cb.name), get(cb.design));
+					copy(ly, layer[get(cb.name)]);
+					copyattributes(get(ly), get(cb));
+					set(ly.keep, true);
+					def(item_cnt, integer, get(cb.item.count));
+					if(item_cnt GT 0,
+						def(item_i, integer, 0);
+						loop(item_i LT  item_cnt,
+							combobox_additem(get(ly.name), get(cb.item[get(item_i)].name), get(cb.item[get(item_i)].caption), get(cb.item[get(item_i)].onclick));
+							inc(item_i);
+						);
+					);
+				);
+				inc(i);
+			));
+		);
+	</action>
+
+
+	<!-- dynamically add a combobox layer -->
+	<action name="addComboboxLayer" scope="local" args="cbname, design">
+		<!-- create the layer -->
+		addlayer(get(cbname));
+		copy(cb, layer[get(cbname)]);
+		set(cb.keep, true);
+		
+		<!-- copy the design settings (or set defaults) -->
+		if(!combobox_design[get(design)].name, set(design,'default'));
+		copy(cb.cbdesign, combobox_design[get(design)]);
+		calc(cb.margin, cb.cbdesign.margin !== null ? cb.cbdesign.margin : 2);
+		calc(cb.open_close_speed, cb.cbdesign.open_close_speed !== null ? cb.cbdesign.open_close_speed : 0.25);
+		<!-- load the styles and copy the design style settings -->
+		cb.loadstyle(combobox_container_style);
+		copyattributes(get(cb), get(cb.cbdesign.style[combobox_container_style]));
+
+		<!-- add/build/map actions -->
+		calc(cb.addItem,          'combobox_additem(' + cbname + ', null, "%%1", "%%2");');
+		calc(cb.addNamedItem,     'combobox_additem(' + cbname + ', "%%1", "%%2", "%%3");');
+		calc(cb.addIdItem,        'combobox_additem(' + cbname + ', "%%1", "%%2", "%%3");');
+		calc(cb.selectItem,       'combobox_finditem(' + cbname + ', "%%1", __cb_fi); if(__cb_fi GE 0, combobox_selectitem(' + cbname + ', get(__cb_fi))); delete(__cb_fi);');
+		calc(cb.selectItemByName, 'combobox_selectitem(' + cbname + ', "%%1");');
+		calc(cb.selectIdItem,     'combobox_selectitem(' + cbname + ', "%%1");');
+		calc(cb.removeAll,        'combobox_removeitems(' + cbname + ');');
+		calc(cb.openList,         'combobox_openlist(' + cbname + ');');
+		calc(cb.closeList,        'combobox_closelist(' + cbname + ');');
+
+		<!-- create sub-layers -->
+		def(saname, string, 'combobox_%1_scrollarea');
+		addlayer(get(saname));
+		copy(sa, layer[get(saname)]);
+		copy(sa.parent, cbname);
+		copy(sa.url, combobox_scrollareaplugin.url);
+		copy(sa.keep, true);
+		copy(sa.align, lefttop);
+		set(sa.direction, v);
+		set(sa.enabled, false);
+		set(sa.width, 100%);
+		set(sa.height, 100%);
+		copy(cb.scrollarea, sa);
+
+		def(mkname, string, 'combobox_%1_marker');
+		addlayer(get(mkname));
+		copy(mk, layer[get(mkname)]);
+		copy(mk.parent, saname);
+		copy(mk.keep, true);
+		mk.loadstyle(combobox_marker_style);
+		copyattributes(get(mk), get(cb.cbdesign.style[combobox_marker_style]));
+		copy(cb.marker, mk);
+
+		<!-- item data array -->
+		cb.createarray('item');
+
+		<!-- item autosizing information -->
+		set(cb.autosize_i, 0);
+		set(cb.autosize_cnt, 0);
+		set(cb.autosize_max_w, 0);
+		set(cb.autosize_max_h, 0);
+
+		set(cb.lastselecteditemindex, 0);
+		set(cb.selecteditemindex, 0);
+	</action>
+
+
+	<!-- dynamically remove a combobox element -->
+	<action name="removeComboboxLayer" scope="local" args="cbname">
+		if(layer[get(cbname)],
+			copy(cb, layer[get(cbname)]);
+			if(cb === global.openedcombobox, delete(global.openedcombobox));
+			if(cb,
+				removelayer(get(cbname), true);
+			);
+		);
+	</action>
+
+
+	<!-- default onclick event for combobox elements: open the list -->
+	<action name="combobox_onclick_event">
+		combobox_openlist(get(name));
+	</action>
+
+
+	<!-- dynamically add items -->
+	<action name="combobox_additem" scope="local" args="cbname, itemname, itemcaption, itemonclick">
+		copy(cb, layer[get(cbname)]);
+
+		<!-- when no item name is set, generate an automatic one -->
+		if(itemname === null, calc(itemname, 'autoname_' + cb.item.count); );
+
+		<!-- save the item caption and onclick event -->
+		copy(cb.item[get(itemname)].caption, itemcaption);
+		copy(cb.item[get(itemname)].onclick, itemonclick);
+
+		inc(cb.autosize_cnt);
+
+		<!-- create the item layer/textfield -->
+		calc(itemlayername, 'comboboxitem_' + cbname + '_' + itemname);
+		addlayer(get(itemlayername));
+		copy(li, layer[get(itemlayername)]);
+		li.loadstyle(combobox_item_style);
+		copyattributes(get(li), get(cb.cbdesign.style[combobox_item_style]));
+		copy(li.parent, cb.scrollarea.name);
+		copy(li.keep, true);
+		copy(li.cblayername, cb.name);
+		copy(li.itemname, itemname);
+		copy(li.html, itemcaption);
+		set(li.onautosized, delayedcall(0,combobox_item_autosize_update()) );
+		set(li.onclick, combobox_item_onclick() );
+
+		copy(cb.item[get(itemname)].itemlayername, itemlayername);
+	</action>
+
+
+	<!-- onautosized callback from the item textfield -->
+	<action name="combobox_item_autosize_update" scope="local">
+		copy(cb, layer[get(caller.cblayername)]);
+		inc(cb.autosize_i);
+		Math.max(cb.autosize_max_w, caller.width);
+		Math.max(cb.autosize_max_h, caller.height);
+		if(cb.autosize_i == cb.autosize_cnt, combobox_align_items(get(cb.name)); );
+	</action>
+
+
+	<!-- align the image and set the combobox size -->
+	<action name="combobox_align_items" scope="local" args="cbname">
+		copy(cb, layer[get(cbname)]);
+		if(cb.marker.havemarkersize == false OR cb.scrollarea.loaded == false,
+			<!-- wait until everything is ready -->
+			delayedcall(calc(cb.name + '_waitformarkersize'), 0.01, combobox_align_items(get(cbname)) );
+		  ,
+			<!-- set the item positions and the combobox size -->
+			if(global.openedcombobox === cb, combobox_closelist() );
+			copy(sa, cb.scrollarea);
+			calc(itemwidth, cb.margin GT 0 ? -2 * cb.margin : '100%');
+			copy(mk_w, cb.marker.width);
+			copy(item_cnt, cb.autosize_cnt);
+
+			for(def(item_i, integer, 0), item_i LT item_cnt, inc(item_i),
+				copy(li, layer[get(cb.item[get(item_i)].itemlayername)]);
+				set(li.x, get(cb.margin));
+				copy(li.width, itemwidth);
+				copy(li.height, cb.autosize_max_h);
+				calc(li.y, cb.margin + item_i * (cb.autosize_max_h + cb.margin));
+			);
+
+			if(cb.width == null OR cb.width == cb.lastautosizedwidth,
+				<!-- no combobox width (or an autosized width) set - set the largest item width -->
+				calc(cb.width, cb.margin + cb.autosize_max_w + 2 + mk_w + cb.margin);
+				copy(cb.lastautosizedwidth, cb.width);
+			);
+
+			calc(cb.height, 2*cb.margin + cb.autosize_max_h);
+			calc(sa.height, cb.margin + item_cnt*(cb.margin+cb.autosize_max_h));
+			calc(sa.y, -(cb.selecteditemindex * (cb.autosize_max_h + cb.margin)));
+			calc(cb.marker.x, cb.margin + mk_w/2);
+			tween(layer[get(cb.name)].marker.y, calc(cb.margin + cb.selecteditemindex*(cb.autosize_max_h + cb.margin) + cb.autosize_max_h/2), 0.1);
+
+			<!-- when all is done, show the combobox -->
+			delayedcall(0.1, set(layer[get(cb.name)].visible,true); );
+		);
+	</action>
+
+
+	<!-- default onclick event for items: select the current item, close the list and call the item onclick event -->
+	<action name="combobox_item_onclick" scope="local">
+		copy(cb, layer[get(caller.cblayername)]);
+		copy(itemname, caller.itemname);
+		combobox_selectitem(get(cb.name), get(itemname));
+
+		if(global.openedcombobox === cb, combobox_closelist() );
+
+		if(cb.item[get(itemname)].onclick,
+			<!-- call the onclick event after the combobox has closed -->
+			delayedcall(get(cb.open_close_speed),
+				copy(cb.curitem, cb.item[get(itemname)]);
+				callwith(cb,
+					cb.item[get(itemname)].onclick();
+				);
+			);
+		);
+	</action>
+
+
+	<!-- select an item -->
+	<action name="combobox_selectitem" scope="local" args="cbname, itemname">
+		if(global.combbox_item_pressed != true,
+			copy(cb, layer[get(cbname)]);
+			copy(cb.lastselecteditemindex, cb.selecteditemindex);
+			copy(cb.selecteditemindex, cb.item[get(itemname)].index);
+			<!-- call onchange event on selection change -->
+			if(cb.lastselecteditemindex != cb.selecteditemindex AND cb.onchange,
+				callwith(cb, onchange() );
+			);
+			if(global.openedcombobox === cb,
+				<!-- when opened, just close to the selected item -->
+				combobox_closelist();
+			  ,
+				if(layer[get(cbname)].scrollarea.loaded,
+					layer[get(cbname)].scrollarea.stopscrolling();
+					calc(offset, cb.selecteditemindex*(cb.autosize_max_h + cb.margin));
+					tween(layer[get(cbname)].marker.y, calc(cb.margin + offset + cb.autosize_max_h/2), 0);
+					tween(layer[get(cbname)].scrollarea.y, calc(-offset), 0, default, layer[get(cbname)].scrollarea.update(); );
+				);
+			);
+		);
+	</action>
+
+
+	<!-- find an item by its caption, the global variable defined in 'returnvariable' will contain the index  -->
+	<action name="combobox_finditem" scope="local" args="cbname, itemcaption, returnvariable">
+		copy(cb, layer[get(cbname)]);
+		copy(item_cnt, cb.item.count);
+		set(calc('global.' + returnvariable), -1);
+		for(def(item_i, integer, 0), item_i LT  item_cnt, inc(item_i),
+			if(cb.item[get(item_i)].caption == itemcaption,
+				copy(calc('global.' + returnvariable), item_i);
+				copy(item_i, item_cnt);
+			);
+		);
+	</action>
+
+
+	<!-- remove all items (to be able to add new ones) -->
+	<action name="combobox_removeitems" scope="local" args="cbname">
+		copy(cb, layer[get(cbname)]);
+		if(global.openedcombobox === cb, combobox_closelist() );
+
+		<!-- remove all item layers -->
+		calc(item_i, cb.item.count - 1);
+		loop(item_i GE 0,
+			removelayer(get(cb.item[get(item_i)].itemlayername));
+			dec(item_i);
+		);
+
+		<!-- reset the item information -->
+		set(cb.item.count, 0);
+		set(cb.autosize_i,0);
+		set(cb.autosize_cnt, 0);
+		set(cb.autosize_max_w, 0);
+		set(cb.autosize_max_h, 0);
+		set(cb.selecteditemindex, 0);
+		set(cb.lastselecteditemindex, 0);
+		if(cb.width == cb.lastautosizedwidth, set(cb.width, null));
+	</action>
+
+
+	<!-- open the combobox list -->
+	<action name="combobox_openlist" scope="local" args="cbname">
+		<!-- if another combobox is already open, close that one first -->
+		if(global.openedcombobox !== null, combobox_closelist() );
+
+		copy(cb, layer[get(cbname)]);
+		copy(global.openedcombobox, cb);
+
+		<!-- find the available screen space above or below the combobox -->
+		calc(cbheight, 2*cb.margin + cb.autosize_max_h);
+		set(lx1, 0);
+		set(ly1, 0);
+		copy(lx2, cb.pixelwidth);
+		copy(ly2, cbheight);
+		layertoscreen(get(cbname), lx1,ly1, lx1,ly1);
+		layertoscreen(get(cbname), lx2,ly2, lx2,ly2);
+		calc(space_above, ly1 - area.pixely);
+		calc(space_below, area.pixelheight - (ly2 - area.pixely));
+
+		<!-- the required space for full opening: -->
+		calc(openheight, cb.margin + cb.autosize_cnt*(cb.margin+cb.autosize_max_h) );
+
+		<!-- vertical centered alignment? -->
+		calc(cb_edge, cb.edge ? cb.edge : cb.align);
+		calc(iscentered, cb_edge == 'left' OR cb_edge == 'center' OR cb_edge == 'right');
+		if(iscentered,
+			calc(openheight_max, space_above + space_below);
+		  ,
+			Math.max(openheight_max, space_above, space_below);
+		);
+
+		<!-- limit the height to the available space (minus some margin) -->
+		Math.min(openheight, calc(openheight_max + cbheight - 20));
+
+		<!-- need vertical offset? (depending on the available space and the align/edge setting) -->
+		set(yoffset, null);
+		calc(top_overflow, -ly1 + area.pixely + openheight/2);
+		calc(bottom_overflow, ly2 - area.pixely + openheight/2 - area.pixelheight);
+		if(cb.parent,
+			<!-- no vertical offset inside other layers, do only a height clipping -->
+			Math.max(max_overflow, top_overflow, bottom_overflow, 0);
+			sub(openheight, max_overflow);
+		  ,
+			if(iscentered,
+				if(openheight GE (area.pixelheight - 20),
+					set(yoffset,0);
+				  ,
+					if(top_overflow GT 0, calc(yoffset, cb.y + top_overflow); );
+					if(bottom_overflow GT 0, calc(yoffset, cb.y - bottom_overflow); );
+				);
+			,
+				indexoftxt(isbottomalign, get(cb_edge), 'bottom');
+				if(space_above GT space_below,
+					if(isbottomalign LT 0, calc(yoffset, cb.y - openheight + cbheight); );
+				  ,
+					if(isbottomalign GE 0, calc(yoffset, cb.y - openheight + cbheight); );
+				);
+			);
+		);
+		if(yoffset != null,
+			copy(cb.ybackup, cb.y);
+			tween(layer[get(cbname)].y, calc(yoffset), get(cb.open_close_speed));
+		);
+
+		<!-- center the opened list at the selected item -->
+		calc(centeritem_y, -1 * (cb.margin + cb.selecteditemindex*(cb.margin+cb.autosize_max_h) + cb.autosize_max_h/2 - openheight/2));
+		clamp(centeritem_y, calc(openheight - cb.scrollarea.height), 0);
+
+		<!-- apply the changes now -->
+		tween(layer[get(cbname)].height, get(openheight), get(cb.open_close_speed));
+		tween(layer[get(cbname)].scrollarea.y, get(centeritem_y), get(cb.open_close_speed), default, layer[get(cbname)].scrollarea.update(); );
+
+		<!-- special html5/flash case:
+			 rotating textfields (the marker symbol here) are not possible in
+			 flash (a flashplayer limitation), so use a rotated symbol instead.
+		-->
+		if(device.html5,
+			tween(layer[get(cbname)].marker.rotate, 90, get(cb.open_close_speed));
+		  ,
+			set(layer[get(cbname)].marker.html, '◀');
+		);
+
+		<!-- enable the scrollarea to allow the user to drag it -->
+		set(cb.scrollarea.enabled, true);
+
+		<!-- install a global onmousedown event to close the list when clicking at the pano -->
+		set(events[combobox_xml_plugin_events].onmousedown, combobox_closelist() );
+	</action>
+
+
+	<!-- close the current open list -->
+	<action name="combobox_closelist" scope="local">
+		if(global.openedcombobox !== null,
+			copy(cb, global.openedcombobox);
+			delete(global.openedcombobox);
+			
+			<!-- clear the global onmousedown event -->
+			set(events[combobox_xml_plugin_events].onmousedown, null);
+
+			<!-- disable the dragging -->
+			set(cb.scrollarea.enabled, false);
+
+			<!-- closing animations -->
+			calc(offset, cb.selecteditemindex*(cb.autosize_max_h + cb.margin));
+			if(cb.ybackup !== null, tween(cb.y, get(cb.ybackup), get(cb.open_close_speed)));
+			layer[get(cb.name)].scrollarea.stopscrolling();
+			tween(layer[get(cb.name)].height, calc(2*cb.margin + cb.autosize_max_h), get(cb.open_close_speed));
+			tween(layer[get(cb.name)].scrollarea.y, calc(-offset), get(cb.open_close_speed), default, layer[get(cb.name)].scrollarea.update(); );
+			tween(layer[get(cb.name)].marker.y, calc(cb.margin + offset + cb.autosize_max_h/2), get(cb.open_close_speed));
+			<!-- special html5/flash case: rotate marker or change symbol -->
+			if(device.html5,
+				tween(layer[get(cb.name)].marker.rotate, 0, get(cb.open_close_speed));
+			  ,
+				set(layer[get(cb.name)].marker.html, '▼');
+			);
+		);
+	</action>
+
+</krpano>

File diff suppressed because it is too large
+ 5 - 0
public/code/resource/plugins/googlemaps.js


File diff suppressed because it is too large
+ 5 - 0
public/code/resource/plugins/gyro2.js


File diff suppressed because it is too large
+ 19 - 0
public/code/resource/plugins/scrollarea.js


File diff suppressed because it is too large
+ 5 - 0
public/code/resource/plugins/soundinterface.js


File diff suppressed because it is too large
+ 5 - 0
public/code/resource/plugins/videoplayer.js


File diff suppressed because it is too large
+ 5 - 0
public/code/resource/plugins/webvr.js


+ 897 - 0
public/code/resource/plugins/webvr.xml

@@ -0,0 +1,897 @@
+<krpano>
+	<!--
+		webvr.xml
+		- krpano 1.19
+	-->
+
+	<!-- load the WebVR plugin and assign it to a 'webvr' variable for easier usage -->
+	<plugin name="WebVR" devices="html5" keep="true"
+	        url="webvr.js"
+	        onloaded="copy(webvr, plugin[WebVR]);"
+	        mousespeed="0.00125"
+	        multireslock="true"
+	        fullscreen_mirroring="true"
+	        mobilevr_support="true"
+	        mobilevr_ipd="63.5"
+	        mobilevr_screensize="auto"
+	        mobilevr_lens_overlap="1.0"
+	        mobilevr_lens_fov="96"
+	        mobilevr_lens_dist="0.6"
+	        mobilevr_lens_dist2="1|0|0|0"
+	        mobilevr_lens_ca="0.0"
+	        mobilevr_lens_vign="100"
+	        mobilevr_wakelock="true"
+	        mobilevr_sensor_mode="3"
+	        mobilevr_autocalibration="false"
+	        mobilevr_touch_support="true"
+	        mobilevr_fake_support="false"
+	        vr_cursor="hotspot[vr_cursor]"
+	        vr_cursor_enabled="true"
+	        vr_cursor_onover="if(handcursor, tween(hotspot[vr_cursor].scale,0.4,0.1); vr_auto_click(get(vr_timeout)); );"
+	        vr_cursor_onout="tween(hotspot[vr_cursor].scale,0.3,0.1);"
+	        onavailable="webvr_onavailable();"
+	        onunavailable=""
+	        onunknowndevice="webvr_onunknowndevice();"
+	        onentervr="webvr_onentervr();"
+	        onexitvr="webvr_onexitvr();"
+	        />
+
+	
+	<!-- a custom xml data structure with the supported VR headsets -->
+	<vrheadsets>
+		<headset name="cb1" caption="Cardboard A"   overlap="1.10" fov="96.0"  dist="1.00" dist2="1|0|0|0" ca="0.000" vig="100" />
+		<headset name="cb2" caption="Cardboard B"   overlap="1.00" fov="96.0"  dist="0.60" dist2="1|0|0|0" ca="0.000" vig="100" />
+		<headset name="gvr" caption="GearVR"        overlap="1.00" fov="112.0" dist="0.95" dist2="1|0|0|0" ca="0.090" vig="100" />
+		<headset name="hom" caption="HOMiDO"        overlap="1.00" fov="101.0" dist="1.10" dist2="1|0|0|0" ca="0.075" vig="100" />
+		<headset name="one" caption="VR ONE"        overlap="1.00" fov="109.9" dist="0.00" dist2="1.139|0.093|0.018|0.207" ca="0.090" vig="35" />
+		<headset name="ccr" caption="ColorCross VR" overlap="1.00" fov="70.0"  dist="0.65" dist2="1|0|0|0" ca="0.000" vig="100" />
+		<headset name="nod" caption="No Distortion" overlap="1.00" fov="96.0"  dist="0.00" dist2="1|0|0|0" ca="0.000" vig="100" />
+	</vrheadsets>
+
+
+	<!-- the VR cursor hotspot -->
+	<hotspot name="vr_cursor" keep="true"
+	         url="webvr_cursor_80x80_17f.png"
+	         visible="false"
+	         enabled="false"
+	         distorted="true"
+	         crop="0|0|80|80"
+	         scale="0.3"
+	         depth="1000"
+	         />
+
+
+	<!-- vr_auto_click() - call this action in the onover event of a
+	     hotspot to trigger automatically a click after some time.  -->
+	<action name="vr_auto_click">
+		if(webvr.isenabled,
+			if(%1 != null, set(vr_aclk_timeout, %1), set(vr_aclk_timeout, 2000));
+			copy(vr_aclk_t1, timertick);
+			set(vr_aclk_waiting, true);
+			copy(vr_aclk_hotspot, name);
+			set(hotspot[vr_cursor].crop,'0|0|80|80');
+
+			asyncloop(vr_aclk_waiting AND vr_aclk_hotspot == name,
+				sub(dt, timertick,vr_aclk_t1);
+
+				if(!hovering,
+					set(vr_aclk_waiting, false);
+					set(hotspot[vr_cursor].crop,'0|0|80|80');
+				  ,
+					div(f, dt, vr_aclk_timeout);
+					mul(f, 16);
+					roundval(f);
+					Math.min(f, 16);
+					mul(f, 80);
+
+					txtadd(hotspot[vr_cursor].crop,get(f),'|0|80|80');
+
+					<!-- wait another 100ms delay after finishing the animation before doing the click -->
+					sub(dt, 100);
+					if(dt GT vr_aclk_timeout,
+						set(vr_aclk_waiting,false);
+						set(hotspot[vr_cursor].crop,'0|0|80|80');
+						<!-- call onclick -->
+						onclick();
+					  );
+				  );
+				);
+		  );
+	</action>
+
+
+	<!-- by pressing SPACE the Oculus Rift could be re-centered -->
+	<events name="webvr_events" devices="html5" keep="true"
+	        onkeydown="if(webvr AND webvr.isenabled AND keycode==32, webvr.resetSensor() );"
+	        onmousedown="if(webvr AND webvr.isenabled, webvr_showbuttons() );"
+	        />
+
+
+	<!-- when WebVR support is available show an EnterVR button -->
+	<action name="webvr_onavailable">
+		webvr.loadsettings();
+		delayedcall(0.5, tween(layer[webvr_enterbutton].alpha,1.0); );
+	</action>
+	
+	
+	<action name="webvr_onunknowndevice">
+		if(webvr.isfake AND device.desktop AND webvr.havesettings == false,
+			<!-- set the 'no distortion' headset for fake desktop usage -->
+			set(webvr.mobilevr_lens_overlap, 1.0);
+			set(webvr.mobilevr_lens_fov, 96.0);
+			set(webvr.mobilevr_lens_dist, 0.0);
+			set(webvr.mobilevr_lens_dist2, '1|0|0|0');
+			set(webvr.mobilevr_lens_ca, 0.0);
+			set(webvr.mobilevr_lens_vign, 100);
+		  ,
+			set(ask_user_for_screensize,true);
+		  );
+	</action>
+
+
+	<action name="webvr_onentervr">
+		tween(layer[webvr_enterbutton].alpha,0,0);
+
+		webvr_showbuttons();
+		webvr_hide_all_non_vr_layers();
+
+		<!-- when the screen size is unknown an no custom size is set, open the setup screen on entering the VR mode -->
+		if(webvr.ismobilevr == true AND !webvr.isfake AND ask_user_for_screensize == true AND webvr.mobilevr_screensize == 'auto',
+			set(ask_user_for_screensize, false);
+			vr_setup();
+		  );
+		if(webvr.isfake,
+			webvr_show_fakemode_info(true);
+		  );
+	</action>
+
+
+	<action name="webvr_onexitvr">
+		stopdelayedcall(vr_button_fadeout);
+
+		tween(layer[webvr_enterbutton].alpha,1);
+		tween(layer[webvr_exitbutton].alpha,0);
+		tween(layer[webvr_setupbutton].alpha,0);
+		
+		webvr_show_fakemode_info(false);
+
+		webvr_restore_layers();
+	</action>
+
+
+	<action name="webvr_hide_all_non_vr_layers">
+		for(set(i,0), i LT layer.count, inc(i),
+			copy(lr, layer[get(i)]);
+			if(lr.vr !== true,
+				copy(lr.vr_backup_visible, lr.visible);
+				set(lr.visible, false);
+			  );
+		  );
+	</action>
+
+	<action name="webvr_restore_layers">
+		for(set(i,0), i LT layer.count, inc(i),
+			copy(lr, layer[get(i)]);
+			if(lr.vr_backup_visible,
+				copy(lr.visible, lr.vr_backup_visible);
+				delete(lr.vr_backup_visible);
+			  );
+		  );
+	</action>
+	
+	<action name="webvr_show_fakemode_info">
+		if('%1' == 'true',
+			addlayer(webvr_fakemode_info);
+			set(layer[webvr_fakemode_info].url, '%SWFPATH%/plugins/textfield.swf');
+			set(layer[webvr_fakemode_info].keep, true);
+			set(layer[webvr_fakemode_info].align, 'bottom');
+			set(layer[webvr_fakemode_info].y, 80);
+			set(layer[webvr_fakemode_info].background, false);
+			set(layer[webvr_fakemode_info].css, 'color:#FFFFFF;text-align:center;');
+			set(layer[webvr_fakemode_info].html, '[i][u]Simulated WebVR Mode![/u][/i][br]For real WebVR with headset tracking, either use a [a href="http://webvr.info" target="_blank" style="color:#FFFFFF;"]WebVR-API-capable[/a] desktop browser or a mobile device and a VR headset.');
+		  ,
+			removelayer(webvr_fakemode_info);
+		  );
+	</action>
+	
+	
+	<!-- ensure the same scaling on mobiles (regardless if mobilescale is 0.5 or 1.0) -->
+	<krpano webvr_setup_scale="calc:(1.0 + 1.0*(device.mobile AND stagescale LT 1.0)) / (1.0 + 1.0*device.mobile)"
+	        webvr_button_scale.normal="1.0"
+	        webvr_button_scale.mobile="1.6"
+	        />
+
+	
+	<!-- the EnterVR/ExitVR and SetupVR buttons -->
+	<style name="webvr_button_style"
+	       url="%SWFPATH%/plugins/textfield.swf"
+	       backgroundcolor="0x000000"
+	       backgroundalpha="0.5"
+	       roundedge="calc:9*webvr_setup_scale*webvr_button_scale"
+	       css="calc:'color:#FFFFFF;font-size:' + 20*webvr_setup_scale*webvr_button_scale + 'px;'"
+	       padding="calc:6*webvr_setup_scale*webvr_button_scale + ' ' + 10*webvr_setup_scale*webvr_button_scale"
+	       />
+	
+	<layer name="webvr_enterbutton" keep="true" vr="true"
+	       style="webvr_button_style"
+	       html="Enter VR"
+	       align="top" y="24"
+	       autoalpha="true" alpha="0.0"
+	       onclick="webvr.enterVR();"
+	       />
+
+	<layer name="webvr_exitbutton" keep="true" vr="true"
+	       style="webvr_button_style"
+	       html="Exit VR"
+	       align="top" y="24"
+	       autoalpha="true" alpha="0.0"
+	       onclick="webvr.exitVR();"
+	       />
+
+	<layer name="webvr_setupbutton" keep="true" vr="true"
+	       style="webvr_button_style"
+	       html="VR Setup"
+	       align="bottom" y="24"
+	       autoalpha="true" alpha="0.0"
+	       onclick="vr_setup()"
+	       />
+
+
+	<action name="webvr_showbuttons">
+		stopdelayedcall(vr_button_fadeout);
+		if(webvr.ismobilevr,
+			tween(layer[webvr_exitbutton].alpha|layer[webvr_setupbutton].alpha, 1.0|1.0, 0.25);
+			delayedcall(vr_button_fadeout, 3.0, tween(layer[webvr_exitbutton].alpha|layer[webvr_setupbutton].alpha, 0.0|0.0, 1.0); );
+		  ,
+			tween(layer[webvr_exitbutton].alpha, 1.0, 0.25);
+			delayedcall(vr_button_fadeout, 3.0, tween(layer[webvr_exitbutton].alpha, 0.0, 1.0); );
+		  );
+	</action>
+
+
+
+	<!--
+		VR Setup
+	-->
+
+	<action name="vr_setup">
+		<!-- disable cursor -->
+		set(webvr.vr_cursor_enabled, false);
+		
+		<!-- hide VR buttons -->
+		tween(layer[webvr_exitbutton].alpha,0);
+		tween(layer[webvr_setupbutton].alpha,0);
+		
+		<!-- create background layer -->
+		addlayer(vr_setup_bg);
+		set(layer[vr_setup_bg].type, container);
+		set(layer[vr_setup_bg].bgcolor, 0x000000);
+		set(layer[vr_setup_bg].bgalpha, 0.5);
+		set(layer[vr_setup_bg].bgcapture, true);
+		set(layer[vr_setup_bg].handcursor, false);
+		set(layer[vr_setup_bg].align, lefttop);
+		set(layer[vr_setup_bg].width, 100%);
+		set(layer[vr_setup_bg].height, 100%);
+		set(layer[vr_setup_bg].zorder, 99999);
+		
+		<!-- get and prepare device infos and settings -->
+		copy(i_screensize, webvr.mobilevr_screensize);
+		if(i_screensize == 'auto', copy(i_screensize, webvr.devicesize));
+		if(i_screensize LE 0, set(i_screensize, 5.0));
+		roundval(i_screensize, 1);
+		txtadd(i_screensize, ' inch');
+
+		copy(i_ipd, webvr.mobilevr_ipd);
+		roundval(i_ipd, 1);
+		txtadd(i_ipd, ' mm');
+
+		copy(i_fov, webvr.mobilevr_lens_fov);
+		roundval(i_fov, 1);
+
+		copy(i_dist, webvr.mobilevr_lens_dist);
+		roundval(i_dist, 2);
+		
+		copy(i_dist2, webvr.mobilevr_lens_dist2);
+		txtsplit(i_dist2, '|', i_dist2_k1, i_dist2_k2, i_dist2_k3, i_dist2_k4);
+		mul(i_dist2_k1,1);
+		mul(i_dist2_k2,10);
+		mul(i_dist2_k3,10);
+		mul(i_dist2_k4,10);
+		roundval(i_dist2_k1,2);
+		roundval(i_dist2_k2,2);
+		roundval(i_dist2_k3,2);
+		roundval(i_dist2_k4,2);
+
+		copy(i_vig, webvr.mobilevr_lens_vign);
+		roundval(i_vig, 0);
+		
+		copy(i_overlap, webvr.mobilevr_lens_overlap);
+		roundval(i_overlap, 2);
+		
+		copy(i_ca, webvr.mobilevr_lens_ca);
+		roundval(i_ca, 3);
+
+		set(i_headset, 'Custom');
+		for(set(i,0), i LT vrheadsets.headset.count, inc(i),
+			copy(hs, vrheadsets.headset[get(i)]);
+			if(i_overlap == hs.overlap AND i_fov == hs.fov AND i_dist == hs.dist AND i_dist2 == hs.dist2 AND i_ca == hs.ca AND i_vig == hs.vig , copy(i_headset, hs.caption));
+		   );
+
+		<!-- when the screen size is unknown, mark it red -->
+		set(known_size, true);
+		set(sizcol, #FFFFFF);
+		copy(i_devicename, webvr.devicename);
+		if(i_devicename == 'Unknown',
+			if(webvr.mobilevr_screensize == 'auto',
+				set(sizcol, #AA0000);
+				set(known_size, false);
+			  ,
+				set(i_devicename, 'Custom');
+			  );
+		  );
+
+		
+		<!-- create layer for the main menu -->
+		addlayer(vr_setup_m1);
+		set(layer[vr_setup_m1].type, container);
+		set(layer[vr_setup_m1].parent, vr_setup_bg);
+		set(layer[vr_setup_m1].align, lefttop);
+		set(layer[vr_setup_m1].width, 100%);
+		set(layer[vr_setup_m1].height, 100%);
+		
+		<!-- create layer for the headset customization menu -->
+		addlayer(vr_setup_m3);
+		set(layer[vr_setup_m3].type, container);
+		set(layer[vr_setup_m3].parent, vr_setup_bg);
+		set(layer[vr_setup_m3].align, lefttop);
+		set(layer[vr_setup_m3].width, 100%);
+		set(layer[vr_setup_m3].height, 100%);
+		set(layer[vr_setup_m3].visible, false);
+		
+		<!-- create layer for the calibration menu -->
+		addlayer(vr_setup_m2);
+		set(layer[vr_setup_m2].type, container);
+		set(layer[vr_setup_m2].parent, vr_setup_bg);
+		set(layer[vr_setup_m2].align, lefttop);
+		set(layer[vr_setup_m2].width, 100%);
+		set(layer[vr_setup_m2].height, 100%);
+		set(layer[vr_setup_m2].visible, false);
+		
+		<!-- create the text elements -->
+		set(vr_setup_text_parent, 'vr_setup_m1');
+		vr_setup_createtext(vr_setup_title, 'MOBILE VR SETUP',       center, center, 0, -225, #FFFFFF,     false);
+
+		vr_setup_createtext(vr_setup_dvn1, 'Device:',         center, right,  0, -145, #FFFFFF,     true, vr_setup_select('screen') );
+		vr_setup_createtext(vr_setup_dvn2, get(i_devicename), center, left,   0, -145, get(sizcol), true, vr_setup_select('screen') );
+		vr_setup_createtext(vr_setup_siz1, 'Screensize:',     center, right,  0, -105, #FFFFFF,     true, vr_setup_select('screen') );
+		vr_setup_createtext(vr_setup_siz2, get(i_screensize), center, left,   0, -105, get(sizcol), true, vr_setup_select('screen') );
+
+		vr_setup_createtext(vr_setup_ipd1, 'IPD:',            center, right,  0,  -35, #FFFFFF,     true, vr_setup_select('ipd') );
+		vr_setup_createtext(vr_setup_ipd2, get(i_ipd),        center, left,   0,  -35, #FFFFFF,     true, vr_setup_select('ipd') );
+
+		vr_setup_createtext(vr_setup_hmd1, 'VR Headset:',     center, right,  0,  +35, #FFFFFF,     true, vr_setup_select('headset') );
+		vr_setup_createtext(vr_setup_hmd2, get(i_headset),    center, left,   0,  +35, #FFFFFF,     true, vr_setup_select('headset') );
+		
+		vr_setup_createtext(vr_setup_hmd3, 'Customize',       center, center, 0,  +75, #FFFFFF,     true, set(background,true), set(background,false), vr_setup_customize_headset() );
+
+		
+
+		if(webvr.iswebvr == false,
+			vr_setup_createtext(vr_setup_cal, 'Calibrate Gyroscope',   center, center,    0, +145, #FFFFFF,     true, set(background,true), set(background,false), vr_setup_calibration() );
+		  );
+
+		vr_setup_createtext(vr_setup_sav, 'SAVE',          center, center, -200, +225, #FFFFFF,     true, set(background,true), set(background,false), vr_setup_save() );
+		vr_setup_createtext(vr_setup_rst, 'RESET',         center, center,    0, +225, #FFFFFF,     true, set(background,true), set(background,false), vr_setup_reset() );
+		vr_setup_createtext(vr_setup_cls, 'CLOSE',         center, center, +200, +225, #FFFFFF,     true, set(background,true), set(background,false), vr_setup_close() );
+		
+		<!-- and the adjusting buttons -->
+		vr_setup_createbutton(vr_setup_btn1, '&#60;', left,  left,  5%, -35, #FFFFFF, true, null);
+		vr_setup_createbutton(vr_setup_btn2, '&#62;', right, right, 5%, -35, #FFFFFF, true, null);
+		
+		
+		<!-- create the customize_headset text elements -->
+		set(vr_setup_text_parent, 'vr_setup_m3');
+		vr_setup_createtext(vr_setup_m31, 'VR HEADSET', center, center, 0, -225, #FFFFFF, false);
+		
+		vr_setup_createtext(vr_setup_fov1,  'FOV:',           center, right,  0,  -80,  #FFFFFF,    true, vr_setup_select('fov') );
+		vr_setup_createtext(vr_setup_fov2, get(i_fov),        center, left,   0,  -80,  #FFFFFF,    true, vr_setup_select('fov') );
+		vr_setup_createtext(vr_setup_dst1, 'Distortion:',     center, right,  0,  -32,  #FFFFFF,    true, vr_setup_select('dist') );
+		vr_setup_createtext(vr_setup_dst2, get(i_dist),       center, left,   0,  -32,  #FFFFFF,    true, vr_setup_select('dist') );
+		vr_setup_createtext(vr_setup_d2tx, 'Dist2:',          center, right,  0,  +16,  #FFFFFF,    true, vr_setup_select('dist2k1') );
+		vr_setup_createtext(vr_setup_d2k1, get(i_dist2_k1),   center, left,   0,  +16,  #FFFFFF,    true, vr_setup_select('dist2k1') );
+		vr_setup_createtext(vr_setup_d2k2, get(i_dist2_k2),   center, left, +100, +16,  #FFFFFF,    true, vr_setup_select('dist2k2') );
+		vr_setup_createtext(vr_setup_d2k3, get(i_dist2_k3),   center, left, +200, +16,  #FFFFFF,    true, vr_setup_select('dist2k3') );
+		vr_setup_createtext(vr_setup_d2k4, get(i_dist2_k4),   center, left, +300, +16,  #FFFFFF,    true, vr_setup_select('dist2k4') );
+		
+		
+		vr_setup_createtext(vr_setup_cac1, 'CA Corr:',        center, right,  0,  +64,  #FFFFFF,    true, vr_setup_select('ca') );
+		vr_setup_createtext(vr_setup_cac2, get(i_ca),         center, left,   0,  +64,  #FFFFFF,    true, vr_setup_select('ca') );
+		vr_setup_createtext(vr_setup_vig1, 'Vignette:',       center, right,  0, +112,  #FFFFFF,    true, vr_setup_select('vignette') );
+		vr_setup_createtext(vr_setup_vig2, get(i_vig),        center, left,   0, +112,  #FFFFFF,    true, vr_setup_select('vignette') );
+		vr_setup_createtext(vr_setup_olp1, 'Overlap:',        center, right,  0, +160,  #FFFFFF,    true, vr_setup_select('overlap') );
+		vr_setup_createtext(vr_setup_olp2, get(i_overlap),    center, left,   0, +160,  #FFFFFF,    true, vr_setup_select('overlap') );
+				
+		vr_setup_createtext(vr_setup_m35, 'CLOSE',       center, center, 0, +225, #FFFFFF, true, set(background,true), set(background,false), vr_setup_close_sub_menus() );
+		
+		
+		<!-- create the calibration text elements -->
+		set(vr_setup_text_parent, 'vr_setup_m2');
+		vr_setup_createtext(vr_setup_cb1, 'GYROSCOPE', center, center, 0, -225, #FFFFFF, false);
+		vr_setup_createtext(vr_setup_cb2, 'Place the device on a flat and[br]stable surface and tab calibrate[br]to correct a gyroscope drifting.', center, center, 0, -95, #FFFFFF, false, vr_setup_select('screen') );
+		vr_setup_createtext(vr_setup_cb3, 'CALIBRATE',   center, center, 0,  +55, #FFFFFF, true, set(background,true), set(background,false), vr_setup_do_calibration() );
+		vr_setup_createtext(vr_setup_cb4, 'RESET',       center, center, 0, +125, #FFFFFF, true, set(background,true), set(background,false), webvr.resetcalibration() );
+		vr_setup_createtext(vr_setup_cb5, 'CLOSE',       center, center, 0, +225, #FFFFFF, true, set(background,true), set(background,false), vr_setup_close_sub_menus() );
+		
+		vr_setup_createtext(vr_setup_cb6, 'Calibrating...',      bottom, center, 0, 40, #FFFFFF, false, null );
+		vr_setup_createtext(vr_setup_cb7, 'Calibration okay.',   bottom, center, 0, 40, #FFFFFF, false, null );
+		vr_setup_createtext(vr_setup_cb8, 'Calibration failed!', bottom, center, 0, 40, #FFFFFF, false, null );
+		set(layer[vr_setup_cb6].autoalpha, true);
+		set(layer[vr_setup_cb7].autoalpha, true);
+		set(layer[vr_setup_cb8].autoalpha, true);
+		set(layer[vr_setup_cb6].alpha, 0.0);
+		set(layer[vr_setup_cb7].alpha, 0.0);
+		set(layer[vr_setup_cb8].alpha, 0.0);
+		
+		
+		<!-- pre-select the screen size for adjusting when it is unknown, otherwise the IPD -->
+		if(known_size == false,
+			vr_setup_select('screen', true);
+		  ,
+			vr_setup_select('ipd', true);
+		  );
+	</action>
+
+
+	<action name="vr_setup_createtext">
+		<!--
+			%1 = name
+			%2 = text
+			%3 = align
+			%4 = edge
+			%5 = x
+			%6 = y
+			%7 = color
+			%8 = enabled
+			%9 = ondown
+			%10 = onup
+			%11 = onclick
+		-->
+		addlayer(%1);
+		set(layer[%1].parent, get(vr_setup_text_parent));
+		set(layer[%1].url, '%SWFPATH%/plugins/textfield.swf');
+		set(layer[%1].css, calc('text-align:%3;color:%7;font-size:'+40*webvr_setup_scale+'px;font-weight:bold;'));
+		set(layer[%1].padding, calc(0 + ' ' + 8*webvr_setup_scale));
+		set(layer[%1].roundedge, calc(8*webvr_setup_scale));
+		set(layer[%1].background, false);
+		set(layer[%1].backgroundcolor, 0xFFFFFF);
+		set(layer[%1].backgroundalpha, 0.25);
+		set(layer[%1].align, %3);
+		set(layer[%1].edge, %4);
+		set(layer[%1].x, calc(%5 * webvr_setup_scale));
+		set(layer[%1].y, calc(%6 * webvr_setup_scale));
+		set(layer[%1].html, %2);
+		set(layer[%1].enabled, %8);
+		set(layer[%1].ondown, %9);
+		set(layer[%1].onup, %10);
+		set(layer[%1].onclick, %11);
+	</action>
+
+
+	<action name="vr_setup_createbutton">
+		vr_setup_createtext(%1,%2,%3,%4,%5,%6,%7,%8,%9);
+		set(layer[%1].css, calc('vertical-align:middle;text-align:center;color:%7;font-size:'+60*webvr_setup_scale+'px;font-weight:bold;'));
+		set(layer[%1].background, true);
+		set(layer[%1].padding, 0);
+		set(layer[%1].roundedge, calc(40 * webvr_setup_scale));
+		set(layer[%1].width, calc(70 * webvr_setup_scale));
+		set(layer[%1].height, calc(70 * webvr_setup_scale));
+		set(layer[%1].vcenter, true);
+	</action>
+
+
+	<action name="vr_setup_reset">
+		<!-- reset to the defaults -->
+		set(webvr.mobilevr_screensize, 'auto');
+		copy(i_screensize, webvr.devicesize);
+		if(i_screensize LE 0, set(i_screensize, 5.0); );
+		roundval(i_screensize, 1);
+		set(layer[vr_setup_dvn2].html, get(webvr.devicename));
+		txtadd(layer[vr_setup_siz2].html, get(i_screensize), ' inch');
+
+		set(webvr.mobilevr_ipd, 63.5);
+		copy(i_ipd, webvr.mobilevr_ipd);
+		roundval(i_ipd, 1);
+		txtadd(layer[vr_setup_ipd2].html, get(i_ipd), ' mm');
+
+		<!-- set fake custom lens settings and call 'next' headset to switch to the default 'Cardboard' settings -->
+		set(webvr.mobilevr_lens_fov, 100);
+		set(webvr.mobilevr_lens_dist, 0.5);
+		set(webvr.mobilevr_lens_dist2, '1|0|0|0');
+		set(webvr.mobilevr_lens_vign, 100);
+		set(webvr.mobilevr_lens_overlap, 1.0);
+		set(webvr.mobilevr_lens_ca, 0.0);
+		
+		if(webvr.isfake AND device.desktop,
+			<!-- select 'no distortion' headset for fake desktop usage -->
+			vr_setup_change_headset(-1);
+		  ,
+			<!-- select 'Cardboard A' headset for Mobile-VR usage -->
+			vr_setup_change_headset(+1);	
+		  );
+
+		vr_setup_select(get(selected_var));
+	</action>
+
+
+	<action name="vr_setup_close">
+		<!-- 2. parameter == true => remove children elements too -->
+		removelayer(vr_setup_bg, true);
+		
+		<!-- enable cursor -->
+		set(webvr.vr_cursor_enabled, true);
+	</action>
+
+
+	<action name="vr_setup_save">
+		webvr.saveSettings();
+		vr_setup_close();
+	</action>
+	
+	
+	<action name="vr_setup_customize_headset">
+		set(layer[vr_setup_bg].bgalpha, 0.1);
+		
+		set(layer[vr_setup_m1].visible,false);
+		set(layer[vr_setup_m2].visible,false);
+		set(layer[vr_setup_m3].visible,true);
+		
+		set(layer[vr_setup_hmd1].parent, vr_setup_m3);
+		set(layer[vr_setup_hmd2].parent, vr_setup_m3);
+		set(layer[vr_setup_btn1].parent, vr_setup_m3);
+		set(layer[vr_setup_btn2].parent, vr_setup_m3);
+		
+		set(layer[vr_setup_hmd1].y, calc(-145 * webvr_setup_scale));
+		set(layer[vr_setup_hmd2].y, calc(-145 * webvr_setup_scale));
+		
+		copy(old_selection, selected_var);
+		vr_setup_select('headset');
+	</action>
+	
+	
+
+	<action name="vr_setup_calibration">
+		set(layer[vr_setup_m1].visible,false);
+		set(layer[vr_setup_m2].visible,true);
+	</action>
+	
+	<action name="vr_setup_close_sub_menus">
+		set(layer[vr_setup_bg].bgalpha, 0.5);
+		
+		set(layer[vr_setup_m1].visible,true);
+		set(layer[vr_setup_m2].visible,false);
+		set(layer[vr_setup_m3].visible,false);
+		
+		set(layer[vr_setup_hmd1].parent, vr_setup_m1);
+		set(layer[vr_setup_hmd2].parent, vr_setup_m1);
+		set(layer[vr_setup_btn1].parent, vr_setup_m1);
+		set(layer[vr_setup_btn2].parent, vr_setup_m1);
+		
+		set(layer[vr_setup_hmd1].y, calc(+35 * webvr_setup_scale));
+		set(layer[vr_setup_hmd2].y, calc(+35 * webvr_setup_scale));
+		
+		if(old_selection,
+			vr_setup_select(get(old_selection));
+			delete(old_selection);
+		  );
+	</action>
+	
+	<action name="vr_setup_do_calibration">
+		if(!webvr.isfake,
+			tween(layer[vr_setup_cb6].alpha, 1.0, 0.1);
+			tween(layer[vr_setup_cb7].alpha, 0.0, 0.1);
+			tween(layer[vr_setup_cb8].alpha, 0.0, 0.1);
+			webvr.calibrate(
+				tween(layer[vr_setup_cb6].alpha, 0.0, 0.1);
+				tween(layer[vr_setup_cb7].alpha, 1.0, 0.1);
+				delayedcall(2.0, tween(layer[vr_setup_cb7].alpha, 0.0, 0.25) );
+			  ,
+				tween(layer[vr_setup_cb6].alpha, 0.0, 0.1);
+				tween(layer[vr_setup_cb8].alpha, 1.0, 0.1);
+				delayedcall(2.0, tween(layer[vr_setup_cb8].alpha, 0.0, 0.25) );
+			  );
+		  );
+	</action>
+
+	<action name="vr_setup_update_dist2">
+		txtadd(webvr.mobilevr_lens_dist2, get(i_dist2_k1), '|', calc(i_dist2_k2/10.0), '|', calc(i_dist2_k3/10.0), '|', calc(i_dist2_k4/10.0));
+		vr_setup_change_headset(0);
+	</action>
+
+	<action name="vr_setup_select">
+		<!-- select a setting for adjusting -->
+		set(layer[vr_setup_siz2].background, false);
+		set(layer[vr_setup_ipd2].background, false);
+		set(layer[vr_setup_hmd2].background, false);
+		set(layer[vr_setup_fov2].background, false);
+		set(layer[vr_setup_dst2].background, false);
+		set(layer[vr_setup_d2k1].background, false);
+		set(layer[vr_setup_d2k2].background, false);
+		set(layer[vr_setup_d2k3].background, false);
+		set(layer[vr_setup_d2k4].background, false);
+		set(layer[vr_setup_vig2].background, false);
+		set(layer[vr_setup_cac2].background, false);
+		set(layer[vr_setup_olp2].background, false);
+
+		set(selected_setting, null);
+		delete(selected_var_value);
+
+		set(layer[vr_setup_btn1].ondown, vr_setup_change_ondown(-1) );
+		set(layer[vr_setup_btn2].ondown, vr_setup_change_ondown(+1) );
+		set(selected_var_callback, null);
+
+		set(selected_var, %1);
+
+		if(selected_var == 'screen',
+			set(selected_setting,      vr_setup_siz2);
+			set(selected_var_name,     'webvr.mobilevr_screensize');
+			set(selected_var_postfix,  ' inch');
+			copy(selected_var_value,   get(selected_var_name));
+			if(selected_var_value == 'auto', copy(selected_var_value, webvr.devicesize));
+			if(selected_var_value LE 0, set(selected_var_value, 5.0));
+			set(selected_var_step,     0.1);
+			set(selected_var_min,      4);
+			set(selected_var_max,      10);
+			set(selected_var_round,    1);
+			set(selected_var_callback, vr_setup_change_screen() );
+		  );
+
+		if(selected_var == 'ipd',
+			set(selected_setting,      vr_setup_ipd2);
+			set(selected_var_name,     'webvr.mobilevr_ipd');
+			set(selected_var_postfix,  ' mm');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.1);
+			set(selected_var_min,      40);
+			set(selected_var_max,      80);
+			set(selected_var_round,    1);
+		  );
+
+		if(selected_var == 'headset',
+			set(selected_setting,      vr_setup_hmd2);
+			set(layer[vr_setup_btn1].ondown, vr_setup_change_headset(-1) );
+			set(layer[vr_setup_btn2].ondown, vr_setup_change_headset(+1) );
+		  );
+
+		if(selected_var == 'fov',
+			set(selected_setting,      vr_setup_fov2);
+			set(selected_var_name,     'webvr.mobilevr_lens_fov');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.1);
+			set(selected_var_min,      40);
+			set(selected_var_max,      179);
+			set(selected_var_round,    1);
+			set(selected_var_callback, vr_setup_change_headset(0) );
+		  );
+
+		if(selected_var == 'dist',
+			set(selected_setting,      vr_setup_dst2);
+			set(selected_var_name,     'webvr.mobilevr_lens_dist');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.01);
+			set(selected_var_min,      0);
+			set(selected_var_max,      5);
+			set(selected_var_round,    2);
+			set(selected_var_callback, vr_setup_change_headset(0) );
+		  );
+		
+		if(selected_var == 'dist2k1',
+			set(selected_setting,      vr_setup_d2k1);
+			set(selected_var_name,     'i_dist2_k1');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.01);
+			set(selected_var_min,      -9);
+			set(selected_var_max,      +9);
+			set(selected_var_round,    2);
+			set(selected_var_callback, vr_setup_update_dist2() );
+		  );
+		
+		if(selected_var == 'dist2k2',
+			set(selected_setting,      vr_setup_d2k2);
+			set(selected_var_name,     'i_dist2_k2');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.01);
+			set(selected_var_min,      -9);
+			set(selected_var_max,      +9);
+			set(selected_var_round,    2);
+			set(selected_var_callback, vr_setup_update_dist2() );
+		  );
+		
+		if(selected_var == 'dist2k3',
+			set(selected_setting,      vr_setup_d2k3);
+			set(selected_var_name,     'i_dist2_k3');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.01);
+			set(selected_var_min,      -9);
+			set(selected_var_max,      +9);
+			set(selected_var_round,    2);
+			set(selected_var_callback, vr_setup_update_dist2() );
+		  );
+
+		if(selected_var == 'dist2k4',
+			set(selected_setting,      vr_setup_d2k4);
+			set(selected_var_name,     'i_dist2_k4');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.01);
+			set(selected_var_min,      -9);
+			set(selected_var_max,      +9);
+			set(selected_var_round,    2);
+			set(selected_var_callback, vr_setup_update_dist2() );
+		  );
+
+		if(selected_var == 'vignette',
+			set(selected_setting,      vr_setup_vig2);
+			set(selected_var_name,     'webvr.mobilevr_lens_vign');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     1);
+			set(selected_var_min,      10);
+			set(selected_var_max,      200);
+			set(selected_var_round,    0);
+			set(selected_var_callback, vr_setup_change_headset(0) );
+		  );
+
+		if(selected_var == 'ca',
+			set(selected_setting,      vr_setup_cac2);
+			set(selected_var_name,     'webvr.mobilevr_lens_ca');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.01);
+			set(selected_var_min,      -1.0);
+			set(selected_var_max,      +1.0);
+			set(selected_var_round,    2);
+			set(selected_var_callback, vr_setup_change_headset(0) );
+		  );
+		  
+		if(selected_var == 'overlap',
+			set(selected_setting,      vr_setup_olp2);
+			set(selected_var_name,     'webvr.mobilevr_lens_overlap');
+			set(selected_var_postfix,  '');
+			copy(selected_var_value,   get(selected_var_name));
+			set(selected_var_step,     0.01);
+			set(selected_var_min,      0.5);
+			set(selected_var_max,      2.0);
+			set(selected_var_round,    2);
+			set(selected_var_callback, vr_setup_change_headset(0) );
+		  );
+
+		if(selected_setting != null,
+			set(layer[get(selected_setting)].background, true);
+			if(%2 == true,
+				set(layer[vr_setup_btn1].y, get(layer[get(selected_setting)].y));
+				set(layer[vr_setup_btn2].y, get(layer[get(selected_setting)].y));
+			  ,
+				tween(layer[vr_setup_btn1].y, get(layer[get(selected_setting)].y));
+				tween(layer[vr_setup_btn2].y, get(layer[get(selected_setting)].y));
+			  );
+		  );
+	</action>
+
+
+	<action name="vr_setup_change_screen">
+		set(layer[vr_setup_dvn2].html, 'Custom');
+		set(layer[vr_setup_dvn2].css, calc('color:#FFFFFF;font-size:'+40*webvr_setup_scale+'px;font-weight:bold;'));
+		set(layer[vr_setup_siz2].css, calc('color:#FFFFFF;font-size:'+40*webvr_setup_scale+'px;font-weight:bold;'));
+	</action>
+
+
+	<action name="vr_setup_change_ondown">
+		copy(t0,timertick);
+		set(t1,0);
+		asyncloop(pressed,
+			copy(t2,timertick);
+			sub(dt,t2,t1);
+			if(dt GT 100,
+				copy(t1,t2);
+				sub(dt,t1,t0);
+				div(dt,1000);
+				Math.max(dt,1);
+				mul(dt,%1);
+				vr_setup_adjust(get(dt));
+			  );
+		  );
+	</action>
+
+
+	<action name="vr_setup_adjust">
+		if(selected_setting != null,
+			mul(change, selected_var_step, %1);
+			add(selected_var_value, change);
+			Math.max(selected_var_value, selected_var_min);
+			Math.min(selected_var_value, selected_var_max);
+			roundval(selected_var_value, get(selected_var_round));
+			tween(get(selected_var_name), get(selected_var_value), 0.1);
+			txtadd(layer[get(selected_setting)].html, get(selected_var_value), get(selected_var_postfix));
+			if(selected_var_callback != null, selected_var_callback());
+		  );
+	</action>
+
+
+	<action name="vr_setup_change_headset">
+		set(i_headset, 'Custom');
+		if(%1 != 0,
+			copy(i_fov, webvr.mobilevr_lens_fov);
+			roundval(i_fov, 1);
+			copy(i_dist, webvr.mobilevr_lens_dist);
+			roundval(i_dist, 2);
+			copy(i_dist2, webvr.mobilevr_lens_dist2);
+			copy(i_vig, webvr.mobilevr_lens_vign);
+			roundval(i_vig, 0);
+			copy(i_ca, webvr.mobilevr_lens_ca);
+			roundval(i_ca, 3);
+			copy(i_overlap, webvr.mobilevr_lens_overlap);
+			roundval(i_overlap, 2);
+			set(i_hsindex, -1);
+			copy(i_hscount, vrheadsets.headset.count);
+			for(set(i,0), i LT i_hscount, inc(i),
+				copy(hs, vrheadsets.headset[get(i)]);
+				if(i_overlap == hs.overlap AND i_fov == hs.fov AND i_dist == hs.dist AND i_dist2 == hs.dist2 AND i_ca == hs.ca AND i_vig == hs.vig , copy(i_hsindex, i); copy(i_headset, hs.caption); );
+			   );
+
+			if(%1 GT 0,
+				<!-- loop right -->
+				add(i_hsindex, 1);
+				if(i_hsindex GE i_hscount, set(i_hsindex,0));
+			  ,
+				<!-- loop left -->
+				sub(i_hsindex, 1);
+				if(i_hsindex LT 0, sub(i_hsindex,i_hscount,1));
+			  );
+
+			copy(hs, vrheadsets.headset[get(i_hsindex)]);
+			copy(i_headset, hs.caption);
+			copy(i_overlap, hs.overlap);
+			copy(i_fov,     hs.fov);
+			copy(i_dist,    hs.dist);
+			copy(i_dist2,   hs.dist2);
+			copy(i_ca,      hs.ca);
+			copy(i_vig,     hs.vig);
+		  );
+
+		copy(layer[vr_setup_hmd2].html, i_headset);
+		if(%1 != 0,
+			copy(webvr.mobilevr_lens_overlap, i_overlap);
+			copy(webvr.mobilevr_lens_fov, i_fov);
+			copy(webvr.mobilevr_lens_dist, i_dist);
+			copy(webvr.mobilevr_lens_dist2, i_dist2);
+			copy(webvr.mobilevr_lens_ca, i_ca);
+			copy(webvr.mobilevr_lens_vign, i_vig);
+			copy(layer[vr_setup_olp2].html, i_overlap);
+			copy(layer[vr_setup_fov2].html, i_fov);
+			copy(layer[vr_setup_dst2].html, i_dist);
+			
+			txtsplit(i_dist2, '|', i_dist2_k1, i_dist2_k2, i_dist2_k3, i_dist2_k4);
+			mul(i_dist2_k1,1);
+			mul(i_dist2_k2,10);
+			mul(i_dist2_k3,10);
+			mul(i_dist2_k4,10);
+			roundval(i_dist2_k1,2);
+			roundval(i_dist2_k2,2);
+			roundval(i_dist2_k3,2);
+			roundval(i_dist2_k4,2);
+			copy(layer[vr_setup_d2k1].html, i_dist2_k1);
+			copy(layer[vr_setup_d2k2].html, i_dist2_k2);
+			copy(layer[vr_setup_d2k3].html, i_dist2_k3);
+			copy(layer[vr_setup_d2k4].html, i_dist2_k4);
+			
+			copy(layer[vr_setup_cac2].html, i_ca);
+			copy(layer[vr_setup_vig2].html, i_vig);
+		  );
+	</action>
+
+</krpano>

BIN
public/code/resource/plugins/webvr_cursor_80x80_17f.png


BIN
public/code/resource/skin/rotate_device.png


BIN
public/code/resource/skin/vtourskin.png


File diff suppressed because it is too large
+ 1177 - 0
public/code/resource/skin/vtourskin.xml


+ 28 - 0
public/code/resource/skin/vtourskin_design_117.xml

@@ -0,0 +1,28 @@
+<krpano>
+
+	<!-- Version 1.17 Design -->
+
+	<skin_settings layout_width="100%"
+	               layout_maxwidth=""
+	               controlbar_width="100%"
+	               controlbar_height.normal="40"
+	               controlbar_height.mobile="38"
+	               controlbar_offset.normal="20"
+	               controlbar_offset.mobile="0"
+	               controlbar_offset_closed="-2"
+	               controlbar_overlap="0"
+	               design_skin_images="vtourskin.png"
+	               design_bgcolor="0x000000"
+	               design_bgalpha="0.5"
+	               design_bgborder="1,0 0xFFFFFF 1"
+	               design_bgroundedge.no-ios="0"
+	               design_bgroundedge.ios="1"
+	               design_bgshadow="0 0 20 0x000000 1.0"
+	               design_thumbborder_bgborder="4 0xFFFFFF 1.0"
+	               design_thumbborder_padding="2"
+	               design_thumbborder_bgroundedge="3"
+	               design_text_css="color:#FFFFFF; font-family:Arial; font-weight:bold;"
+	               design_text_shadow="1"
+	               />
+
+</krpano>

+ 31 - 0
public/code/resource/skin/vtourskin_design_117round.xml

@@ -0,0 +1,31 @@
+<krpano>
+
+	<!-- Version 1.17 Round Design -->
+
+	<skin_settings layout_width="100%"
+	               layout_maxwidth.normal="900"
+	               layout_maxwidth.mobile=""
+	               controlbar_width.normal="-44"
+	               controlbar_width.mobile="100%"
+	               controlbar_height.normal="38"
+	               controlbar_height.mobile="34"
+	               controlbar_offset.normal="22"
+	               controlbar_offset.mobile="0"
+	               controlbar_offset_closed="-40"
+	               controlbar_overlap.normal="7"
+	               controlbar_overlap.mobile="2"
+	               design_skin_images="vtourskin.png"
+	               design_bgcolor="0x000000"
+	               design_bgalpha="0.5"
+	               design_bgborder="0 0xFFFFFF 1.0"
+	               design_bgroundedge.normal="9"
+	               design_bgroundedge.mobile="1"
+	               design_bgshadow="0 0 9 0xFFFFFF 0.5"
+	               design_thumbborder_bgborder="4 0xFFFFFF 1.0"
+	               design_thumbborder_padding="2"
+	               design_thumbborder_bgroundedge="5"
+	               design_text_css="color:#FFFFFF; font-family:Arial; font-weight:bold;"
+	               design_text_shadow="1"
+	               />
+
+</krpano>

+ 71 - 0
public/code/resource/skin/vtourskin_design_black.xml

@@ -0,0 +1,71 @@
+<krpano>
+
+	<!-- Flat Light Design -->
+
+	<!-- modify the <skin_settings> values -->
+	<skin_settings layout_width="100%"
+	               layout_maxwidth="100%"
+	               controlbar_width="100%"
+	               controlbar_height="40"
+	               controlbar_offset.normal="0"
+	               controlbar_offset.mobile="0"
+	               controlbar_offset_closed="-40"
+	               controlbar_overlap.no-fractionalscaling="0"
+	               controlbar_overlap.fractionalscaling="0"
+	               design_skin_images="vtourskin.png"
+	               design_bgcolor="0x000000"
+	               design_bgalpha="1.0"
+	               design_bgborder="0"
+	               design_bgroundedge="0"
+	               design_bgshadow="0 4 10 0xFFFFFF 0.3"
+	               design_thumbborder_bgborder="3 0xB2B2B2 1.0"
+	               design_thumbborder_padding="2"
+	               design_thumbborder_bgroundedge="0"
+	               design_text_css="color:#FFFFFF; font-family:Arial;"
+	               design_text_shadow="0"
+	               />
+
+	<!-- adjust the design of some skin elements  -->
+	<layer name="skin_layer">
+		<layer name="skin_loadingtext" width="100%" css="calc:skin_settings.design_text_css + ' text-align:center; font-size:20px;'" padding="4 6" textshadow="calc:2.0" textshadowrange="1.0" textshadowangle="90" textshadowcolor="0x2D3E50" textshadowalpha="1.0" />
+		<layer name="skin_control_bar" alpha="0.7" />
+	</layer>
+
+
+	<!-- use a fullscreen map -->
+	<action name="skin_showmap">
+		if(%1 == null, if(layer[skin_map].state == 'closed', set(show,true), set(show,false)); , set(show,%1); );
+		mul(mh, layer[skin_scroll_layer].pixelheight, -1);
+		if(show,
+			tween(layer[skin_thumbs_container].alpha, 0.0, 0.25, default, set(layer[skin_thumbs_container].visible,false));
+			set(layer[skin_map].visible, true);
+			tween(layer[skin_map].alpha, 1.0, 0.25);
+			set(layer[skin_map].state, 'opened');
+			sub(hh,area.pixelheight,skin_settings.controlbar_offset);
+			sub(hh,layer[skin_control_bar].height);
+			sub(hh,0);
+			add(mh,hh);
+			sub(hh,skin_settings.controlbar_overlap);
+			copy(layer[skin_map].height, hh);
+			tween(layer[skin_scroll_layer].y, get(mh), 0.5, easeOutQuint);
+		  ,
+		  	if(layer[skin_map].state != 'closed',
+				set(layer[skin_map].state, 'closed');
+				add(mh, layer[skin_scroll_layer].y_offset);
+				tween(layer[skin_map].alpha, 0.0, 0.5, easeOutQuint);
+				tween(layer[skin_scroll_layer].y, get(mh), 0.5, easeOutQuint, set(layer[skin_map].visible,false) );
+			  );
+		  );
+	</action>
+
+
+	<!-- webvr button style (adjust to match skin style) -->
+	<style name="webvr_button_style"
+	       border="false"
+	       roundedge="calc:1.0"
+	       backgroundcolor="get:skin_settings.design_bgcolor" backgroundalpha="get:skin_settings.design_bgalpha"
+	       shadow="0.01" shadowrange="10.0" shadowangle="90.0" shadowcolor="0x30261B" shadowalpha="0.50"
+	       css="calc:skin_settings.design_text_css + ' font-size:' + 20*webvr_setup_scale*webvr_button_scale + 'px;'"
+	       />
+
+</krpano>

+ 42 - 0
public/code/resource/skin/vtourskin_design_flat_light.xml

@@ -0,0 +1,42 @@
+<krpano>
+
+	<!-- Flat Light Design -->
+
+	<!-- modify the <skin_settings> values -->
+	<skin_settings layout_width="100%"
+	               layout_maxwidth="814"
+	               controlbar_width="-24"
+	               controlbar_height="40"
+	               controlbar_offset.normal="20"
+	               controlbar_offset.mobile="20"
+	               controlbar_offset_closed="-40"
+	               controlbar_overlap.no-fractionalscaling="10"
+	               controlbar_overlap.fractionalscaling="0"
+	               design_skin_images="vtourskin_light.png"
+	               design_bgcolor="0x2D3E50"
+	               design_bgalpha="0.8"
+	               design_bgborder="0"
+	               design_bgroundedge="1"
+	               design_bgshadow="0 4 10 0x000000 0.3"
+	               design_thumbborder_bgborder="2 0xFFFFFF 0.8"
+	               design_thumbborder_padding="2"
+	               design_thumbborder_bgroundedge="0"
+	               design_text_css="color:#FFFFFF; font-family:Arial; font-weight:lighter;"
+	               design_text_shadow="1"
+	               />
+
+	<!-- adjust the design of some skin elements  -->
+	<layer name="skin_layer">
+		<layer name="skin_loadingtext" width="100%" css="calc:skin_settings.design_text_css + ' text-align:center; font-size:20px;'" padding="4 6" textshadow="calc:2.0" textshadowrange="1.0" textshadowangle="90" textshadowcolor="0x2D3E50" textshadowalpha="1.0" />
+	</layer>
+
+	<!-- webvr button style (adjust to match skin style) -->
+	<style name="webvr_button_style"
+	       border="false"
+	       roundedge="calc:1.0"
+	       backgroundcolor="get:skin_settings.design_bgcolor" backgroundalpha="get:skin_settings.design_bgalpha"
+	       shadow="0.01" shadowrange="10.0" shadowangle="90.0" shadowcolor="0x30261B" shadowalpha="0.50"
+	       css="calc:skin_settings.design_text_css + ' font-size:' + 20*webvr_setup_scale*webvr_button_scale + 'px;'"
+	       />
+
+</krpano>

+ 40 - 0
public/code/resource/skin/vtourskin_design_glass.xml

@@ -0,0 +1,40 @@
+<krpano>
+
+	<!-- Glass Design -->
+
+	<!-- modify the <skin_settings> values -->
+	<skin_settings thumbs_scrollindicator="true"
+	               layout_width="100%"
+	               layout_maxwidth="680"
+	               xcontrolbar_width="-44"
+	               controlbar_width="-20"
+	               controlbar_height="36"
+	               controlbar_offset.normal="40"
+	               controlbar_offset.mobile="12"
+	               controlbar_offset_closed="-40"
+	               controlbar_overlap="10"
+	               design_skin_images="vtourskin.png"
+	               design_bgcolor="0xFFFFFF"
+	               design_bgalpha="0.25"
+	               design_bgborder="2 0xFFFFFF 0.1"
+	               design_bgroundedge="13"
+	               design_bgshadow="0"
+	               design_thumbborder_bgborder="3 0xFFFFFF 1.0"
+	               design_thumbborder_padding="2"
+	               design_thumbborder_bgroundedge="5"
+	               design_text_css="color:#FFFFFF; font-family:Arial; font-weight:bold;"
+	               design_text_shadow="0"
+	               />
+
+	<!-- webvr button style (adjust to match default skin style) -->
+	<style name="webvr_button_style"
+	       border="true" borderwidth="2" bordercolor="0xFFFFFF" borderalpha="0.25"
+	       backgroundcolor="get:skin_settings.design_bgcolor" backgroundalpha="get:skin_settings.design_bgalpha"
+	       shadow="0"
+	       css="calc:skin_settings.design_text_css + ' color:#FFFFFF; font-weight:normal; font-size:' + 20*webvr_setup_scale*webvr_button_scale + 'px;'"
+	       />
+
+	<!-- contextmenu style (adjust to match skin style) -->
+	<contextmenu customstyle="default|default|default|0x77AAAAAA|0xFFFFFF|0xBBBBBB|2|0x7FFFFFFF|13|0|0|0|0xFFFFFF|0|0|4|6|7|0xAAFFFFFF|none|3|0|0|0|3|0xAAFFFFFF|0xAAFFFFFF|0xFFFFFF|12|8" />
+
+</krpano>

+ 58 - 0
public/code/resource/skin/vtourskin_design_ultra_light.xml

@@ -0,0 +1,58 @@
+<krpano>
+
+	<!-- Ultra Light Design -->
+
+	<!-- modify the <skin_settings> values -->
+	<skin_settings title="false"
+	               layout_width="100%"
+	               layout_maxwidth="814"
+	               controlbar_width="-24"
+	               controlbar_height="40"
+	               controlbar_offset.normal="30"
+	               controlbar_offset.mobile="20"
+	               controlbar_offset_closed="-40"
+	               controlbar_overlap="0"
+	               design_skin_images="vtourskin_light.png"
+	               design_bgcolor="0x2D3E50"
+	               design_bgalpha="0.0"
+	               design_bgborder="0,0,1,0 0xFFFFFF 1"
+	               design_bgroundedge="0"
+	               design_bgshadow="0"
+	               design_thumbborder_bgborder="1 0xFFFFFF 0.8"
+	               design_thumbborder_padding="0"
+	               design_thumbborder_bgroundedge="0"
+	               design_text_css="color:#FFFFFF; font-family:Arial; font-weight:lighter;"
+	               design_text_shadow="0"
+	               />
+
+	<!-- webvr button style (adjust to match skin style) -->
+	<style name="webvr_button_style"
+	       border="false"
+	       roundedge="calc:1.0"
+	       backgroundcolor="get:skin_settings.design_bgcolor" backgroundalpha="get:skin_settings.design_bgalpha"
+	       shadow="0.01" shadowrange="10.0" shadowangle="90.0" shadowcolor="0x30261B" shadowalpha="0.50"
+	       css="calc:skin_settings.design_text_css + ' font-size:' + 20*webvr_setup_scale*webvr_button_scale + 'px;'"
+	       />
+
+	<!-- adjust video controls to match skin style -->
+	<layer name="skin_layer">
+		<layer name="skin_scroll_window">
+			<layer name="skin_scroll_layer">
+				<layer name="skin_video_controls">
+					<layer name="skin_video_seekbar_container">
+						<layer name="skin_video_seekbar" height="1" y="4">
+							<layer name="skin_video_loadbar" height="1" />
+							<layer name="skin_video_seekpos" bgroundedge="2" width="6" height="6" />
+						</layer>
+					</layer>
+					<layer name="skin_video_time" y="-4" />
+				</layer>
+			</layer>
+		</layer>
+	</layer>
+					
+
+	<!-- contextmenu style (adjust to match skin style) -->
+	<contextmenu customstyle="default|default|default|0x7F000000|0xFFFFFF|0xBBBBBB|0|0x20FFFFFF|1|0|0|0|0xFFFFFF|0|0xFFFFFF|4|6|7|0xAAFFFFFF|none|3|0|0|0|3|0xFFFFFF|0xFFFFFF|0x000000|12|8" />
+
+</krpano>

BIN
public/code/resource/skin/vtourskin_hotspot.png


BIN
public/code/resource/skin/vtourskin_light.png


BIN
public/code/resource/skin/vtourskin_mapspot.png


BIN
public/code/resource/skin/vtourskin_mapspotactive.png


+ 29 - 0
public/code/resource/tour.html

@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+	<title>krpano - qqw</title>
+	<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
+	<meta name="apple-mobile-web-app-capable" content="yes" />
+	<meta name="apple-mobile-web-app-status-bar-style" content="black" />
+	<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+	<meta http-equiv="x-ua-compatible" content="IE=edge" />
+	<style>
+		@-ms-viewport { width:device-width; }
+		@media only screen and (min-device-width:800px) { html { overflow:hidden; } }
+		html { height:100%; }
+		body { height:100%; overflow:hidden; margin:0; padding:0; font-family:Arial, Helvetica, sans-serif; font-size:16px; color:#FFFFFF; background-color:#000000; }
+	</style>
+</head>
+<body>
+
+<script src="tour.js"></script>
+
+<div id="pano" style="width:100%;height:100%;">
+	<noscript><table style="width:100%;height:100%;"><tr style="vertical-align:middle;"><td><div style="text-align:center;">ERROR:<br/><br/>Javascript not activated<br/><br/></div></td></tr></table></noscript>
+	<script>
+		embedpano({swf:"tour.swf", xml:"tour.xml", target:"pano", html5:"auto", mobilescale:1.0, passQueryParameters:true});
+	</script>
+</div>
+
+</body>
+</html>

File diff suppressed because it is too large
+ 14 - 0
public/code/resource/tour.js


BIN
public/favicon.png


+ 29 - 0
public/show.html

@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
+    <link rel="icon" href="<%= BASE_URL %>favicon.png">
+    <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>resource/js/scrollbar/perfect-scrollbar.css"/>
+    <title>第15届中国航展</title>
+    <script>
+      var _hmt = _hmt || [];
+      (function() {
+        var hm = document.createElement("script");
+        hm.src = "https://hm.baidu.com/hm.js?d832f83b23b622976d17bd411fe9f17d";
+        var s = document.getElementsByTagName("script")[0]; 
+        s.parentNode.insertBefore(hm, s);
+      })();
+      </script>
+      
+  </head>
+  <body>
+    <div id="app"></div>
+    <script src="<%= VUE_APP_STATIC_DIR %>resource/js/jquery-2.1.1.min.js"></script>
+    <script src="<%= VUE_APP_STATIC_DIR %>resource/js/tour.js"></script>
+    <script src="<%= VUE_APP_STATIC_DIR %>resource/js/clipboard.min.js"></script>
+    <script src="<%= VUE_APP_STATIC_DIR %>resource/js/scrollbar/perfect-scrollbar.min.js"></script>
+
+  </body>
+</html>

+ 26 - 0
public/showMobile.html

@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
+    <link rel="icon" href="<%= BASE_URL %>favicon.png">
+    <title>第15届中国航展</title>
+    <script>
+      var _hmt = _hmt || [];
+      (function() {
+        var hm = document.createElement("script");
+        hm.src = "https://hm.baidu.com/hm.js?d832f83b23b622976d17bd411fe9f17d";
+        var s = document.getElementsByTagName("script")[0]; 
+        s.parentNode.insertBefore(hm, s);
+      })();
+      </script>
+      
+  </head>
+  <body>
+    <div id="app"></div>
+    <script src="<%= VUE_APP_STATIC_DIR %>resource/js/jquery-2.1.1.min.js"></script>
+    <script src="<%= VUE_APP_STATIC_DIR %>resource/js/clipboard.min.js"></script>
+    <script src="<%= VUE_APP_STATIC_DIR %>resource/js/tour.js"></script>
+  </body>
+</html>

+ 31 - 0
src/App.vue

@@ -0,0 +1,31 @@
+<template>
+  <div id="app">
+    <Home/>
+  </div>
+</template>
+
+<script>
+import '@/assets/style/reset.less'
+import '@/assets/style/public.less'
+import Home from '@/views/Home.vue'
+
+export default {
+  components:{Home},
+   methods: {
+     
+    },
+    mounted(){
+    }
+};
+</script>
+
+<style lang="less">
+@color:#C20E23;
+
+#app {
+  width: 100%;
+  height: 100%;
+  background-color: @color;
+}
+
+</style>

BIN
src/assets/audio/bgm.mp3


BIN
src/assets/images/a.png


BIN
src/assets/images/bg.jpg


BIN
src/assets/images/close.png


BIN
src/assets/images/jiantou.png


BIN
src/assets/images/jiantou_w.png


BIN
src/assets/images/jump.png


BIN
src/assets/images/labg.png


BIN
src/assets/images/logo.png


BIN
src/assets/images/mbbg.jpg


BIN
src/assets/images/menu.png


BIN
src/assets/images/top1.png


BIN
src/assets/images/top2.png


BIN
src/assets/images/top3.png


+ 43 - 0
src/assets/style/iconfont/iconfont.css

@@ -0,0 +1,43 @@
+@font-face {
+  font-family: "iconfont"; /* Project id 2820495 */
+  src: url('iconfont.woff2?t=1631880378082') format('woff2'),
+       url('iconfont.woff?t=1631880378082') format('woff'),
+       url('iconfont.ttf?t=1631880378082') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-a-9gedian:before {
+  content: "\e69f";
+}
+
+.icon-sangedian:before {
+  content: "\e69e";
+}
+
+.icon-jianjie:before {
+  content: "\e69d";
+}
+
+.icon-fenxiang:before {
+  content: "\e69c";
+}
+
+.icon-yinleguan:before {
+  content: "\e69b";
+}
+
+.icon-yinlekai:before {
+  content: "\e69a";
+}
+
+.icon-more:before {
+  content: "\e698";
+}
+

File diff suppressed because it is too large
+ 1 - 0
src/assets/style/iconfont/iconfont.js


+ 58 - 0
src/assets/style/iconfont/iconfont.json

@@ -0,0 +1,58 @@
+{
+  "id": "2820495",
+  "name": "航展",
+  "font_family": "iconfont",
+  "css_prefix_text": "icon-",
+  "description": "",
+  "glyphs": [
+    {
+      "icon_id": "24432102",
+      "name": "9个点",
+      "font_class": "a-9gedian",
+      "unicode": "e69f",
+      "unicode_decimal": 59039
+    },
+    {
+      "icon_id": "24431545",
+      "name": "三个点",
+      "font_class": "sangedian",
+      "unicode": "e69e",
+      "unicode_decimal": 59038
+    },
+    {
+      "icon_id": "24431439",
+      "name": "简介",
+      "font_class": "jianjie",
+      "unicode": "e69d",
+      "unicode_decimal": 59037
+    },
+    {
+      "icon_id": "24430046",
+      "name": "分享",
+      "font_class": "fenxiang",
+      "unicode": "e69c",
+      "unicode_decimal": 59036
+    },
+    {
+      "icon_id": "24429866",
+      "name": "音乐关",
+      "font_class": "yinleguan",
+      "unicode": "e69b",
+      "unicode_decimal": 59035
+    },
+    {
+      "icon_id": "24429858",
+      "name": "音乐开",
+      "font_class": "yinlekai",
+      "unicode": "e69a",
+      "unicode_decimal": 59034
+    },
+    {
+      "icon_id": "24429570",
+      "name": "more",
+      "font_class": "more",
+      "unicode": "e698",
+      "unicode_decimal": 59032
+    }
+  ]
+}

BIN
src/assets/style/iconfont/iconfont.ttf


BIN
src/assets/style/iconfont/iconfont.woff


BIN
src/assets/style/iconfont/iconfont.woff2


+ 49 - 0
src/assets/style/public.less

@@ -0,0 +1,49 @@
+html,body{
+  width: 100%;
+  height: 100%;
+  -webkit-overflow-scrolling: touch;
+  -webkit-tap-highlight-color:transparent;
+}
+
+.brightness{
+  &::before{
+    content: '';
+    position: absolute;
+    top: 0; 
+    bottom: 0;
+    left: 0; 
+    right: 0;
+    z-index: -2;
+    overflow: hidden;
+    background-repeat: no-repeat;
+    background-position: center;
+    background-color: rgba(0,0,0,0.7);
+    font-size: 0;
+  }
+}
+
+@supports (backdrop-filter: brightness(60%)) {
+  .brightness{
+    &::before{
+      content: '';
+      backdrop-filter: blur(10px) brightness(60%)!important;
+      background-color: rgba(0,0,0,0)!important;
+    }
+  }  
+}
+
+
+.fade-leave-active {
+  transition: opacity .3s;
+}
+.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
+  opacity: 0;
+}
+
+.noshow{
+  position: fixed;
+  top: -100px;
+  left: -100px;
+  opacity: 0;
+  visibility: hidden;
+}

+ 43 - 0
src/assets/style/reset.less

@@ -0,0 +1,43 @@
+/* reset */
+html,body,h1,h2,h3,h4,h5,h6,div,dl,dt,dd,ul,ol,li,p,blockquote,pre,hr,figure,table,caption,th,td,form,fieldset,legend,input,button,textarea,menu{margin:0;padding:0;}
+header,footer,section,article,aside,nav,hgroup,address,figure,figcaption,menu,details{display:block;}
+table{border-collapse:collapse;border-spacing:0;}
+caption,th{text-align:left;font-weight:normal;}
+html,body,fieldset,img,iframe,abbr{border:0;}
+i,cite,em,var,address,dfn{font-style:normal;}
+[hidefocus],summary{outline:0;}
+li{list-style:none;}
+h1,h2,h3,h4,h5,h6,small{font-size:100%;}
+sup,sub{font-size:83%;}
+pre,code,kbd,samp{font-family:inherit;}
+q:before,q:after{content:none;}
+textarea{overflow:auto;resize:none;}
+label,summary{cursor:default;}
+a,button{cursor:pointer;}
+h1,h2,h3,h4,h5,h6,em,strong,b{font-weight:bold;}
+del,ins,u,s,a,a:hover{text-decoration:none;}
+body,textarea,input,button,select,keygen,legend{font:14px/1.14;outline:0;}
+body{background:#fff;}
+*{box-sizing: border-box}
+a{text-decoration: none;}
+
+
+::-webkit-scrollbar {
+  width: 0;
+  height: 8px;
+}
+
+::-webkit-scrollbar-thumb {
+  height: 50px;
+  background-color: #ddd;
+  -webkit-border-radius: 4px;
+  outline: 2px solid #fff;
+  outline-offset: -2px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+  height: 50px;
+  background-color: #9f9f9f;
+  -webkit-border-radius: 4px;
+}
+

BIN
src/assets/videos/once.mp4


+ 91 - 0
src/components/rollName/index.vue

@@ -0,0 +1,91 @@
+<template>
+  <div class="rollcon" :ref="'r_'+myref">
+    <span :class="{shenglv:(parentW < childW && !active)}" :ref="myref" :style="`transform: translateX(${translate}px);
+    ${`width: ${(parentW < childW && !active)?`calc(100% - ${mgin||10}px)`:'auto'}`}`">{{name}}</span>
+  </div>
+</template>
+<script>
+export default {
+  props:['name','myref','active','offset','mgin'],
+
+  data(){
+    return {
+      translate: 0,
+      parentW:0,
+      childW:0,
+      inter:null
+    }
+  },
+  watch:{
+    active:{
+      immediate:true,
+      handler:function (newVal) {
+        if (newVal) {
+          this.init()
+        }
+      }
+    }
+  },
+  methods:{
+    clearInter(){
+      clearInterval(this.inter)
+      this.inter = null
+    },
+    init(){
+      this.$nextTick(() => {
+          this.parentW = this.$refs['r_'+this.myref] ? this.$refs['r_'+this.myref].offsetWidth : 0
+          this.childW = this.$refs[this.myref] ? this.$refs[this.myref].offsetWidth : 0
+          this.start()
+      })
+    },
+    start(){
+      let fn = ()=>{
+        this.translate -= 0.2
+        if ((this.parentW - this.translate -  (this.mgin || 0))>(this.childW + this.parentW)) {
+          this.translate = this.parentW
+        }
+        if (!this.active) {
+          this.translate = 0
+          this.clearInter()
+          return
+        }
+        // requestAnimationFrame(fn)
+      }
+
+      console.log(this.parentW, this.childW);
+      
+      if (this.parentW < this.childW) {
+        this.clearInter()
+        this.inter = setInterval(() => {
+            fn()
+        }, 10);
+      }
+    }
+  },
+  mounted(){
+    this.init()
+  },
+  beforeDestroy(){
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.rollcon{
+  width: 100%;
+  display: inline-block;
+  >span{
+    width: auto;
+    display: inline-block;
+    // transition: 0.3s transform ease;
+    vertical-align:unset;
+  }
+  .shenglv{
+    text-overflow: ellipsis;
+    overflow: hidden;
+    white-space: nowrap;
+    line-height: 100%;
+    vertical-align: baseline;
+  }
+}
+</style>

+ 252 - 0
src/components/welcome/index.vue

@@ -0,0 +1,252 @@
+<template>
+  <div
+    class="welcome"
+    :style="{
+      backgroundImage: !isVideo
+        ? `url(${g_CDN}images/${g_isMobile ? 'mbbg' : 'bg'}.jpg)`
+        : '',
+    }"
+  >
+    <img class="logo" :src="`${g_CDN}images/logo.png`" alt="" />
+    <div class="wlvideo brightness" v-if="isVideo">
+      <div class="videocon">
+        <video
+          ref="welcome"
+          autoplay
+          controls
+          controlslist="nodownload noremoteplayback"
+          disablePictureInPicture
+          :src="`${g_CDN}videos/once.mp4`"
+        ></video>
+        <div @click="handleJump" class="vbtn">
+          <img :src="`${g_CDN}images/jump.png`" alt="" />
+        </div>
+      </div>
+    </div>
+
+    <div class="wlcon" v-else>
+      <!-- <img class="top1" :src="`${g_CDN}images/top1.png`" alt="" />
+      <img class="top2" :src="`${g_CDN}images/top2.png`" alt="" />
+      <img class="top3" :src="`${g_CDN}images/top3.png`" alt="" /> -->
+      <img class="top4" :src="`${g_CDN}images/top4.png`" alt="" />
+      <ul>
+        <!-- 待完善 -->
+        <li style="opacity: 0; pointer-events: none;" @click="select('fdkk')">展馆漫游</li>
+        <li @click="select('pano')">展区漫游</li>
+      </ul>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      showJump: "",
+      isVideo: false,
+      // isKj: false,
+    };
+  },
+  watch: {},
+  methods: {
+    select(type) {
+      this.$bus.$emit("changeType", type);
+      this.$bus.$emit("toggleBgm", true);
+      this.handleJump();
+      // this.isVideo = true;
+      // this.startplay();
+    },
+    handleJump() {
+      this.$bus.$emit("closeWel", true);
+    },
+    startplay() {
+      this.$nextTick(() => {
+        if (this.$refs.welcome) {
+          this.$refs.welcome.play();
+          this.$refs.welcome &&
+            this.$refs.welcome.addEventListener("ended", () => {
+              this.$bus.$emit("closeWel", true);
+            });
+        }
+      });
+    },
+  },
+  mounted() {
+    // this.$nextTick(() => {
+    //   this.isKj = this.getQueryVariable("type") == "kj";
+    //   if (this.isKj) {
+    //     setTimeout(() => {
+    //       this.select("pano");
+    //     }, 0);
+    //   }
+    // });
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.welcome {
+  position: fixed;
+  left: 50%;
+  top: 50%;
+  transform: translate(-50%, -50%);
+  width: 102%;
+  height: 102%;
+  overflow: hidden;
+  background-size: cover;
+  background-repeat: no-repeat;
+  font-size: 0;
+  background-color: #7dbded;
+  z-index: 9999;
+  .logo {
+    position: absolute;
+    left: 60px;
+    top: 36px;
+    width: 140px;
+  }
+  .wlcon {
+    position: absolute;
+    bottom: 10%;
+    left: 50%;
+    transform: translateX(-50%);
+    text-align: center;
+    width: 100%;
+    > img {
+      max-width: 100%;
+      display: block;
+      margin: 0 auto;
+    }
+
+    .top1 {
+      width: 400px;
+    }
+
+    .top2 {
+      width: 204px;
+      margin: 16px auto;
+    }
+
+    .top3 {
+      width: 440px;
+    }
+
+    > ul {
+      margin: 110px auto 0;
+      width: 365px;
+      > li {
+        @h: 60px;
+        border: 2px solid @color;
+        height: @h;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        border-radius: 40px;
+        letter-spacing: 2px;
+        cursor: pointer;
+        color: @color;
+        background-color: rgba(255, 255, 255, 0.4);
+        font-size: 20px;
+        &:last-of-type {
+          margin-top: 30px;
+        }
+      }
+    }
+  }
+
+  .wlvideo {
+    position: absolute;
+    left: 50%;
+    transform: translateX(-50%);
+    text-align: center;
+    width: 100%;
+    height: 100%;
+    .videocon {
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      width: 100%;
+      transform: translate(-50%, -50%);
+      > video {
+        width: 50%;
+      }
+      .vbtn {
+        margin: 30px auto;
+        width: 80px;
+        cursor: pointer;
+        > img {
+          width: 100%;
+        }
+      }
+    }
+  }
+}
+
+@media screen and (max-width: 800px) {
+  .welcome {
+    .logo {
+      position: absolute;
+      right: 0;
+      top: 0;
+      left: unset;
+      width: 30%;
+    }
+    .wlcon {
+      position: absolute;
+      bottom: 5%;
+      left: 50%;
+      transform: translateX(-50%);
+      text-align: center;
+      width: 100%;
+      > img {
+        max-width: 100%;
+        display: block;
+        margin: 0 auto;
+      }
+
+      .top1 {
+        width: 50%;
+      }
+
+      .top2 {
+        width: 40%;
+        margin: 16px auto;
+      }
+
+      .top3 {
+        width: 80%;
+      }
+
+      > ul {
+        margin: 38% auto 0;
+        width: 50%;
+        > li {
+          @h: 60px;
+          border: 2px solid @color;
+          height: @h;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          border-radius: 40px;
+          margin-bottom: 14px;
+          letter-spacing: 2px;
+          cursor: pointer;
+          color: @color;
+          background-color: rgba(255, 255, 255, 0.4);
+          font-size: 20px;
+        }
+      }
+    }
+
+    .wlvideo {
+      .videocon {
+        > video {
+          width: 100%;
+        }
+        .vbtn {
+          width: 60px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 0 - 0
src/data/index.js


+ 268 - 0
src/framework/show/fdkk.vue

@@ -0,0 +1,268 @@
+<template>
+  <div class="ifrcon">
+    <iframe allowfullscreen="true" ref="iframe" :key="selected.id"
+      :src="`https://airshow.4dkankan.com/spc.html?m=${selected.id}`" frameborder="0" @click="handleifrclk"
+      @load="onIframLoad"></iframe>
+    <mbui :type="type" :isShow="isShow" @close="isShow = false">
+      <div class="img_ul" slot="imgList">
+        <ul v-if="selectExh.scenes">
+          <li v-for="(item, i) in selectExh.scenes" @click="selected = item" :key="i"
+            :class="{ active: selected.id == item.id }">
+            <div>
+              <img
+                :src="`https://4dkk.4dage.com/images/images${item.id}/floor_0.png?t=1667802021476?v=0&rnd=0.5813201205835572&x-oss-process=image/resize,m_fill,w_80,h_60/quality,q_70`"
+                v-errorimg="`${fdkk_CDN}/hangzhan/images/images${item.id}/result.png`" alt="" />
+              <!-- <img :src="`https://airshow.4dkankan.com/images/images${item.id}/smallPic.jpg`" v-errorimg="`${fdkk_CDN}/hangzhan/images/images${item.id}/result.png`" alt="" /> -->
+              <rollName :offset="20" :active="selected.id == item.id" class="pic-name" :myref="'subw' + item.id"
+                :name="item.title" />
+            </div>
+            <span class="bar"></span>
+          </li>
+        </ul>
+      </div>
+
+      <div class="txt_ul" slot="txtList">
+        <ul>
+          <li v-for="(item, i) in list" @click="selectExh = item" :key="i" :class="{ active: selectExh.id == item.id }">
+            <span>{{ selectExh.id == item.id ? item.title : item.short }}</span>
+          </li>
+        </ul>
+      </div>
+
+      <div v-if="!isShow" @click="isShow = true" class="btn_zhankai" slot="btn_zhankai">
+        <i class="iconfont icon-more"></i>
+      </div>
+      <vAside class="ui_header" slot="aside" />
+      <vSelect slot="select" :type="type"></vSelect>
+    </mbui>
+  </div>
+</template>
+
+<script>
+import mbui from "./ui";
+import vAside from "./ui/aside.vue";
+import vSelect from "./ui/select.vue";
+
+
+export default {
+  props: ['type', 'exhibition'],
+  components: {
+    mbui,
+    vSelect,
+    vAside
+  },
+  data() {
+    return {
+      params: "",
+      isShow: true,
+      selected: '',
+      selectExh: {},
+      list: []
+    };
+  },
+  watch: {
+    selected: {
+      deep: true,
+      handler: function (newVal) {
+        console.log(newVal);
+      }
+    }
+  },
+  methods: {
+    handleifrclk() {
+      console.log(1111);
+    },
+    getList() {
+      window.$.ajax({
+        url: `${this.g_CDN}fdkk/data.json`, success: (data) => {
+          this.list = data.list
+          if (this.exhibition) {
+            this.selectExh = this.list.find(item => item.id == this.exhibition)
+          } else {
+            this.selectExh = this.list[0]
+          }
+          this.selected = this.selectExh.scenes[0]
+        }
+      })
+    },
+    onIframLoad() {
+      window.onmessage = () => {
+
+      };
+    },
+  },
+  mounted() {
+    this.getList()
+    this.$bus.$on('showM', () => {
+      this.isShowM = true
+    })
+  }
+};
+</script>
+
+<style lang="less" scoped>
+.ifrcon {
+  width: 100%;
+  height: 100%;
+  background: #fcfcfc;
+  text-align: center;
+
+  >iframe {
+    width: 100%;
+    height: 100%;
+  }
+
+  .img_ul {
+    width: 100%;
+    position: relative;
+
+    >ul {
+      overflow-x: auto;
+      display: inline-block;
+      background: linear-gradient(to right, rgba(32, 32, 32, 0), rgba(32, 32, 32, 1), rgba(32, 32, 32, 0));
+      min-width: 50%;
+
+      >li {
+        cursor: pointer;
+        list-style: none;
+        display: inline-block;
+        margin: 8px 10px;
+        position: relative;
+        padding-bottom: 8px;
+
+        >div {
+          width: 68px;
+          height: 68px;
+          overflow: hidden;
+          position: relative;
+          border-radius: 4px;
+          cursor: pointer;
+          color: rgba(256, 256, 256, 0.4);
+
+          >img {
+            position: absolute;
+            top: 50%;
+            left: 50%;
+            height: 100%;
+            transform: translate(-50%, -50%);
+          }
+
+          .iconfont {
+            position: absolute;
+            left: 4px;
+            top: 4px;
+            z-index: 99;
+          }
+
+          >span {
+            text-align: center;
+            display: inline-block;
+            background: rgba(0, 0, 0, 0.3);
+            position: absolute;
+            text-overflow: ellipsis;
+            overflow: hidden;
+            white-space: nowrap;
+            left: 0;
+            bottom: 0;
+            width: 100%;
+          }
+        }
+
+        .bar {
+          display: none;
+        }
+
+        .pic-name {
+          background: rgba(0, 0, 0, 0.6);
+          position: absolute;
+          left: 0;
+          bottom: 0;
+          text-align: center;
+
+          /deep/ span {
+            word-break: keep-all;
+            white-space: nowrap;
+            font-size: 12px;
+          }
+        }
+
+        &.active {
+          .bar {
+            display: inline-block;
+            position: absolute;
+            bottom: 0px;
+            width: 80%;
+            left: 50%;
+            transform: translateX(-50%);
+            height: 2px;
+            background: @color;
+          }
+
+          >div {
+            color: rgba(256, 256, 256, 1);
+          }
+        }
+      }
+    }
+  }
+
+  .txt_ul {
+    margin: 18px auto;
+    border: 2px solid @color;
+    border-radius: 30px;
+    padding: 6px 15px;
+    display: inline-block;
+
+    >ul {
+      overflow-x: auto;
+      display: flex;
+
+      &::-webkit-scrollbar {
+        display: none;
+      }
+
+      >li {
+        border: 1px solid rgba(256, 256, 256, 0.4);
+        border-radius: 24px;
+        padding: 6px 9px;
+        margin: 0 5px;
+        cursor: pointer;
+
+        >span {
+          font-size: 16px;
+          display: inline-block;
+          vertical-align: middle;
+          line-height: 1.2;
+          word-break: keep-all;
+          color: rgba(256, 256, 256, 0.4);
+        }
+
+        &.active {
+          padding: 6px 12px;
+          border: 1px solid @color;
+
+          >span {
+            color: #fff;
+          }
+        }
+      }
+    }
+  }
+
+  .btn_zhankai {
+    position: fixed;
+    left: 50%;
+    bottom: 8px;
+    transform: translateX(-50%);
+    background: rgba(0, 0, 0, .3);
+    border-radius: 50%;
+    padding: 6px;
+    cursor: pointer;
+
+    >i {
+      font-size: 28px;
+      cursor: pointer;
+    }
+  }
+}
+</style>

+ 79 - 0
src/framework/show/index.vue

@@ -0,0 +1,79 @@
+<template>
+  <div class="mbcon">
+    <audio ref="vbgm" class="noshow" loop :src="`${g_CDN}audio/bgm.mp3`"></audio>
+    <!-- <v-fdkk :exhibition="exhibition" v-if="exhibition" />
+    <template v-else> -->
+    <transition name="fade">
+      <welcome v-if="welcome && !exhibition && !area" />
+    </transition>
+    <v-fdkk :exhibition="exhibition" :type="type" v-if="type == 'fdkk'" />
+    <v-pano :type="type" :area="area" v-else />
+    <!-- </template> -->
+  </div>
+</template>
+
+<script>
+import vFdkk from "./fdkk";
+import vPano from "./pano";
+import welcome from "@/components/welcome";
+
+export default {
+  components: {
+    vFdkk,
+    vPano,
+    welcome
+  },
+  data() {
+    return {
+      type: 'fdkk',
+      exhibition: '',
+      isBgm: false,
+      welcome: false,
+      area: ''
+    }
+  },
+  watch: {
+    isBgm(newVal) {
+      !newVal ? this.$refs.vbgm.pause() : this.$refs.vbgm.play()
+    }
+  },
+  mounted() {
+
+    this.$bus.$on('changeType', (data) => {
+      this.type = data
+    })
+
+    this.$bus.$on('toggleBgm', (data) => {
+      this.isBgm = data
+    })
+
+    this.$bus.$on('closeWel', () => {
+      this.welcome = false
+      this.isBgm = true
+    })
+
+    this.exhibition = this.getQueryVariable('exhibition')
+
+    this.area = this.getQueryVariable('type')
+
+
+    this.$nextTick(() => {
+      this.welcome = true
+      if (this.exhibition) {
+        this.type = 'fdkk'
+      }
+      if (this.area) {
+        this.type = 'pano'
+      }
+    })
+
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.mbcon {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 385 - 0
src/framework/show/pano copy.vue

@@ -0,0 +1,385 @@
+<template>
+  <div class="ifrcon">
+    <div id="pano" class="pano"></div>
+    <div v-if="selected" class="title">{{ selected.sceneTitle }}</div>
+    <mbui :type="type" :class="{ uicon: exhibition }" :isShow="isShowM" @close="isShowM = false">
+      <div class="img_ul clip-scroller" slot="imgList">
+        <ul>
+          <li v-for="(item, i) in currentScenes" @click="handleItem(item)" :key="i"
+            :class="{ active: selected.id == item.id }">
+            <div>
+              <img :src="item.icon"
+                alt="" />
+              <rollName :offset="20" :active="selected.id == item.id" class="pic-name" :myref="'subw' + item.id"
+                :name="item.sceneTitle" />
+            </div>
+            <span class="bar"></span>
+          </li>
+        </ul>
+      </div>
+      <div class="txt_ul clip-scroller" slot="txtList" v-if="!exhibition">
+        <ul>
+          <li v-for="(item, i) in list" @click="selectExh = item" :key="i" :class="{ active: selectExh.id == item.id }">
+            <span>{{ item.title }}</span>
+          </li>
+        </ul>
+      </div>
+
+      <div v-if="!isShowM" @click="isShowM = true" class="btn_zhankai" slot="btn_zhankai">
+        <i class="iconfont icon-more"></i>
+      </div>
+      <vAside class="ui_header" slot="aside" />
+      <vSelect slot="select" v-if="!exhibition" :type="type"></vSelect>
+    </mbui>
+  </div>
+</template>
+
+<script>
+import mbui from "./ui";
+import vAside from "./ui/aside.vue";
+import vSelect from "./ui/select.vue";
+
+
+
+export default {
+  props: ['type', 'exhibition'],
+  components: {
+    mbui,
+    vSelect,
+    vAside
+  },
+  data() {
+    return {
+      params: "",
+      isShowM: true,
+      selected: {},
+      selectExh: {},
+      currentScenes:[],
+      list: [],
+      isFirst:true,
+      loadFinish: false
+    };
+  },
+  watch: {
+    selectExh: {
+      deep: true,
+      handler: function (newVal) {
+        if (newVal) {
+          this.isFirst = true
+          window.$.ajax({
+            dataType:'json',
+            url: `https://4dkk.4dage.com/720yun_fd_manage/${newVal.id}/someData.json?_=0.0672449349999431`, success: (data) => {
+              this.selected = data.scenes[0]
+              this.currentScenes = data.scenes
+              this.loadFinish = false
+            }
+          })
+        }
+      }
+    },
+    selected: {
+      deep: true,
+      handler: function (newVal) {
+          window.vrViewFn = () => {
+            try {
+              this.loadFilsh = true
+              if (this.isFirst) {
+                this.isFirst = false
+              }
+              setTimeout(() => {
+                this.loadFinish = true
+              }, 4000);
+            } catch (error) {
+              error;
+            }
+          };
+
+          var settings = {
+            "events[skin_events].onloadcomplete": "js(window.vrViewFn());",
+            "skin_settings.littleplanetintro":this.isFirst,
+            "view.vlookat": newVal.initVisual ? newVal.initVisual.vlookat : 0,
+            "view.hlookat": newVal.initVisual ? newVal.initVisual.hlookat : 0,
+          };
+
+
+          window.$("#pano").empty();
+          window.removepano("#pano");
+          window.embedpano({
+            // https://4dkk.4dage.com/720yun_fd_manage/fd720_FC5BmPHcV/vtour/tour.xml
+            // xml: "%HTMLPATH%/static/template/tour.xml",
+            xml: `https://4dkk.4dage.com/720yun_fd_manage/${newVal.sceneCode}/vtour/tour.xml`,
+            swf: `${this.g_CDN}resource/tour.swf`,
+            target: "pano",
+            html5: "auto",
+            mobilescale: 1,
+            vars: settings,
+            passQueryParameters: true,
+          });
+
+          // var krpano = document.getElementById("krpanoSWFObject");
+          // krpano.call(`loadscene('scene_${this.selectExh.id}__(${newVal.id})')`)
+          // setTimeout(() => {
+          //   if (newVal.view) {
+          //     console.log(newVal.view);
+          //     krpano.set("view.vlookat", newVal.view.vlookat || 0);
+          //     krpano.set("view.hlookat", newVal.view.hlookat || 0);
+          //   }
+          // });
+      }
+    }
+  },
+  methods: {
+    handleItem(item) {
+      if (this.loadFinish) {
+        this.selected = item
+      }
+    },
+    getList() {
+      // window.$.ajax({url:`code/pano/data.json`,success:(data)=>{
+      window.$.ajax({
+        url: `${this.g_CDN}pano/data.json`, success: (data) => {
+          this.list = data.list
+          if (this.exhibition) {
+            this.selectExh = this.list.find(item => item.id == this.exhibition)
+          } else {
+            this.selectExh = this.list[0]
+          }
+        }
+      })
+    }
+  },
+  mounted() {
+    this.getList()
+    this.$nextTick(() => {
+      let el1 = window.$(".clip-scroller > ul")
+      Array.from(el1).forEach(item => {
+        let frame1 = new window.PerfectScrollbar(item, {
+          useBothWheelAxes: true,
+          suppressScrollY: true,
+          wheelSpeed: 0.8,
+        });
+        window.$(item).data("scrollbar", frame1);
+      })
+    });
+  }
+};
+</script>
+<style lang="less" scoped>
+.ifrcon {
+  width: 100%;
+  height: 100%;
+  background: #fcfcfc;
+  text-align: center;
+
+  .pano {
+    width: 100%;
+    height: 100%;
+  }
+
+  .title {
+    --height: 40px;
+    position: fixed;
+    z-index: 99;
+    margin: 0;
+    height: var(--height);
+    line-height: var(--height);
+    font-size: 18px;
+    font-weight: 700;
+    color: #fff;
+    padding: 0 15px;
+    display: inline-block;
+    text-shadow: 1px 0 2px rgb(0 0 0 / 16%);
+    left: 50%;
+    -webkit-transform: translateX(-50%) translateY(0);
+    transform: translateX(-50%) translateY(0);
+    -webkit-transition: background 0.3s ease, min-width 0.3s ease,
+      border-radius 0.3s ease;
+    transition: background 0.3s ease, min-width 0.3s ease,
+      border-radius 0.3s ease;
+    width: 40%;
+    top: 20px;
+    background: -webkit-gradient(linear,
+        left top,
+        right top,
+        from(transparent),
+        color-stop(29%, rgba(0, 0, 0, 0.2)),
+        color-stop(69%, rgba(0, 0, 0, 0.2)),
+        to(transparent));
+    background: linear-gradient(90deg,
+        transparent,
+        rgba(0, 0, 0, 0.2) 29%,
+        rgba(0, 0, 0, 0.2) 69%,
+        transparent);
+    margin-top: 0;
+    text-align: center;
+  }
+
+  .uicon {
+    & /deep/ .btm-menu {
+      height: 250px;
+    }
+  }
+
+  .img_ul {
+    position: relative;
+    display: inline-block;
+    min-width: 50%;
+    max-width: 100%;
+
+    >ul {
+      display: inline-block;
+      white-space: nowrap;
+      background: linear-gradient(to right, rgba(32, 32, 32, 0), rgba(32, 32, 32, 1), rgba(32, 32, 32, 0));
+      width: 100%;
+
+      >li {
+        cursor: pointer;
+        list-style: none;
+        display: inline-block;
+        margin: 8px 10px;
+        position: relative;
+        padding-bottom: 8px;
+
+        >div {
+          width: 68px;
+          height: 68px;
+          overflow: hidden;
+          position: relative;
+          border-radius: 4px;
+          cursor: pointer;
+          color: rgba(256, 256, 256, 0.4);
+
+          >img {
+            position: absolute;
+            top: 50%;
+            left: 50%;
+            height: 100%;
+            transform: translate(-50%, -50%);
+          }
+
+          .iconfont {
+            position: absolute;
+            left: 4px;
+            top: 4px;
+            z-index: 99;
+          }
+
+          >span {
+            text-align: center;
+            display: inline-block;
+            background: rgba(0, 0, 0, 0.3);
+            position: absolute;
+            text-overflow: ellipsis;
+            overflow: hidden;
+            white-space: nowrap;
+            left: 0;
+            bottom: 0;
+            width: 100%;
+          }
+        }
+
+        .bar {
+          display: none;
+        }
+
+        .pic-name {
+          background: rgba(0, 0, 0, 0.6);
+          position: absolute;
+          left: 0;
+          bottom: 0;
+          text-align: center;
+
+          /deep/ span {
+            word-break: keep-all;
+            white-space: nowrap;
+            font-size: 12px;
+          }
+        }
+
+        &.active {
+          .bar {
+            display: inline-block;
+            position: absolute;
+            bottom: 0px;
+            width: 80%;
+            left: 50%;
+            transform: translateX(-50%);
+            height: 2px;
+            background: @color;
+          }
+
+          >div {
+            color: rgba(256, 256, 256, 1);
+          }
+        }
+      }
+    }
+  }
+
+  .txt_ul {
+    margin: 18px auto;
+    border: 2px solid @color;
+    border-radius: 30px;
+    padding: 6px 15px;
+    display: inline-block;
+    position: relative;
+    width: 80%;
+
+    >ul {
+      width: 100%;
+      display: inline-block;
+      white-space: nowrap;
+
+      >li {
+        border: 1px solid rgba(256, 256, 256, 0.4);
+        border-radius: 24px;
+        padding: 6px 9px;
+        margin: 0 5px;
+        cursor: pointer;
+        display: inline-block;
+
+        >span {
+          font-size: 16px;
+          display: inline-block;
+          vertical-align: middle;
+          line-height: 1.2;
+          word-break: keep-all;
+          color: rgba(256, 256, 256, 0.4);
+        }
+
+        &.active {
+          padding: 6px 12px;
+          border: 1px solid @color;
+
+          >span {
+            color: #fff;
+          }
+        }
+      }
+    }
+  }
+
+  .btn_zhankai {
+    position: fixed;
+    left: 50%;
+    bottom: 8px;
+    transform: translateX(-50%);
+    background: rgba(0, 0, 0, .3);
+    border-radius: 50%;
+    padding: 6px;
+    cursor: pointer;
+
+    >i {
+      font-size: 28px;
+      cursor: pointer;
+    }
+  }
+
+}
+</style>
+
+<style lang="less">
+.ps__thumb-x {
+  width: 0px !important;
+}
+</style>

+ 407 - 0
src/framework/show/pano.vue

@@ -0,0 +1,407 @@
+<template>
+  <div class="ifrcon">
+    <!-- 待完善 -->
+     <!--       :src="`https://airshow.4dkankan.com/spc.html?m=${selected.id}`" frameborder="0"></iframe>
+ -->
+    <iframe v-if="selectExh.type==='4dkk'" allowfullscreen="true" ref="iframe" :key="selected.id+selectExh.id"
+      :src="`https://www.4dkankan.com/spg.html?m=${selected.id}&hideNav`" frameborder="0"></iframe>
+    <div v-else id="pano" class="pano"></div>
+
+    <div v-if="selected && selectExh.type != '4dkk'" class="title">{{ selected.sceneTitle }}</div>
+    <mbui :type="type" :class="{ uicon: exhibition }" :isShow="isShowM" @close="isShowM = false">
+      <div class="img_ul clip-scroller" slot="imgList">
+        <ul>
+          <li v-for="(item, i) in currentScenes" @click="handleItem(item)" :key="i"
+            :class="{ active: selected.id == item.id }">
+            <div>
+              <img :src="item.icon" alt="" />
+              <rollName :offset="20" :active="selected.id == item.id" class="pic-name" :myref="'subw' + item.id"
+                :name="item.sceneTitle || item.title" />
+            </div>
+            <span class="bar"></span>
+          </li>
+        </ul>
+      </div>
+      <div class="txt_ul clip-scroller" slot="txtList" v-if="!exhibition">
+        <ul>
+          <li v-for="(item, i) in list" @click="selectExh = item" :key="i" :class="{ active: selectExh.id == item.id }">
+            <span>{{ item.title }}</span>
+          </li>
+        </ul>
+      </div>
+
+      <div v-if="!isShowM" @click="isShowM = true" class="btn_zhankai" slot="btn_zhankai">
+        <i class="iconfont icon-more"></i>
+      </div>
+      <vAside class="ui_header" slot="aside" />
+      <vSelect slot="select" v-if="!exhibition" :type="type"></vSelect>
+    </mbui>
+  </div>
+</template>
+
+<script>
+import mbui from "./ui";
+import vAside from "./ui/aside.vue";
+import vSelect from "./ui/select.vue";
+
+
+
+export default {
+  props: ['type', 'exhibition','area'],
+  components: {
+    mbui,
+    vSelect,
+    vAside
+  },
+  data() {
+    return {
+      params: "",
+      isShowM: true,
+      selected: {},
+      selectExh: {},
+      currentScenes: [],
+      list: [],
+      isFirst: true,
+      loadFinish: false
+    };
+  },
+  watch: {
+    selectExh: {
+      deep: true,
+      handler: function (newVal) {
+        if (newVal) {
+          this.isFirst = true
+          if (newVal.type === '4dkk') {
+            
+            this.selectExh = this.list.find(v=>v.id===newVal.id)
+            this.selected = this.selectExh.scenes[0]
+            this.currentScenes = this.selectExh.scenes.map(item => {
+              return {
+                ...item,
+                // 待完善
+                // icon: `https://4dkk.4dage.com/images/images${item.id}/floor_0.png?t=1667802021476?v=0&rnd=0.5813201205835572&x-oss-process=image/resize,m_fill,w_80,h_60/quality,q_70`
+                icon: `https://4dkk.4dage.com/scene_view_data/${item.id}/user/thumb-2k.jpg?_=5`
+              }
+            })
+            this.loadFinish = true
+          }
+          else {
+            window.$.ajax({
+              dataType: 'json',
+              url: `https://airshow.4dkankan.com/pano/${newVal.id}/someData.json?_=${Math.random()}`, success: (data) => {
+                this.selected = data.scenes[0]
+                this.currentScenes = data.scenes
+                this.loadFinish = false
+              }
+            })
+          }
+
+        }
+      }
+    },
+    selected: {
+      deep: true,
+      handler: function (newVal) {
+
+        window.vrViewFn = () => {
+          try {
+            this.loadFilsh = true
+            if (this.isFirst) {
+              this.isFirst = false
+            }
+            setTimeout(() => {
+              this.loadFinish = true
+            }, 4000);
+          } catch (error) {
+            error;
+          }
+        };
+
+        var settings = {
+          "events[skin_events].onloadcomplete": "js(window.vrViewFn());",
+          "skin_settings.littleplanetintro": this.isFirst,
+          "view.vlookat": newVal.initVisual ? newVal.initVisual.vlookat : 0,
+          "view.hlookat": newVal.initVisual ? newVal.initVisual.hlookat : 0,
+        };
+
+
+        window.$("#pano").empty();
+        window.removepano("#pano");
+
+        if (this.selectExh.type != '4dkk') {
+          window.embedpano({
+            // https://4dkk.4dage.com/720yun_fd_manage/fd720_FC5BmPHcV/vtour/tour.xml
+            // xml: "%HTMLPATH%/static/template/tour.xml",
+            xml: `https://airshow.4dkankan.com/pano/${this.selectExh.id}/${newVal.sceneCode}/vtour/tour.xml`,
+            swf: `${this.g_CDN}resource/tour.swf`,
+            target: "pano",
+            html5: "auto",
+            mobilescale: 1,
+            vars: settings,
+            passQueryParameters: true,
+          });
+        }
+
+      }
+    }
+  },
+  methods: {
+    handleItem(item) {
+      if (this.loadFinish) {
+        this.selected = item
+      }
+    },
+    getList() {
+      // window.$.ajax({url:`code/pano/data.json`,success:(data)=>{
+      window.$.ajax({
+        url: `${this.g_CDN}pano/data.json`, success: (data) => {
+          this.list = data.list
+          if (this.area) {
+            this.selectExh = this.list.find(item => item.id == this.area)
+          } else {
+            this.selectExh = this.list[0]
+          }
+        }
+      })
+    }
+  },
+  mounted() {
+    this.getList()
+    this.$nextTick(() => {
+      let el1 = window.$(".clip-scroller > ul")
+      Array.from(el1).forEach(item => {
+        let frame1 = new window.PerfectScrollbar(item, {
+          useBothWheelAxes: true,
+          suppressScrollY: true,
+          wheelSpeed: 0.8,
+        });
+        window.$(item).data("scrollbar", frame1);
+      })
+    });
+  }
+};
+</script>
+<style lang="less" scoped>
+.ifrcon {
+  width: 100%;
+  height: 100%;
+  background: #fcfcfc;
+  text-align: center;
+
+  >iframe {
+    width: 100%;
+    height: 100%;
+  }
+
+  .pano {
+    width: 100%;
+    height: 100%;
+  }
+
+  .title {
+    --height: 40px;
+    position: fixed;
+    z-index: 99;
+    margin: 0;
+    height: var(--height);
+    line-height: var(--height);
+    font-size: 18px;
+    font-weight: 700;
+    color: #fff;
+    padding: 0 15px;
+    display: inline-block;
+    text-shadow: 1px 0 2px rgb(0 0 0 / 16%);
+    left: 50%;
+    -webkit-transform: translateX(-50%) translateY(0);
+    transform: translateX(-50%) translateY(0);
+    -webkit-transition: background 0.3s ease, min-width 0.3s ease,
+      border-radius 0.3s ease;
+    transition: background 0.3s ease, min-width 0.3s ease,
+      border-radius 0.3s ease;
+    width: 40%;
+    top: 20px;
+    background: -webkit-gradient(linear,
+        left top,
+        right top,
+        from(transparent),
+        color-stop(29%, rgba(0, 0, 0, 0.2)),
+        color-stop(69%, rgba(0, 0, 0, 0.2)),
+        to(transparent));
+    background: linear-gradient(90deg,
+        transparent,
+        rgba(0, 0, 0, 0.2) 29%,
+        rgba(0, 0, 0, 0.2) 69%,
+        transparent);
+    margin-top: 0;
+    text-align: center;
+  }
+
+  .uicon {
+    & /deep/ .btm-menu {
+      height: 250px;
+    }
+  }
+
+  .img_ul {
+    position: relative;
+    display: inline-block;
+    min-width: 50%;
+    max-width: 100%;
+
+    >ul {
+      display: inline-block;
+      white-space: nowrap;
+      background: linear-gradient(to right, rgba(32, 32, 32, 0), rgba(32, 32, 32, 1), rgba(32, 32, 32, 0));
+      width: 100%;
+
+      >li {
+        cursor: pointer;
+        list-style: none;
+        display: inline-block;
+        margin: 8px 10px;
+        position: relative;
+        padding-bottom: 8px;
+
+        >div {
+          width: 68px;
+          height: 68px;
+          overflow: hidden;
+          position: relative;
+          border-radius: 4px;
+          cursor: pointer;
+          color: rgba(256, 256, 256, 0.4);
+
+          >img {
+            position: absolute;
+            top: 50%;
+            left: 50%;
+            height: 100%;
+            transform: translate(-50%, -50%);
+          }
+
+          .iconfont {
+            position: absolute;
+            left: 4px;
+            top: 4px;
+            z-index: 99;
+          }
+
+          >span {
+            text-align: center;
+            display: inline-block;
+            background: rgba(0, 0, 0, 0.3);
+            position: absolute;
+            text-overflow: ellipsis;
+            overflow: hidden;
+            white-space: nowrap;
+            left: 0;
+            bottom: 0;
+            width: 100%;
+          }
+        }
+
+        .bar {
+          display: none;
+        }
+
+        .pic-name {
+          background: rgba(0, 0, 0, 0.6);
+          position: absolute;
+          left: 0;
+          bottom: 0;
+          text-align: center;
+
+          /deep/ span {
+            word-break: keep-all;
+            white-space: nowrap;
+            font-size: 12px;
+          }
+        }
+
+        &.active {
+          .bar {
+            display: inline-block;
+            position: absolute;
+            bottom: 0px;
+            width: 80%;
+            left: 50%;
+            transform: translateX(-50%);
+            height: 2px;
+            background: @color;
+          }
+
+          >div {
+            color: rgba(256, 256, 256, 1);
+          }
+        }
+      }
+    }
+  }
+
+  .txt_ul {
+    margin: 18px auto;
+    border: 2px solid @color;
+    border-radius: 30px;
+    padding: 6px 15px;
+    display: block;
+    position: relative;
+    max-width: 864px;
+
+    >ul {
+      width: 100%;
+      display: inline-block;
+      white-space: nowrap;
+
+      >li {
+        border: 1px solid rgba(256, 256, 256, 0.4);
+        border-radius: 24px;
+        padding: 6px 9px;
+        margin: 0 5px;
+        cursor: pointer;
+        display: inline-block;
+
+        >span {
+          font-size: 16px;
+          display: inline-block;
+          vertical-align: middle;
+          line-height: 1.2;
+          word-break: keep-all;
+          color: rgba(256, 256, 256, 0.4);
+        }
+
+        &.active {
+          padding: 6px 12px;
+          border: 1px solid @color;
+
+          >span {
+            color: #fff;
+          }
+        }
+      }
+    }
+  }
+
+  .btn_zhankai {
+    position: fixed;
+    left: 50%;
+    bottom: 8px;
+    transform: translateX(-50%);
+    background: rgba(0, 0, 0, .3);
+    border-radius: 50%;
+    padding: 6px;
+    cursor: pointer;
+
+    >i {
+      font-size: 28px;
+      cursor: pointer;
+    }
+  }
+
+}
+</style>
+
+<style lang="less">
+.ps__thumb-x {
+  width: 0px !important;
+}
+</style>

+ 97 - 0
src/framework/show/popup/imgview.vue

@@ -0,0 +1,97 @@
+<template>
+  <div class="imgcon">
+    <img @click.stop class="v-image" v-for="(item,i) in image" :key="i" preview="0" :src="item.icon" />
+  </div>
+</template>
+
+<script>
+export default {
+  props:['image'],
+  data(){
+    return {
+      current:0
+    }
+  },
+  mounted(){
+    setTimeout(() => {
+      let img = $('.v-image')[0]
+      img.click()
+    });
+
+    //图片查看器打开后,打印本次查看器的实例(事件、方法、属性的示例)
+    this.$preview.on('close',(e,item)=>{
+      this.$emit('close')
+    })
+    
+  },
+  methods:{
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.imgcon{
+  .v-image{
+    width: 100%;
+    height: 540px;
+  }
+  .toLeft,.toRight{
+    font-size: 0;
+    top: 50%;
+    left: 10px;
+    transform: translateY(-50%);
+    z-index: 99;
+    cursor: pointer;
+    position: absolute;
+    color: #fff;
+    width: 52px;
+    height: 52px;
+    background: rgba(0, 0, 0, 0.5);
+    padding: 14px;
+    >img{
+      width: 100%;
+      height: 100%;
+      cursor: pointer;
+    }
+  }
+  .toRight{
+    left: auto;
+    right: 10px;
+  }
+  .scale{
+      font-size: 0;
+      bottom: 10px;
+      right: 10px;
+      z-index: 99;
+      cursor: pointer;
+      position: absolute;
+      color: #fff;
+      width: 36px;
+      height: 36px;
+      background: rgba(0, 0, 0, 0.5);
+      padding: 10px;
+      border: 1px solid rgba(255, 255, 255, 0.2);
+      border-radius: 18px;
+      >img{
+        width: 100%;
+        height: 100%;
+        cursor: pointer;
+      }
+    }
+  .btmdot{
+    height: 28px;
+    line-height: 28px;
+    padding: 0 20px;
+    font-size: 14px;
+    color: #fff;
+    background: rgba(0, 0, 0, 0.3);
+    border-radius: 14px;
+    position: absolute;
+    letter-spacing: 1px;
+    transform: translateX(-50%);
+    left: 50%;
+    z-index: 999;
+    bottom: 16px;
+  }
+}
+</style>

+ 0 - 0
src/framework/show/popup/index.vue


Some files were not shown because too many files changed in this diff