shaogen1995 9 часов назад
Родитель
Сommit
37a3f742e8

+ 153 - 40
project/package-lock.json

@@ -25,8 +25,7 @@
         "classnames": "^2.5.1",
         "crypto-js": "^4.2.0",
         "d3": "^7.9.0",
-        "pdfh5": "^3.0.0",
-        "pdfjs-dist": "3.11.174",
+        "media-chrome": "^4.15.1",
         "react": "^18.2.0",
         "react-dom": "^18.2.0",
         "react-redux": "^8.0.4",
@@ -37,6 +36,7 @@
         "redux-devtools-extension": "^2.13.9",
         "redux-thunk": "^2.4.1",
         "sass": "^1.55.0",
+        "swiper": "^11.2.10",
         "typescript": "^4.8.4",
         "vconsole": "^3.15.1",
         "web-vitals": "^2.1.4"
@@ -2991,6 +2991,7 @@
       "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
       "license": "BSD-3-Clause",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "detect-libc": "^2.0.0",
         "https-proxy-agent": "^5.0.0",
@@ -5027,7 +5028,8 @@
       "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-1.1.1.tgz",
       "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
       "license": "ISC",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "node_modules/accepts": {
       "version": "1.3.8",
@@ -5403,7 +5405,8 @@
       "resolved": "https://registry.npmmirror.com/aproba/-/aproba-2.1.0.tgz",
       "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==",
       "license": "ISC",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "node_modules/are-we-there-yet": {
       "version": "2.0.0",
@@ -5412,6 +5415,7 @@
       "deprecated": "This package is no longer supported.",
       "license": "ISC",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "delegates": "^1.0.0",
         "readable-stream": "^3.6.0"
@@ -6159,6 +6163,7 @@
       "hasInstallScript": true,
       "license": "MIT",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "@mapbox/node-pre-gyp": "^1.0.0",
         "nan": "^2.17.0",
@@ -6176,6 +6181,15 @@
         "node": ">=4"
       }
     },
+    "node_modules/ce-la-react": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmmirror.com/ce-la-react/-/ce-la-react-0.3.2.tgz",
+      "integrity": "sha512-QJ6k4lOD/btI08xG8jBPxRCGXvCnusGGkTsiXk0u3NqUu/W+BXRnFD4PYjwtqh8AWmGa5LDbGk0fLQsqr0nSMA==",
+      "license": "BSD-3-Clause",
+      "peerDependencies": {
+        "react": ">=17.0.0"
+      }
+    },
     "node_modules/chalk": {
       "version": "2.4.2",
       "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz",
@@ -6239,6 +6253,7 @@
       "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
       "license": "ISC",
       "optional": true,
+      "peer": true,
       "engines": {
         "node": ">=10"
       }
@@ -6342,6 +6357,7 @@
       "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
       "license": "ISC",
       "optional": true,
+      "peer": true,
       "bin": {
         "color-support": "bin.js"
       }
@@ -6467,7 +6483,8 @@
       "resolved": "https://registry.npmmirror.com/console-control-strings/-/console-control-strings-1.1.0.tgz",
       "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
       "license": "ISC",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "node_modules/content-disposition": {
       "version": "0.5.4",
@@ -7421,6 +7438,7 @@
       "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
       "license": "MIT",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "mimic-response": "^2.0.0"
       },
@@ -7531,7 +7549,8 @@
       "resolved": "https://registry.npmmirror.com/delegates/-/delegates-1.0.0.tgz",
       "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
       "license": "MIT",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "node_modules/depd": {
       "version": "2.0.0",
@@ -7556,6 +7575,7 @@
       "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
       "license": "Apache-2.0",
       "optional": true,
+      "peer": true,
       "engines": {
         "node": ">=8"
       }
@@ -9297,6 +9317,7 @@
       "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
       "license": "ISC",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "minipass": "^3.0.0"
       },
@@ -9310,6 +9331,7 @@
       "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
       "license": "ISC",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "yallist": "^4.0.0"
       },
@@ -9375,6 +9397,7 @@
       "deprecated": "This package is no longer supported.",
       "license": "ISC",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "aproba": "^1.0.3 || ^2.0.0",
         "color-support": "^1.1.2",
@@ -9674,7 +9697,8 @@
       "resolved": "https://registry.npmmirror.com/has-unicode/-/has-unicode-2.0.1.tgz",
       "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
       "license": "ISC",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "node_modules/hasown": {
       "version": "2.0.2",
@@ -12723,6 +12747,15 @@
       "resolved": "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.4.tgz",
       "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA=="
     },
+    "node_modules/media-chrome": {
+      "version": "4.18.0",
+      "resolved": "https://registry.npmmirror.com/media-chrome/-/media-chrome-4.18.0.tgz",
+      "integrity": "sha512-OQmpUCeMMWtUcbar3CiY7V0S6j43HaDhwa6uRUyYiWdfPIj3riWp0agu3x6EcIlDRFIf8iDGZiGeb26ll+mz0g==",
+      "license": "MIT",
+      "dependencies": {
+        "ce-la-react": "^0.3.2"
+      }
+    },
     "node_modules/media-typer": {
       "version": "0.3.0",
       "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz",
@@ -12824,6 +12857,7 @@
       "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
       "license": "MIT",
       "optional": true,
+      "peer": true,
       "engines": {
         "node": ">=8"
       },
@@ -12921,6 +12955,7 @@
       "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
       "license": "ISC",
       "optional": true,
+      "peer": true,
       "engines": {
         "node": ">=8"
       }
@@ -12931,6 +12966,7 @@
       "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
       "license": "MIT",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "minipass": "^3.0.0",
         "yallist": "^4.0.0"
@@ -12945,6 +12981,7 @@
       "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
       "license": "ISC",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "yallist": "^4.0.0"
       },
@@ -12990,7 +13027,8 @@
       "resolved": "https://registry.npmmirror.com/nan/-/nan-2.24.0.tgz",
       "integrity": "sha512-Vpf9qnVW1RaDkoNKFUvfxqAbtI8ncb8OJlqZ9wwpXzWPEsvsB1nvdUi6oYrHIkQ1Y/tMDnr1h4nczS0VB9Xykg==",
       "license": "MIT",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "node_modules/nanoid": {
       "version": "3.3.4",
@@ -13036,6 +13074,7 @@
       "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
       "license": "MIT",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "whatwg-url": "^5.0.0"
       },
@@ -13056,14 +13095,16 @@
       "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz",
       "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
       "license": "MIT",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "node_modules/node-fetch/node_modules/webidl-conversions": {
       "version": "3.0.1",
       "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
       "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
       "license": "BSD-2-Clause",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "node_modules/node-fetch/node_modules/whatwg-url": {
       "version": "5.0.0",
@@ -13071,6 +13112,7 @@
       "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
       "license": "MIT",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "tr46": "~0.0.3",
         "webidl-conversions": "^3.0.0"
@@ -13100,6 +13142,7 @@
       "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
       "license": "ISC",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "abbrev": "1"
       },
@@ -13152,6 +13195,7 @@
       "deprecated": "This package is no longer supported.",
       "license": "ISC",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "are-we-there-yet": "^2.0.0",
         "console-control-strings": "^1.1.0",
@@ -13507,21 +13551,17 @@
       "integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==",
       "license": "MIT",
       "optional": true,
+      "peer": true,
       "engines": {
         "node": ">=8"
       }
     },
-    "node_modules/pdfh5": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmmirror.com/pdfh5/-/pdfh5-3.0.0.tgz",
-      "integrity": "sha512-R1cmlbbxJQP0S7CqbLR9+pSQ7nmCTH/VAjvqhXZErxgaJ1h4K2fj5V600sQPF+fMXc636E+GlqJdQPG4ur+vkw==",
-      "license": "MIT"
-    },
     "node_modules/pdfjs-dist": {
       "version": "3.11.174",
       "resolved": "https://registry.npmmirror.com/pdfjs-dist/-/pdfjs-dist-3.11.174.tgz",
       "integrity": "sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==",
       "license": "Apache-2.0",
+      "peer": true,
       "engines": {
         "node": ">=18"
       },
@@ -16680,7 +16720,8 @@
       "resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz",
       "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
       "license": "ISC",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "node_modules/setprototypeof": {
       "version": "1.2.0",
@@ -16745,7 +16786,8 @@
         }
       ],
       "license": "MIT",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "node_modules/simple-get": {
       "version": "3.1.1",
@@ -16753,6 +16795,7 @@
       "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
       "license": "MIT",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "decompress-response": "^4.2.0",
         "once": "^1.3.1",
@@ -17239,6 +17282,25 @@
         "boolbase": "~1.0.0"
       }
     },
+    "node_modules/swiper": {
+      "version": "11.2.10",
+      "resolved": "https://registry.npmmirror.com/swiper/-/swiper-11.2.10.tgz",
+      "integrity": "sha512-RMeVUUjTQH+6N3ckimK93oxz6Sn5la4aDlgPzB+rBrG/smPdCTicXyhxa+woIpopz+jewEloiEE3lKo1h9w2YQ==",
+      "funding": [
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/swiperjs"
+        },
+        {
+          "type": "open_collective",
+          "url": "http://opencollective.com/swiper"
+        }
+      ],
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4.7.0"
+      }
+    },
     "node_modules/symbol-tree": {
       "version": "3.2.4",
       "resolved": "https://registry.npmmirror.com/symbol-tree/-/symbol-tree-3.2.4.tgz",
@@ -17303,6 +17365,7 @@
       "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
       "license": "ISC",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "chownr": "^2.0.0",
         "fs-minipass": "^2.0.0",
@@ -17321,6 +17384,7 @@
       "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
       "license": "MIT",
       "optional": true,
+      "peer": true,
       "bin": {
         "mkdirp": "bin/cmd.js"
       },
@@ -18320,6 +18384,7 @@
       "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
       "license": "ISC",
       "optional": true,
+      "peer": true,
       "dependencies": {
         "string-width": "^1.0.2 || 2 || 3 || 4"
       }
@@ -20841,6 +20906,7 @@
       "resolved": "https://registry.npmmirror.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
       "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
       "optional": true,
+      "peer": true,
       "requires": {
         "detect-libc": "^2.0.0",
         "https-proxy-agent": "^5.0.0",
@@ -22463,7 +22529,8 @@
       "version": "1.1.1",
       "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-1.1.1.tgz",
       "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "accepts": {
       "version": "1.3.8",
@@ -22763,13 +22830,15 @@
       "version": "2.1.0",
       "resolved": "https://registry.npmmirror.com/aproba/-/aproba-2.1.0.tgz",
       "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "are-we-there-yet": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
       "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
       "optional": true,
+      "peer": true,
       "requires": {
         "delegates": "^1.0.0",
         "readable-stream": "^3.6.0"
@@ -23370,6 +23439,7 @@
       "resolved": "https://registry.npmmirror.com/canvas/-/canvas-2.11.2.tgz",
       "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==",
       "optional": true,
+      "peer": true,
       "requires": {
         "@mapbox/node-pre-gyp": "^1.0.0",
         "nan": "^2.17.0",
@@ -23381,6 +23451,12 @@
       "resolved": "https://registry.npmmirror.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz",
       "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw=="
     },
+    "ce-la-react": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmmirror.com/ce-la-react/-/ce-la-react-0.3.2.tgz",
+      "integrity": "sha512-QJ6k4lOD/btI08xG8jBPxRCGXvCnusGGkTsiXk0u3NqUu/W+BXRnFD4PYjwtqh8AWmGa5LDbGk0fLQsqr0nSMA==",
+      "requires": {}
+    },
     "chalk": {
       "version": "2.4.2",
       "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz",
@@ -23430,7 +23506,8 @@
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz",
       "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "chrome-trace-event": {
       "version": "1.0.3",
@@ -23514,7 +23591,8 @@
       "version": "1.1.3",
       "resolved": "https://registry.npmmirror.com/color-support/-/color-support-1.1.3.tgz",
       "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "colord": {
       "version": "2.9.3",
@@ -23620,7 +23698,8 @@
       "version": "1.1.0",
       "resolved": "https://registry.npmmirror.com/console-control-strings/-/console-control-strings-1.1.0.tgz",
       "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "content-disposition": {
       "version": "0.5.4",
@@ -24292,6 +24371,7 @@
       "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-4.2.1.tgz",
       "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
       "optional": true,
+      "peer": true,
       "requires": {
         "mimic-response": "^2.0.0"
       }
@@ -24384,7 +24464,8 @@
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/delegates/-/delegates-1.0.0.tgz",
       "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "depd": {
       "version": "2.0.0",
@@ -24400,7 +24481,8 @@
       "version": "2.1.2",
       "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz",
       "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "detect-newline": {
       "version": "3.1.0",
@@ -25752,6 +25834,7 @@
       "resolved": "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz",
       "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
       "optional": true,
+      "peer": true,
       "requires": {
         "minipass": "^3.0.0"
       },
@@ -25761,6 +25844,7 @@
           "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz",
           "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
           "optional": true,
+          "peer": true,
           "requires": {
             "yallist": "^4.0.0"
           }
@@ -25809,6 +25893,7 @@
       "resolved": "https://registry.npmmirror.com/gauge/-/gauge-3.0.2.tgz",
       "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
       "optional": true,
+      "peer": true,
       "requires": {
         "aproba": "^1.0.3 || ^2.0.0",
         "color-support": "^1.1.2",
@@ -26029,7 +26114,8 @@
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/has-unicode/-/has-unicode-2.0.1.tgz",
       "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "hasown": {
       "version": "2.0.2",
@@ -28409,6 +28495,14 @@
       "resolved": "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.4.tgz",
       "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA=="
     },
+    "media-chrome": {
+      "version": "4.18.0",
+      "resolved": "https://registry.npmmirror.com/media-chrome/-/media-chrome-4.18.0.tgz",
+      "integrity": "sha512-OQmpUCeMMWtUcbar3CiY7V0S6j43HaDhwa6uRUyYiWdfPIj3riWp0agu3x6EcIlDRFIf8iDGZiGeb26ll+mz0g==",
+      "requires": {
+        "ce-la-react": "^0.3.2"
+      }
+    },
     "media-typer": {
       "version": "0.3.0",
       "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz",
@@ -28478,7 +28572,8 @@
       "version": "2.1.0",
       "resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-2.1.0.tgz",
       "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "min-indent": {
       "version": "1.0.1",
@@ -28552,13 +28647,15 @@
       "version": "5.0.0",
       "resolved": "https://registry.npmmirror.com/minipass/-/minipass-5.0.0.tgz",
       "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "minizlib": {
       "version": "2.1.2",
       "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz",
       "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
       "optional": true,
+      "peer": true,
       "requires": {
         "minipass": "^3.0.0",
         "yallist": "^4.0.0"
@@ -28569,6 +28666,7 @@
           "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz",
           "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
           "optional": true,
+          "peer": true,
           "requires": {
             "yallist": "^4.0.0"
           }
@@ -28606,7 +28704,8 @@
       "version": "2.24.0",
       "resolved": "https://registry.npmmirror.com/nan/-/nan-2.24.0.tgz",
       "integrity": "sha512-Vpf9qnVW1RaDkoNKFUvfxqAbtI8ncb8OJlqZ9wwpXzWPEsvsB1nvdUi6oYrHIkQ1Y/tMDnr1h4nczS0VB9Xykg==",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "nanoid": {
       "version": "3.3.4",
@@ -28642,6 +28741,7 @@
       "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz",
       "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
       "optional": true,
+      "peer": true,
       "requires": {
         "whatwg-url": "^5.0.0"
       },
@@ -28650,19 +28750,22 @@
           "version": "0.0.3",
           "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz",
           "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
-          "optional": true
+          "optional": true,
+          "peer": true
         },
         "webidl-conversions": {
           "version": "3.0.1",
           "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
           "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
-          "optional": true
+          "optional": true,
+          "peer": true
         },
         "whatwg-url": {
           "version": "5.0.0",
           "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz",
           "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
           "optional": true,
+          "peer": true,
           "requires": {
             "tr46": "~0.0.3",
             "webidl-conversions": "^3.0.0"
@@ -28690,6 +28793,7 @@
       "resolved": "https://registry.npmmirror.com/nopt/-/nopt-5.0.0.tgz",
       "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
       "optional": true,
+      "peer": true,
       "requires": {
         "abbrev": "1"
       }
@@ -28722,6 +28826,7 @@
       "resolved": "https://registry.npmmirror.com/npmlog/-/npmlog-5.0.1.tgz",
       "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
       "optional": true,
+      "peer": true,
       "requires": {
         "are-we-there-yet": "^2.0.0",
         "console-control-strings": "^1.1.0",
@@ -29000,17 +29105,14 @@
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz",
       "integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==",
-      "optional": true
-    },
-    "pdfh5": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmmirror.com/pdfh5/-/pdfh5-3.0.0.tgz",
-      "integrity": "sha512-R1cmlbbxJQP0S7CqbLR9+pSQ7nmCTH/VAjvqhXZErxgaJ1h4K2fj5V600sQPF+fMXc636E+GlqJdQPG4ur+vkw=="
+      "optional": true,
+      "peer": true
     },
     "pdfjs-dist": {
       "version": "3.11.174",
       "resolved": "https://registry.npmmirror.com/pdfjs-dist/-/pdfjs-dist-3.11.174.tgz",
       "integrity": "sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==",
+      "peer": true,
       "requires": {
         "canvas": "^2.11.2",
         "path2d-polyfill": "^2.0.1"
@@ -31246,7 +31348,8 @@
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz",
       "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "setprototypeof": {
       "version": "1.2.0",
@@ -31290,13 +31393,15 @@
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/simple-concat/-/simple-concat-1.0.1.tgz",
       "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
-      "optional": true
+      "optional": true,
+      "peer": true
     },
     "simple-get": {
       "version": "3.1.1",
       "resolved": "https://registry.npmmirror.com/simple-get/-/simple-get-3.1.1.tgz",
       "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
       "optional": true,
+      "peer": true,
       "requires": {
         "decompress-response": "^4.2.0",
         "once": "^1.3.1",
@@ -31699,6 +31804,11 @@
         }
       }
     },
+    "swiper": {
+      "version": "11.2.10",
+      "resolved": "https://registry.npmmirror.com/swiper/-/swiper-11.2.10.tgz",
+      "integrity": "sha512-RMeVUUjTQH+6N3ckimK93oxz6Sn5la4aDlgPzB+rBrG/smPdCTicXyhxa+woIpopz+jewEloiEE3lKo1h9w2YQ=="
+    },
     "symbol-tree": {
       "version": "3.2.4",
       "resolved": "https://registry.npmmirror.com/symbol-tree/-/symbol-tree-3.2.4.tgz",
@@ -31751,6 +31861,7 @@
       "resolved": "https://registry.npmmirror.com/tar/-/tar-6.2.1.tgz",
       "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
       "optional": true,
+      "peer": true,
       "requires": {
         "chownr": "^2.0.0",
         "fs-minipass": "^2.0.0",
@@ -31764,7 +31875,8 @@
           "version": "1.0.4",
           "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz",
           "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
-          "optional": true
+          "optional": true,
+          "peer": true
         }
       }
     },
@@ -32535,6 +32647,7 @@
       "resolved": "https://registry.npmmirror.com/wide-align/-/wide-align-1.1.5.tgz",
       "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
       "optional": true,
+      "peer": true,
       "requires": {
         "string-width": "^1.0.2 || 2 || 3 || 4"
       }

+ 1 - 1
project/public/index.html

@@ -11,7 +11,7 @@
     <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
     <link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
     <script src="./myData/myData.js"></script>
-    <title>title</title>
+    <title>革命领袖视察黑龙江纪念馆</title>
   </head>
 
   <body>

+ 326 - 0
project/public/myData/three/PanoramaControls.js

@@ -0,0 +1,326 @@
+
+function PanoramaControls(camera, domElement) {
+
+  
+    // fyz 相机放大缩小
+    this.activationThreshold = 1.1;
+    this.scrollZoomSpeed = 0.08;
+    this.scrollZoomSta = true;
+    this.zoomMin = 0.7;
+    this.zoomMax = 1.5;
+    this.baseFov = 70;
+ 
+    this.camera = camera;
+    this.camera.fov = this.baseFov;
+     
+    this.domElement = domElement; 
+    this.camera.controls = this; 
+    this.enabled = true;
+
+    this.target = new THREE.Vector3(0, 0, 0);
+    this.lookVector = new THREE.Vector3;
+    this.aimFrom = this.camera.position;
+
+
+    this.lat = 0;
+    this.latMin = -60//-40;
+    this.latMax = 60//40;
+    this.lon = 0;
+    this.phi = 0;
+    this.theta = 0;
+    this.lookSpeed = 0.05;
+    this.rotationAcc = new THREE.Vector2;
+    this.rotationSpeed = new THREE.Vector2;
+    this.rotationHistory = [];
+    this.rotationDifference = new THREE.Vector2;
+
+
+    this.pointerDragOn = !1;
+    this.pointer = new THREE.Vector3(0, 0, -1);
+    this.pointerDragStart = new THREE.Vector3(0, 0, -1); 
+    this._wheel = 0;
+    this.zoomLevel = 1; 
+    this.translationWorldDelta = new THREE.Vector3
+    this.bindEvents()
+}
+
+PanoramaControls.prototype.bindEvents = function() {
+
+    window.addEventListener("mousemove", this.onMouseMove.bind(this));
+    this.domElement.addEventListener("mousedown", this.onMouseDown.bind(this));
+    window.addEventListener("mouseup", this.onMouseUp.bind(this));
+    this.domElement.addEventListener("mouseover", (event) => this.pointerDragOn && 0 === event.which && this.onMouseUp(event));
+
+    this.domElement.addEventListener("touchstart", this.onTouchStart.bind(this));
+    this.domElement.addEventListener("touchmove", this.onTouchMove.bind(this));
+    this.domElement.addEventListener("touchend", this.onTouchEnd.bind(this));
+
+    this.domElement.addEventListener("wheel", this.onMouseWheel.bind(this));   // fyz wheel事件代替mousewheel事件
+    this.domElement.addEventListener("DOMMouseScroll", this.onMouseWheel.bind(this));
+    this.domElement.addEventListener("contextmenu", (event) => event.preventDefault());
+
+    //document.addEventListener("keydown", this.onKeyDown.bind(this));
+    //document.addEventListener("keyup", this.onKeyUp.bind(this));
+
+}
+PanoramaControls.prototype.lookAt = function(point) {
+ 
+
+    var directionNegative = this.camera.position.clone().sub(point),
+        theta = Math.atan(directionNegative.z / directionNegative.x);
+
+    theta += directionNegative.x < 0 ? Math.PI : 0;
+    theta += directionNegative.x > 0 && directionNegative.z < 0 ? 2 * Math.PI : 0;
+    this.lon = THREE.Math.radToDeg(theta) + 180;
+
+    let projectorR = Math.sqrt(directionNegative.x * directionNegative.x + directionNegative.z * directionNegative.z),
+        phi = Math.atan(directionNegative.y / projectorR);
+
+    this.lat = -THREE.Math.radToDeg(phi)
+}
+PanoramaControls.prototype.startRotationFrom = function(screenX, screenY) {
+
+    this.updatePointer(screenX, screenY);
+    this.pointerDragOn = true;
+    this.pointerDragStart.copy(this.pointer);
+    //TODO
+    //this.pointerDragStartIntersect = this.player.getMouseIntersect(this.pointer.clone(), [this.scene.skybox]).point;
+    this.rotationHistory = [];
+    this.rotationSpeed.set(0, 0);
+}
+PanoramaControls.prototype.onTouchStart = function(event) {
+
+    if (this.enabled) {
+
+        event.preventDefault();
+        event.stopPropagation();
+        this.startRotationFrom(event.changedTouches[0].clientX, event.changedTouches[0].clientY);
+    }
+
+}
+PanoramaControls.prototype.onMouseDown = function(event) {
+
+    if (this.enabled) {
+
+        event.preventDefault();
+        event.stopPropagation()
+
+        switch (event.button) {
+
+            case 0:
+                this.startRotationFrom(event.clientX, event.clientY);
+                break;
+            case 2:
+
+        }
+    }
+}
+
+PanoramaControls.prototype.updateRotation = function( ) {
+
+
+    if (this.enabled && this.pointerDragOn) {
+
+        var pointerDragStart3D = new THREE.Vector3(this.pointerDragStart.x, this.pointerDragStart.y, 1).unproject(this.camera);
+        var pointer3D = new THREE.Vector3(this.pointer.x, this.pointer.y, 1).unproject(this.camera);
+
+            //两交互点分别到原点的长度
+        var pointerDragStart3DLength = Math.sqrt(pointerDragStart3D.x * pointerDragStart3D.x + pointerDragStart3D.z * pointerDragStart3D.z);
+        var pointer3DLength = Math.sqrt(pointer3D.x * pointer3D.x + pointer3D.z * pointer3D.z);
+
+            //通过Math.atan2计算在XY面上与X轴的夹角弧度。
+            //注:因为 z = -1,所以两者到原点的长度近似为x分量(数值的大小也不需要绝对对应)
+        var anglePointerDragStart3DToX = Math.atan2(pointerDragStart3D.y, pointerDragStart3DLength);       //近似为 anglePointerDragStart3DToX = Math.atan2( pointerDragStart3D.y, pointerDragStart3D.x ) 
+        var anglePointer3DToX = Math.atan2(pointer3D.y, pointer3DLength);                                 //近似为 anglePointer3DToX = Math.atan2( pointer3D.y, pointer3D.x )
+
+        //算出两者角度差,作为竖直方向角度差值(rotationDifference.y)
+        this.rotationDifference.y = THREE.Math.radToDeg(anglePointerDragStart3DToX - anglePointer3DToX);
+
+
+        //y分量清零,原向量等价于在XZ轴上的投影向量
+        pointerDragStart3D.y = 0;
+        pointer3D.y = 0;
+
+        //归一化(/length),求两者夹角作为
+        //判断方向,最后记为水平方向角度差值(rotationDifference.x)
+        var anglePointerDragStart3DToPointer3D = Math.acos(pointerDragStart3D.dot(pointer3D) / pointerDragStart3D.length() / pointer3D.length());
+
+        if (!isNaN(anglePointerDragStart3DToPointer3D)) {
+            this.rotationDifference.x = THREE.Math.radToDeg(anglePointerDragStart3DToPointer3D);
+            if (this.pointerDragStart.x < this.pointer.x) {
+                this.rotationDifference.x *= -1;
+            }
+        }
+
+        //更新pointerDragStart记录当前帧坐标,用于下一帧求帧差值
+        this.pointerDragStart.copy(this.pointer);
+    }
+}
+PanoramaControls.prototype.onMouseMove = function(event) {
+     
+    this.updatePointer(event.clientX, event.clientY);
+
+}
+PanoramaControls.prototype.onTouchMove = function(event) {
+
+    this.updatePointer(event.changedTouches[0].clientX, event.changedTouches[0].clientY)
+
+}
+
+PanoramaControls.prototype.updatePointer = function(screenX, screenY) {
+    this.pointer.x = screenX / this.domElement.clientWidth * 2 - 1;   // 屏幕坐标换算相对于canvas的父级
+    this.pointer.y = 2 * -(screenY / this.domElement.clientHeight) + 1;
+
+}
+PanoramaControls.prototype.endRotation = function() {
+
+
+    this.pointerDragOn = false;
+    try{
+        var rotationHistoryAverage = averageVectors(this.rotationHistory);
+    }catch(e){
+        console.error(e)
+    } 
+    
+    this.rotationSpeed.set(rotationHistoryAverage.x * 30, rotationHistoryAverage.y * 30);
+
+}
+PanoramaControls.prototype.onTouchEnd = function(event) {
+
+    if (this.enabled) {
+
+        event.preventDefault();
+        event.stopPropagation();
+        this.endRotation()
+    }
+}
+PanoramaControls.prototype.onMouseUp = function(event) {
+
+
+    if (this.enabled) {
+
+        event.preventDefault();
+        event.stopPropagation();
+        this.endRotation()
+    }
+}
+PanoramaControls.prototype.update = function(deltaTime) {
+
+    if (this.enabled) {
+
+        this.updateRotation();
+
+        for (this.rotationHistory.push(this.rotationDifference.clone()); this.rotationHistory.length > 5;) {
+
+            this.rotationHistory.shift();
+        }
+
+        this.lon += this.rotationDifference.x;
+        this.lat += this.rotationDifference.y;
+        this.rotationDifference.set(0, 0);
+        this.rotationSpeed.x = this.rotationSpeed.x * (1 - 0.05) + this.rotationAcc.x * 4.5;
+        this.rotationSpeed.y = this.rotationSpeed.y * (1 - 0.05) + this.rotationAcc.y * 4.5;
+
+        this.lon += this.rotationSpeed.x * deltaTime;
+        this.lat += this.rotationSpeed.y * deltaTime;
+
+      
+
+        this.lat = Math.max(this.latMin, Math.min(this.latMax, this.lat));
+        this.phi = THREE.Math.degToRad(90 - this.lat);
+        this.theta = THREE.Math.degToRad(this.lon);
+
+        this.lookVector.x = Math.sin(this.phi) * Math.cos(this.theta);
+        this.lookVector.y = Math.cos(this.phi);
+        this.lookVector.z = Math.sin(this.phi) * Math.sin(this.theta);
+
+
+        this.camera.position.add(this.translationWorldDelta) 
+        this.translationWorldDelta.multiplyScalar(0.9); 
+    
+        this.target.copy(this.lookVector).add(this.aimFrom);
+        this.camera.lookAt(this.target)
+        
+        
+        
+    }
+}
+PanoramaControls.prototype.onMouseWheel = function(event) {
+
+    /* if (this.enabled) {
+
+        // let z = void 0 !== event['wheelDelta'] ? event['wheelDelta'] : 0 !== event.detail && -event.detail;
+        // this.flyDirection(new THREE.Vector3(0, 0, -z).normalize());
+        this._wheel = Math.floor(event['wheelDeltaY'] / 120);
+        this._wheel = Math.abs(this._wheel) > 0.1 ? Math.sign(this._wheel) : 0;
+        if (this._wheel !== 0 && this.scrollZoomSta) {
+            this._wheel > 0 ? this._wheel = 1 + this.scrollZoomSpeed : this._wheel = 1 - this.scrollZoomSpeed;
+            let curZoomLevel = this._wheel * this.zoomLevel;
+            this.zoomTo(curZoomLevel);
+        }
+
+    } */
+    
+    let delta
+    if (event.wheelDelta !== undefined) { // WebKit / Opera / Explorer 9
+        delta = event.wheelDelta;
+    } else if (event.detail !== undefined) { // Firefox
+        delta = -event.detail;
+    }
+        
+    
+    
+    if(delta != void 0){//滚轮缩放 
+        if(delta == 0)return //mac
+        let direction = new THREE.Vector3(0,0,-1).applyQuaternion(this.camera.quaternion)
+        let moveSpeed = 0.1
+        if(delta < 0) moveSpeed *=-1
+        this.translationWorldDelta.add(direction.multiplyScalar(moveSpeed))
+    }
+    
+}
+PanoramaControls.prototype.zoomTo = function(curZoomLevel) {
+    curZoomLevel < this.zoomMin && (curZoomLevel = this.zoomMin);
+    curZoomLevel > this.zoomMax && (curZoomLevel = this.zoomMax);
+    this.zoomLevel = curZoomLevel;
+    this.camera.fov = this.baseFov*(1/this.zoomLevel);
+    this.camera.updateProjectionMatrix();
+} 
+
+/*   
+reset() {
+
+    this.stop()
+}
+
+stop() {
+
+    this.rotationAcc.set(0, 0);
+    this.rotationSpeed.set(0, 0);
+}
+*/
+
+
+
+
+//-------------copyFromPlayer
+PanoramaControls.prototype.handleControlScroll = function(e) {
+     e > 0 ? e = 1 + this.scrollZoomSpeed : e < 0 && (e = 1 - this.scrollZoomSpeed);
+    0 !== e && this.zoomBy(e)
+}
+PanoramaControls.prototype.zoomBy = function(e) {
+     this.zoomTo(this.zoomLevel * e);
+}
+
+
+
+function averageVectors(e, t) {
+    var i = new THREE.Vector3();
+    if (0 === e.length) return i;
+    for (var r = 0, o = 0; o < e.length; o++) {
+        var a = t ? e[o][t] : e[o];
+        i.add(a), r++;
+    }
+    return i.divideScalar(r);
+} 
+ 

BIN
project/public/myData/three/assets/0.jpg


BIN
project/public/myData/three/assets/1.jpg


BIN
project/public/myData/three/assets/10.jpg


BIN
project/public/myData/three/assets/11.jpg


BIN
project/public/myData/three/assets/12.jpg


BIN
project/public/myData/three/assets/13.jpg


BIN
project/public/myData/three/assets/14.jpg


BIN
project/public/myData/three/assets/2.jpg


BIN
project/public/myData/three/assets/3.jpg


BIN
project/public/myData/three/assets/4.jpg


BIN
project/public/myData/three/assets/5.jpg


BIN
project/public/myData/three/assets/6.jpg


BIN
project/public/myData/three/assets/7.jpg


BIN
project/public/myData/three/assets/8.jpg


BIN
project/public/myData/three/assets/9.jpg


BIN
project/public/myData/three/background.jpg


+ 34 - 0
project/public/myData/three/click.js

@@ -0,0 +1,34 @@
+// 点击
+viewer.addEventListener('clickObject', e => {
+  window.top.clickObject(e.imgName);
+  // 暂停动画
+  viewer.setAutoMove(false)
+})
+
+// 继续动画 - 给 父页面调用
+window.stareMove = (val) => {
+  viewer.setAutoMove(val)
+}
+
+// let flag = false
+
+// // 鼠标移入
+// viewer.addEventListener('hoverObject', e => {
+//   // console.log('鼠标移入',e);
+//   flag = true
+//   window.top.hoverObject(e);
+// })
+
+// // 鼠标移出
+// viewer.addEventListener('mouseoutObject', e => {
+//   // console.log('鼠标移出',e);
+//   flag = false
+//   window.top.mouseoutObject(e);
+// })
+
+
+// document.querySelector('#player').onmousemove = (event) => {
+//   if (!flag) return
+//   let e = event || window.event;
+//   window.top.mouseLoc(e.clientX, e.clientY);
+// }

+ 99 - 0
project/public/myData/three/index.html

@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<html lang="zh">
+
+<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">
+  <title>artsandculture</title>
+  <style>
+    #player,
+    body,
+    canvas {
+      width: 100%;
+      height: 100%;
+      position: absolute;
+      overflow: hidden;
+      margin: 0;
+      padding: 0;
+    }
+
+    /*canvas{
+          background-image: url(background.jpg); 
+          background-repeat: no-repeat;
+          background-position: center;
+          background-size: cover;
+      }*/
+    #consoleLog {
+      width: 120px;
+      height: 153px;
+      position: absolute;
+      left: 0px;
+      bottom: 160px;
+      z-index: 999999;
+      color: black;
+      opacity: 0.9;
+      font-size: 12px;
+    }
+  </style>
+</head>
+
+<body>
+  <div id="player">
+    <canvas></canvas>
+  </div>
+
+  <script type="text/javascript" src="jquery-2.1.1.min.js"></script>
+  <script type="text/javascript" src="three.min.js"></script>
+  <script>
+
+    const cardNames = ['1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg', '6.jpg', '7.jpg', '8.jpg', '9.jpg', '10.jpg', '11.jpg', '12.jpg', '13.jpg', '14.jpg']
+
+    let vfov = 60 //垂直视角范围度数
+    window.setting = {
+      vfov,
+      cards: {
+        far: 15,
+        beginFadeNear: 7,
+        near: 1,
+        fadeInDur: 2000,
+        highest: Math.tan(THREE.Math.degToRad(vfov / 2)), //当card在1米处时最高可以多少才能在视线内
+
+      }
+
+
+    };
+
+    /* var textarea = document.createElement('textarea');
+    textarea.id = "consoleLog";
+
+    document.getElementsByTagName("body")[0].appendChild(textarea);
+    var list = ["log", "error", "warn", "debug", "info", "time", "timeEnd"]
+    var exchange = function (o) {
+    console["old" + o] = console[o];
+    console[o] = function (str) {
+      console["old" + o](str);
+      var t = document.getElementById("consoleLog").innerHTML;
+      document.getElementById("consoleLog").innerHTML = str + "\n\n" + t;
+    }
+    }
+
+    for (var i = 0; i < list.length; i++) {
+    exchange(list[i])
+    }
+
+    */
+  </script>
+
+
+
+
+
+
+  <script type="text/javascript" src="utils.js"></script>
+  <script type="text/javascript" src="PanoramaControls.js"></script>
+  <script type="text/javascript" src="index.js"></script>
+  <script src="./click.js"></script>
+</body>
+
+</html>

+ 474 - 0
project/public/myData/three/index.js

@@ -0,0 +1,474 @@
+
+
+let camera, scene, renderer;
+
+const shadowHasAlpha = false  //阴影是否考虑光透过透明材质  
+
+const planeGeo = new THREE.PlaneBufferGeometry(1, 1)
+const raycaster = new THREE.Raycaster(); raycaster.linePrecision = 0;//不检测boxHelper
+const mouse = new THREE.Vector2();
+
+let needUpdateShadow, needsUpdateScene
+
+var BlurShader = {
+
+    uniforms: {
+
+        "map": { value: null },
+        "blurRadius": { value: new THREE.Vector2(1.0 / 512.0, 1.0 / 512.0) },
+        'opacity': { value: 0 }
+    },
+
+    vertexShader: [
+
+        "varying vec2 vUv;",
+
+        "void main() {",
+
+        "	vUv = uv;",
+        "	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+        "}"
+
+    ].join("\n"),
+
+    fragmentShader: [
+
+        "uniform sampler2D map;",
+        "uniform vec2 resolution;",
+        "uniform float blurRadius;",
+        "uniform float opacity;",
+        "varying vec2 vUv;",
+
+        "void main() {",
+
+
+        "	vec2 offset = blurRadius / resolution; ",
+
+        "	vec4 sum = vec4( 0.0 );",
+
+        "	sum += texture2D( map, vec2( vUv.x - 4.0 * offset.x, vUv.y ) ) * 0.051;",
+        "	sum += texture2D( map, vec2( vUv.x - 3.0 * offset.x, vUv.y ) ) * 0.0918;",
+        "	sum += texture2D( map, vec2( vUv.x - 2.0 * offset.x, vUv.y ) ) * 0.12245;",
+        "	sum += texture2D( map, vec2( vUv.x - 1.0 * offset.x, vUv.y ) ) * 0.1531;",
+        "	sum += texture2D( map, vec2( vUv.x, vUv.y ) ) * 0.1633;",
+        "	sum += texture2D( map, vec2( vUv.x + 1.0 * offset.x, vUv.y ) ) * 0.1531;",
+        "	sum += texture2D( map, vec2( vUv.x + 2.0 * offset.x, vUv.y ) ) * 0.12245;",
+        "	sum += texture2D( map, vec2( vUv.x + 3.0 * offset.x, vUv.y ) ) * 0.0918;",
+        "	sum += texture2D( map, vec2( vUv.x + 4.0 * offset.x, vUv.y ) ) * 0.051;",
+
+        "	sum += texture2D( map, vec2( vUv.x , vUv.y - 4.0 * offset.y ) ) * 0.051;",
+        "	sum += texture2D( map, vec2( vUv.x , vUv.y - 3.0 * offset.y) ) * 0.0918;",
+        "	sum += texture2D( map, vec2( vUv.x , vUv.y - 2.0 * offset.y) ) * 0.12245;",
+        "	sum += texture2D( map, vec2( vUv.x , vUv.y - 1.0 * offset.y ) ) * 0.1531;",
+        "	sum += texture2D( map, vec2( vUv.x , vUv.y ) ) * 0.1633;",
+        "	sum += texture2D( map, vec2( vUv.x , vUv.y + 1.0 * offset.y ) ) * 0.1531;",
+        "	sum += texture2D( map, vec2( vUv.x , vUv.y + 2.0 * offset.y ) ) * 0.12245;",
+        "	sum += texture2D( map, vec2( vUv.x , vUv.y + 3.0 * offset.y ) ) * 0.0918;",
+        "	sum += texture2D( map, vec2( vUv.x , vUv.y + 4.0 * offset.y ) ) * 0.051;",
+
+
+        "	gl_FragColor = sum / 2.0 ;",
+        "	gl_FragColor.a *= opacity;",
+
+
+
+        "}"
+
+    ].join("\n")
+
+};
+
+
+
+
+
+var Viewer = function (index, dom) {
+    this.index = index;
+    this.dom = dom
+    this.camera = new THREE.PerspectiveCamera(setting.vfov);
+    this.camera.position.set(0, 1, -1.5);
+    this.control = new PanoramaControls(this.camera, this.dom)
+    this.control.latMin = this.control.latMax = 0
+
+
+    //this.control.target.set(0,-1,0)  
+    this.setRenderer()
+
+    this.scene = new THREE.Scene;
+    this.scene.background = common.loadTexture("background.jpg")
+    this.pointerDownPos
+    this.active = false;
+    this.antialias = true;
+    this.clickTime = new Date().getTime();
+    this.updateClock = new THREE.Clock;
+
+
+    this.cardGroup = new THREE.Object3D();
+    this.scene.add(this.cardGroup);
+    this.cardGroup.name = "cardGroup";
+    this.autoMove = true
+
+
+    this.bindEvents()
+    this.preLoadCards()
+    this.animate()
+}
+
+/* 
+    同一时间,视线范围不能同时出现两张卡。也就是分布要根据视角范围变化,但是如果浏览器变宽导致的出现两张卡不算。
+
+ */
+
+Viewer.prototype.preLoadCards = function () {
+
+    let i = 10
+    while (i-- > 0) {
+        this.addCard(true)
+    }
+
+
+    let add = () => {
+        if (document.hidden) return
+        this.addCard()
+        setTimeout(add, 40000 * Math.random() * this.getDensity())  //当前视野中密度越小 添加越频繁
+    }
+    add()
+
+
+
+    document.addEventListener('visibilitychange', (e) => {
+        if (!document.hidden) add()
+        console.log('document.hidden', document.hidden)
+    })
+
+}
+
+Viewer.prototype.getDensity = function () {
+
+
+    let frustumMatrix = new THREE.Matrix4
+    frustumMatrix.multiplyMatrices(this.camera.projectionMatrix, this.camera.matrixWorldInverse)
+
+    let frustum = new THREE.Frustum();
+    frustum.setFromProjectionMatrix(frustumMatrix)
+
+
+    let count = this.cardGroup.children.filter(card => {
+        return frustum.containsPoint(card.position)
+    }).length
+
+
+    let density = count / (this.renderer.domElement.width * this.renderer.domElement.height) * 1000
+
+    return density
+}
+
+
+Viewer.prototype.addCard = function (around) {
+
+    let cardIndex = Math.floor(cardNames.length * Math.random())
+    common.loadTexture("assets/" + cardNames[cardIndex], (map) => {
+
+
+        /* let card = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({ 
+            map,
+            transparent:true, opacity:0,side:2
+        }))  */
+
+
+        let card = new THREE.Mesh(planeGeo, new THREE.ShaderMaterial({
+            uniforms: {
+                map: { value: map },
+                resolution: { value: new THREE.Vector2(this.renderer.domElement.width, this.renderer.domElement.height) },
+                blurRadius: { value: 0 },//像素
+                opacity: { value: 0 }
+            },
+            vertexShader: BlurShader.vertexShader,
+            fragmentShader: BlurShader.fragmentShader,
+            transparent: true, side: 2
+        }))
+
+        Object.defineProperty(card.material, 'opacity', {
+            get: function () {
+                return card.material.uniforms.opacity.value
+            },
+            set: function (e) {
+                card.material.uniforms.opacity.value = e
+
+                card.material.uniforms.blurRadius.value = math.linearClamp(e, [0, 0.4], [40, 0])
+            }
+        })
+
+        let direction, far = setting.cards.far
+        if (around) {//在四周所有方向都可生成,在一开始时需要
+            let n = 0.6//范围0-1 越大越可能接近相机
+            far = far * (1 - n * Math.random()) //靠近一点  
+            direction = new THREE.Vector3(0, 0, -1).applyEuler(new THREE.Euler(0, Math.PI * 2 * Math.random(), 0))
+        } else {//仅在相机前方生成,因为相机往这个方向移动,最前方空缺
+
+
+            direction = new THREE.Vector3(0, 0, -1).applyQuaternion(this.camera.quaternion).applyEuler(new THREE.Euler(0, this.camera.hfov * (Math.random() - 0.5), 0))
+
+        }
+
+
+        let h = (Math.random() * 2 - 1) * setting.cards.highest * 0.8 // *0.8是因为靠近后就会飞出视线
+        card.position.copy(this.camera.position).add(direction.add(new THREE.Vector3(0, h, 0)).multiplyScalar(far))
+
+        card.scale.set(map.image.width / 500, map.image.height / 500, 1)
+        this.cardGroup.add(card)
+
+
+        card.transition = transitions.start(lerp.property(card.material, 'opacity', 1, (e) => {
+            //console.log(e, card.uuid)
+
+        }), setting.cards.fadeInDur);
+
+
+    })
+}
+
+
+Viewer.prototype.removeCards = function () {//移除超过bound的卡
+    let needRemove = this.cardGroup.children.filter(card => {
+        if (card.disToCam > setting.cards.far) {
+            card.material.dispose()
+            transitions.cancel(card.transition)
+            //console.log('remove一张卡')
+            return true
+        }
+    })
+    needRemove.forEach(card => card.parent.remove(card))
+    //needRemove.length>0 && console.log('当前存在卡数', this.cardGroup.children.length)
+}
+
+
+Viewer.prototype.update = function (deltaTime) {//绘制的时候同时更新 
+
+    this.setSize()
+    this.control.update(deltaTime)
+    transitions.update(deltaTime)
+
+    if (this.autoMove) {
+        let direction = new THREE.Vector3(0, 0, -1).applyQuaternion(this.camera.quaternion)
+        let moveSpeed = 0.8
+        this.camera.position.add(direction.multiplyScalar(deltaTime * moveSpeed))
+    }
+    this.cardGroup.children.forEach(card => {
+        card.quaternion.copy(this.camera.quaternion)
+
+        let dis = card.position.clone().setY(0).distanceTo(this.camera.position.clone().setY(0))
+        if (!card.transition.running) {
+            card.material.opacity = math.linearClamp(dis, [setting.cards.near, setting.cards.beginFadeNear], [0, 1])
+        }
+
+        card.disToCam = dis
+    })
+    this.removeCards()
+
+
+
+
+
+    var needsUpdate = 1;
+    if (needsUpdate) {
+        this.renderer.autoClear = true
+        this.renderer.render(this.scene, this.camera)
+    }
+
+
+}
+
+
+
+
+Viewer.prototype.bindEvents = function () {
+
+    this.renderer.domElement.addEventListener('pointermove', this.onPointerMove.bind(this), false);
+    this.renderer.domElement.addEventListener('pointerdown', this.onPointerDown.bind(this), false);
+    this.renderer.domElement.addEventListener('pointerup', this.onPointerUp.bind(this), false);
+
+}
+
+Viewer.prototype.setRenderer = function () {
+    try {
+        this.renderer = new THREE.WebGLRenderer({ canvas: $(this.dom).find("canvas")[0], antialias: true }),
+            this.renderer.setPixelRatio(window.devicePixelRatio ? window.devicePixelRatio : 1),
+            this.renderer.autoClear = false
+        this.renderer.setClearColor(0xffffff, 1)
+        console.log("ContextCreated")
+        //this.emit(Events.ContextCreated) 
+    } catch (e) {
+        console.error("Unable to create a WebGL rendering context")
+    }
+}
+
+
+
+
+Viewer.prototype.hasChanged = function () {//判断画面是否改变了,改变后需要更新一些东西
+    var copy = function () {
+        this.previousState = {
+            projectionMatrix: this.camera.projectionMatrix.clone(),//worldMatrix在control时归零了所以不用了吧,用position和qua也一样
+            position: this.camera.position.clone(),
+            quaternion: this.camera.quaternion.clone(),
+            //mouse: this.mouse.clone(), 
+            fov: this.camera.fov
+        };
+    }.bind(this)
+
+
+    if (!this.previousState) {
+        copy()
+        return { cameraChanged: !0, changed: !0 };
+    }
+    var cameraChanged =
+        !this.camera.projectionMatrix.equals(this.previousState.projectionMatrix) ||
+        !this.camera.position.equals(this.previousState.position) ||
+        !this.camera.quaternion.equals(this.previousState.quaternion)
+
+
+    var changed = cameraChanged //|| !this.mouse.equals(this.previousState.mouse)  
+
+    copy()
+
+    return { cameraChanged, changed };
+}
+
+Viewer.prototype.setSize = function () {
+    var w, h, pixelRatio;
+    return function () {
+        if (w != this.dom.clientWidth || h != this.dom.clientHeight || pixelRatio != window.devicePixelRatio) {
+            w = this.dom.clientWidth;
+            h = this.dom.clientHeight;
+
+            pixelRatio = window.devicePixelRatio;
+
+            this.camera.aspect = w / h;
+            this.camera.updateProjectionMatrix();
+
+
+            this.renderer.setSize(w, h, false, pixelRatio);
+
+            this.camera.hfov = cameraLight.getHFOVForCamera(this.camera, true)
+
+
+            this.cardGroup.children.forEach(card =>
+                card.material.uniforms.resolution.value.set(w, h)
+            )
+        }
+    }
+}()
+
+
+
+Viewer.prototype.animate = function () {
+    var deltaTime = Math.min(1, this.updateClock.getDelta());
+    this.update(deltaTime)
+    //bus.emit('player/position/change', {x:this.position.x, y:this.position.z, lon: this.cameraControls.controls.panorama.lon})
+
+    window.requestAnimationFrame(this.animate.bind(this));
+},
+
+
+    Viewer.prototype.onPointerMove = function (event) {
+
+        if (event.isPrimary === false) return;
+
+        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
+        mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
+
+        if (!this.pointerDownPos) this.checkIntersection();
+
+    }
+Viewer.prototype.onPointerDown = function (event) {
+
+    if (event.isPrimary === false) return;
+    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
+    mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
+    this.pointerDownPos = mouse.clone()
+    this.pointerDownTime = Date.now()
+}
+
+Viewer.prototype.onPointerUp = function (event) {
+
+    if (event.isPrimary === false) return;
+    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
+    mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
+    let now = Date.now()
+    if (mouse.distanceTo(this.pointerDownPos) < 0.006 && now - this.pointerDownTime < 1000) {//click
+
+        //doubleClick
+        /* var time = new Date().getTime();
+        if(time - this.clickTime < 300){
+            if(this.intersects.length){
+                console.log('doubleClick');
+                transitions.cancelById(0)
+                transitions.start(lerp.vector(this.control.target, this.intersects[0].point), 600, null, 0 , easing.easeInOutQuad, null, Transitions.doubleClick);
+            }
+        } */
+        if (this.hoveredObject) {
+            this.dispatchEvent({ type: 'clickObject', imgName: this.hoveredObject.material.uniforms.map.value.image.src.split('/').pop() })
+        }
+    }
+
+    this.pointerDownPos = null
+}
+
+
+
+Viewer.prototype.checkIntersection = function () {
+
+    raycaster.setFromCamera(mouse, this.camera);
+    raycaster.near = 2
+    const intersects = raycaster.intersectObject(this.cardGroup, true);
+    var recover = () => {
+        if (this.hoveredObject) {
+
+
+        }
+    }
+    if (intersects.length > 0) {
+
+        const hoveredObject = intersects[0].object;
+        if (this.hoveredObject != hoveredObject) {
+            recover()
+            this.dispatchEvent({ type: "hoverObject", imgName: hoveredObject.material.uniforms.map.value.image.src.split('/').pop() })
+            this.hoveredObject = hoveredObject;
+            this.dom.style.cursor = 'pointer'
+
+        }
+    } else {
+        recover()
+        this.dispatchEvent({ type: "mouseoutObject" })
+        this.dom.style.cursor = ''
+        this.hoveredObject = null
+    }
+    this.intersects = intersects;
+}
+
+
+
+Viewer.prototype.setAutoMove = function (state) {//设置相机飞行状态
+    this.autoMove = !!state
+
+}
+
+Object.assign(Viewer.prototype, THREE.EventDispatcher.prototype);
+
+//============
+
+var startTime = new Date().getTime();
+var viewer = new Viewer(0, $("#player")[0])
+
+
+
+
+
+
+
+
+
+
+

Разница между файлами не показана из-за своего большого размера
+ 4 - 0
project/public/myData/three/jquery-2.1.1.min.js


Разница между файлами не показана из-за своего большого размера
+ 2 - 0
project/public/myData/three/three.min.js


+ 636 - 0
project/public/myData/three/utils.js

@@ -0,0 +1,636 @@
+var lerp = {
+	vector: function(e, t, f) {//xzw change, add f
+		var i = e.clone();
+		return t = t.clone(),
+		function(n) {
+			e.set(i.x * (1 - n) + t.x * n, i.y * (1 - n) + t.y * n, i.z * (1 - n) + t.z * n)
+			f && f(e,n);
+		}
+	},
+    quaternion: function(e, t, f) {//xzw change, add f
+        var i = e.clone();
+        return function(n) {
+            e.copy(i).slerp(t, n);
+			f && f(e,n);
+        }
+    },
+    property: function(e, t, i, n) {
+        var r = e[t];
+        return function(o) {
+            e[t] = r * (1 - o) + i * o,
+            n && n(e[t])
+        }
+    },
+    uniform: function(e, t, i) {
+        var n = e.material.uniforms[t].value;
+        return function(r) {
+            try{
+                e.material.uniforms[t] && (e.material.uniforms[t].value = n * (1 - r) + i * r)
+            }catch(e){
+                console.log(1)
+            }
+            
+        }
+    },
+    matrix4: function(e, t) {
+        var i = e.clone();
+        return function(n) {
+            for (var r = e.elements, o = i.elements, a = t.elements, s = 0; s < 16; s++)
+                r[s] = o[s] * (1 - n) + a[s] * n
+        }
+    },
+    allUniforms: function(e, t, i) {
+        var n = e.map(function(e) {
+            return this.uniform(e, t, i)
+        }
+        .bind(this));
+        return function(e) {
+            n.forEach(function(t) {
+                t(e)
+            })
+        }
+    }
+};
+
+
+//////
+ 
+var easing = {};
+//渐变曲线函数,反应加速度的变化
+easing.linearTween = function(e, t, i, n) {
+    return i * e / n + t
+}
+,
+easing.easeInQuad = function(e, t, i, n) {
+    return e /= n,
+    i * e * e + t
+}
+,
+easing.easeOutQuad = function(e, t, i, n) {
+    return e /= n,
+    -i * e * (e - 2) + t
+}
+,
+easing.easeInOutQuad = function(e, t, i, n) {
+    return e /= n / 2,
+    e < 1 ? i / 2 * e * e + t : (e--,
+    -i / 2 * (e * (e - 2) - 1) + t)
+}
+,
+easing.easeInCubic = function(e, t, i, n) {
+    return e /= n,
+    i * e * e * e + t
+}
+,
+easing.easeOutCubic = function(e, t, i, n) {
+    return e /= n,
+    e--,
+    i * (e * e * e + 1) + t
+}
+,
+easing.easeInOutCubic = function(e, t, i, n) {
+    return e /= n / 2,
+    e < 1 ? i / 2 * e * e * e + t : (e -= 2,
+    i / 2 * (e * e * e + 2) + t)
+}
+,
+easing.easeInQuart = function(e, t, i, n) {
+    return e /= n,
+    i * e * e * e * e + t
+}
+,
+easing.easeOutQuart = function(e, t, i, n) {
+    return e /= n,
+    e--,
+    -i * (e * e * e * e - 1) + t
+}
+,
+easing.easeInOutQuart = function(e, t, i, n) {
+    return e /= n / 2,
+    e < 1 ? i / 2 * e * e * e * e + t : (e -= 2,
+    -i / 2 * (e * e * e * e - 2) + t)
+}
+,
+easing.easeInQuint = function(e, t, i, n) {
+    return e /= n,
+    i * e * e * e * e * e + t
+}
+,
+easing.easeOutQuint = function(e, t, i, n) {
+    return e /= n,
+    e--,
+    i * (e * e * e * e * e + 1) + t
+}
+,
+easing.easeInOutQuint = function(e, t, i, n) {
+    return e /= n / 2,
+    e < 1 ? i / 2 * e * e * e * e * e + t : (e -= 2,
+    i / 2 * (e * e * e * e * e + 2) + t)
+}
+,
+easing.easeInSine = function(e, t, i, n) {
+    return -i * Math.cos(e / n * (Math.PI / 2)) + i + t
+}
+,
+easing.easeOutSine = function(e, t, i, n) {
+    return i * Math.sin(e / n * (Math.PI / 2)) + t
+}
+,
+easing.easeInOutSine = function(e, t, i, n) {
+    return -i / 2 * (Math.cos(Math.PI * e / n) - 1) + t
+}
+,
+easing.easeInExpo = function(e, t, i, n) {
+    return i * Math.pow(2, 10 * (e / n - 1)) + t
+}
+,
+easing.easeOutExpo = function(e, t, i, n) {
+    return i * (-Math.pow(2, -10 * e / n) + 1) + t
+}
+,
+easing.easeInOutExpo = function(e, t, i, n) {
+    return e /= n / 2,
+    e < 1 ? i / 2 * Math.pow(2, 10 * (e - 1)) + t : (e--,
+    i / 2 * (-Math.pow(2, -10 * e) + 2) + t)
+}
+,
+easing.easeInCirc = function(e, t, i, n) {
+    return e /= n,
+    -i * (Math.sqrt(1 - e * e) - 1) + t
+}
+,
+easing.easeOutCirc = function(e, t, i, n) {
+    return e /= n,
+    e--,
+    i * Math.sqrt(1 - e * e) + t
+}
+,
+easing.easeInOutCirc = function(e, t, i, n) {
+    return e /= n / 2,
+    e < 1 ? -i / 2 * (Math.sqrt(1 - e * e) - 1) + t : (e -= 2,
+    i / 2 * (Math.sqrt(1 - e * e) + 1) + t)
+}
+,
+easing.easeInElastic = function(e, t, i, n) {
+    var r = 1.70158
+      , o = 0
+      , a = i;
+    return 0 === e ? t : 1 === (e /= n) ? t + i : (o || (o = .3 * n),
+    a < Math.abs(i) ? (a = i,
+    r = o / 4) : r = o / (2 * Math.PI) * Math.asin(i / a),
+    -(a * Math.pow(2, 10 * (e -= 1)) * Math.sin((e * n - r) * (2 * Math.PI) / o)) + t)
+}
+,
+easing.easeOutElastic = function(e, t, i, n) {
+    var r = 1.70158
+      , o = 0
+      , a = i;
+    return 0 === e ? t : 1 === (e /= n) ? t + i : (o || (o = .3 * n),
+    a < Math.abs(i) ? (a = i,
+    r = o / 4) : r = o / (2 * Math.PI) * Math.asin(i / a),
+    a * Math.pow(2, -10 * e) * Math.sin((e * n - r) * (2 * Math.PI) / o) + i + t)
+}
+,
+easing.easeInOutElastic = function(e, t, i, n) {
+    var r = 1.70158
+      , o = 0
+      , a = i;
+    return 0 === e ? t : 2 === (e /= n / 2) ? t + i : (o || (o = n * (.3 * 1.5)),
+    a < Math.abs(i) ? (a = i,
+    r = o / 4) : r = o / (2 * Math.PI) * Math.asin(i / a),
+    e < 1 ? -.5 * (a * Math.pow(2, 10 * (e -= 1)) * Math.sin((e * n - r) * (2 * Math.PI) / o)) + t : a * Math.pow(2, -10 * (e -= 1)) * Math.sin((e * n - r) * (2 * Math.PI) / o) * .5 + i + t)
+}
+,
+easing.easeInBack = function(e, t, i, n, r) {
+    return void 0 === r && (r = 1.70158),
+    i * (e /= n) * e * ((r + 1) * e - r) + t
+}
+,
+easing.easeOutBack = function(e, t, i, n, r) {
+    return void 0 === r && (r = 1.70158),
+    i * ((e = e / n - 1) * e * ((r + 1) * e + r) + 1) + t
+}
+,
+easing.easeInOutBack = function(e, t, i, n, r) {
+    return void 0 === r && (r = 1.70158),
+    (e /= n / 2) < 1 ? i / 2 * (e * e * (((r *= 1.525) + 1) * e - r)) + t : i / 2 * ((e -= 2) * e * (((r *= 1.525) + 1) * e + r) + 2) + t
+}
+,
+easing.easeOutBounce = function(e, t, i, n) {
+    return (e /= n) < 1 / 2.75 ? i * (7.5625 * e * e) + t : e < 2 / 2.75 ? i * (7.5625 * (e -= 1.5 / 2.75) * e + .75) + t : e < 2.5 / 2.75 ? i * (7.5625 * (e -= 2.25 / 2.75) * e + .9375) + t : i * (7.5625 * (e -= 2.625 / 2.75) * e + .984375) + t
+}
+,
+easing.easeInBounce = function(e, t, i, r) {
+    return i - easing.easeOutBounce(r - e, 0, i, r) + t
+}
+,
+easing.easeInOutBounce = function(e, t, i, r) {
+    return e < r / 2 ? .5 * easing.easeInBounce(2 * e, 0, i, r) + t : .5 * easing.easeOutBounce(x, 2 * e - r, 0, i, r) + .5 * i + t
+}
+
+ 
+ 
+ 
+ 
+/* 
+    渐变
+    
+
+ */
+
+var transitions = {
+    globalDone: null,
+    funcs: [],
+    counter: 0,
+    uniqueID: 0,
+    start: function(e, t, i, r, o, a, s, cancelFun) {
+        r = r || 0 
+        let info = {
+            func: e,
+            current: -r * Math.abs(t),                      //当前时间
+            duration: (1 - Math.max(r, 0)) * Math.abs(t),   //总时长
+            done: i,
+            easing: o || easing.linearTween,                //渐变曲线
+            cycling: t < 0,
+            running: !0,
+            debug: r < 0,
+            name: a || "T" + this.counter,
+            id: void 0 === s ? this.counter : s,
+            paused: !1,
+			cancelFun : cancelFun,   //取消时执行的函数
+        }  
+        this.funcs.push(info),
+        e(0, 16),
+        this.counter += 1 
+        return info
+    },
+    trigger: function(e) {
+        var t = void 0 === e.delayRatio ? 0 : e.delayRatio
+            , i = e.func || function() {}
+            , r = void 0 === e.duration ? 0 : e.duration;
+        void 0 !== e.cycling && e.cycling && (r = -Math.abs(r));
+        var o = e.done || null
+            , a = e.easing || easing.linearTween
+            , s = e.name || "R" + this.counter
+            , l = void 0 === e.id ? this.counter : e.id;
+        return this.start(i, r, o, t, a, s, l)
+    },
+    setTimeout: function(e, t, i) {
+        var n = void 0 === i ? this.counter : i;
+        return this.trigger({
+            done: e,
+            duration: void 0 === t ? 0 : t,
+            name: "O" + this.counter,
+            id: n
+        })
+    },
+    pause: function() {
+        this.paused = !0
+    },
+    resume: function() {
+        this.paused = !1
+    },
+    update: function(e) {
+        this.funcs.forEach(function(t) {
+            if (!(t.paused || (t.current += 1e3 * e, t.current < 0))){ 
+                if (t.current >= t.duration && !t.cycling) {
+                    var i = t.easing(1, 0, 1, 1);
+                    t.func(i, 1e3 * e),
+                    t.done && t.done(),
+                    t.running = !1 
+                } else {
+                    var n = t.easing(t.current % t.duration / t.duration, 0, 1, 1)
+                        , r = t.func(n, 1e3 * e) || !1;
+                    r && (t.done && t.done(),
+                    t.running = !1)
+                }
+            }
+        });
+        var t = this.funcs.length;
+        this.funcs = this.funcs.filter(function(e) {
+            return e.running
+        }); 
+        var i = this.funcs.length;
+        if (t > 0 && 0 === i && this.globalDone) {
+            var n = this.globalDone;
+            this.globalDone = null,
+            n()
+        }
+    },
+    adjustSpeed: function(e, t) {
+        for (var i = this.getById(e), n = 0; n < i.length; n++) {
+            var r = i[n];
+            r.duration /= t,
+            r.current /= t
+        }
+    },
+    getById: function(e) {
+        return this.funcs.filter(function(t) {
+            return e === t.id
+        })
+    },
+    get: function(e) {
+        for (var t = 0; t < this.funcs.length; t += 1)
+            if (this.funcs[t].func === e)
+                return this.funcs[t];
+        return null
+    },
+    isRunning: function(e) {
+        var t = this.get(e);
+        return null !== t && t.running
+    },
+    countActive: function() {
+        for (var e = 0, t = 0; t < this.funcs.length; t += 1)
+            e += this.funcs[t].running;
+        return e
+    },
+    listActive: function() {
+        for (var e = [], t = 0; t < this.funcs.length; t += 1)
+            this.funcs[t].running && e.push(this.funcs[t].name);
+        return e
+    },
+    done: function(e) {
+        this.globalDone = e
+    },
+    cancelById: function(e, dealCancelFun) { //xzw add dealDone
+        var t = void 0 === e ? 0 : e;
+		 
+        this.funcs = this.funcs.filter(function(e) {
+			var is = e.id == t;
+			
+			if(is && dealCancelFun){
+				e.cancelFun && e.cancelFun()
+			} 
+            return !is
+        })
+    },
+    cancel: function(e) {
+        this.funcs = this.funcs.filter(function(t) {
+            return t.func !== e
+        }) 
+        
+    },
+    getUniqueId: function() {
+        return this.uniqueID -= 1,
+        this.uniqueID
+    }
+};
+
+ 
+let convertTool = {
+    
+	getPos2d : function(point, camera, dom){//获取一个三维坐标对应屏幕中的二维坐标
+	  
+        
+        
+        if(!camera)return
+		var pos = point.clone().project(camera)	//比之前hotspot的计算方式写得简单  project用于3转2(求法同shader); unproject用于2转3 :new r.Vector3(e.x, e.y, -1).unproject(this.camera);
+		
+		var x,y;
+		x = (pos.x + 1) / 2 * dom.clientWidth;
+		y = (1 - (pos.y + 1) / 2) * dom.clientHeight; 
+  
+		var inSight = x <= dom.clientWidth &&  x >= 0    //是否在屏幕中   
+					&& y <= dom.clientHeight &&  y >= 0 
+	 
+	
+		return {
+			pos: new THREE.Vector2(x,y),  // 屏幕像素坐标
+			vector:  pos,   //(范围 -1 ~ 1)
+			trueSide : pos.z<1, //trueSide为false时,即使在屏幕范围内可见,也是反方向的另一个不可以被渲染的点   参见Tag.update
+			inSight : inSight	//在屏幕范围内可见
+		};
+	},
+
+	ifShelter: function (pos3d,  pos2d,  camera, colliders, margin=0  ) {
+        //检测某点在视线中是否被mesh遮挡
+        if (!pos2d) pos2d = convertTool.getPos2d(pos3d )
+        camera = camera || player.camera
+        var ori = new THREE.Vector3(pos2d.x, pos2d.y, -1).unproject(camera) //找到视线原点
+        var dir = pos3d.clone().sub(ori).normalize()
+        var ray = new THREE.Raycaster(ori, dir); //由外向里 因为模型从内侧是可见的所以从外侧
+        var o = ray.intersectObjects(colliders); 
+	 
+		var len = pos3d.distanceTo(ori);
+		if (o && o.length) {
+			for(var i=0;i<o.length;i++){
+				if(o[i].distance < len-margin){  return true;  }//有遮挡
+			} 
+		} 
+	},
+    
+    updateVisible : function(object, reason, ifShow, level=0, type){//当所有加入的条件都不为false时才显示. reason='force'一般是强制、临时的
+        if(!object.unvisibleReasons) object.unvisibleReasons = []; //如果length>0代表不可见
+        if(!object.visibleReasons) object.visibleReasons = []; //在同级时,优先可见
+        
+        
+        var update = function(){
+            
+            //先按从高到低的level排列
+            object.unvisibleReasons = object.unvisibleReasons.sort((a,b)=>b.level-a.level)
+            object.visibleReasons = object.visibleReasons.sort((a,b)=>b.level-a.level)
+            var maxVisiLevel = object.visibleReasons[0] ? object.visibleReasons[0].level : -1
+            var maxunVisiLevel = object.unvisibleReasons[0] ? object.unvisibleReasons[0].level : -1
+            
+            var shouldVisi = maxVisiLevel >= maxunVisiLevel
+            var visiBefore = object.visible
+            
+            
+            if(visiBefore != shouldVisi){
+                object.visible = shouldVisi
+                object.dispatchEvent({
+                    type: 'isVisible',
+                    visible: shouldVisi,
+                    reason,
+                }) 
+            }
+            
+            
+        }    
+        
+        
+        
+        if(ifShow){ 
+
+            var index = object.unvisibleReasons.findIndex(e=>e.reason == reason) 
+            if(index > -1){
+                type = 'cancel'
+                object.unvisibleReasons.splice(index, 1); 
+            }
+            
+            if(type == 'add' ){
+                if(!object.visibleReasons.some(e=>e.reason == reason)){
+                    object.visibleReasons.push({reason,level})
+                }
+            } 
+        }else{ 
+            var index = object.visibleReasons.findIndex(e=>e.reason == reason) 
+            if(index > -1){
+                type = 'cancel'
+                object.visibleReasons.splice(index, 1); 
+            }
+            
+            if(type != 'cancel' ){
+                if(!object.unvisibleReasons.some(e=>e.reason == reason)){
+                    object.unvisibleReasons.push({reason,level})
+                }
+            }
+        }
+          
+        update() 
+        
+    }, 
+     
+
+    toPrecision: function (e, t) {//xzw change 保留小数
+		var f = function (e, t) {
+			var i = Math.pow(10, t);
+			return Math.round(e * i) / i
+		}
+		if (e instanceof Array) {
+			for (var s = 0; s < e.length; s++) {
+				e[s] = f(e[s], t);
+			}
+			return e;
+		} else if (e instanceof Object) {
+			for (var s in e) {
+				e[s] = f(e[s], t);
+			}
+			return e;
+		} else return f(e, t)
+	},
+
+    intervalTool:{  //延时update,防止卡顿
+        list:[],
+        
+        isWaiting:function(name, func, delayTime){
+            if(!this.list.includes(name)){  //如果没有该项, 则开始判断
+                var needWait = func(); //触发了改变,则等待一段时间后再自动判断
+                if(needWait){
+                    this.list.push(name);
+                    setTimeout(()=>{
+                        var a = this.list.indexOf(name);
+                        this.list.splice(a,1);
+                        this.isWaiting(name, func, delayTime) //循环
+                    },delayTime)
+                } 
+            }
+        }, 
+    }
+    ,
+
+}
+ 
+
+
+let math = {
+    closeTo : function(a,b, precision=1e-6){ 
+        let f = (a,b)=>{
+            return Math.abs(a-b) < precision;
+        }; 
+          
+        if(typeof (a) == 'number'){
+            return f(a, b);
+        }else {
+            let judge = (name)=>{
+                if(a[name] == void 0)return true //有值就判断,没值就不判断
+                else return f(a[name],b[name])
+            };
+            return judge('x') && judge('y') && judge('z') && judge('w')  
+        } 
+        
+    }, 
+    linearClamp(value, xArr , yArr){ //xArr需要按顺序从小到大,yArr对应xArr中的值
+	        
+	        let len = xArr.length; 
+	        if(value <= xArr[0]) return yArr[0]
+	        if(value >= xArr[len - 1]) return yArr[len - 1]
+	        let i = 0; 
+	        
+	        while(++i < len ){
+	            if(value < xArr[i]){
+	                let x1 = xArr[i-1], x2 = xArr[i], y1 = yArr[i-1], y2 = yArr[i]; 
+	                value = y1 + ( y2 - y1) * (value - x1)  / (x2 - x1);  
+	                break
+	            }
+	        }
+	        return value
+	        
+	         
+	    } 
+
+
+}
+var cameraLight = {
+    clampVFOV: function(currentFov, maxHFov, width, height) {//限制currentFov, 使之造成的横向fov不大于指定值maxHFov
+        var r = cameraLight.getHFOVFromVFOV(currentFov, width, height);
+        return r > maxHFov ? cameraLight.getVFOVFromHFOV(maxHFov, width, height) : currentFov
+    },
+    getHFOVForCamera: function(camera,  getRad) {
+        return cameraLight.getHFOVByScreenPrecent(camera.fov, camera.aspect, getRad)
+    }, 
+    //add
+    getHFOVByScreenPrecent: function(fov, percent, getRad) { //当fov为占比百分百时,percent代表在屏幕上从中心到边缘的占比
+        let rad = 2 * Math.atan(percent * Math.tan(THREE.Math.degToRad(fov * 2)));
+        if(getRad)return rad 
+        else return rad * MathLight.DEGREES_PER_RADIAN;
+    }
+};
+
+
+let texLoader = new THREE.TextureLoader; 
+let texs = new Map
+let common = {
+    urlHasValue(key, isGetValue) { 
+        let querys = window.location.search.substr(1).split('?')
+        if (isGetValue) {
+            for (let i = 0; i < querys.length; i++) {
+                let keypair = querys[i].split('=')
+                if (keypair.length === 2 && keypair[0] === key) {
+                    return keypair[1]
+                }
+            }
+            return ''
+        } else {
+            //return window.location.search.match("&" + key + "|\\?" + key) != null  有bug
+            for (let i = 0; i < querys.length; i++) {
+                let keypair = querys[i].split('=')
+                if(keypair[0] == key){
+                    return true
+                }
+            }
+            return false
+        }
+    }, 
+
+
+    dataURLtoBlob(dataurl) {//将base64转换blob
+        var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
+            bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
+        while (n--) {
+            u8arr[n] = bstr.charCodeAt(n);
+        }
+        return new Blob([u8arr], { type: mime });
+    },
+     
+    loadTexture(src,done){
+        let o = texs.get(src)
+        if(o){
+            if(o.tex.image) done && done(o.tex)//加载完毕
+            else{
+                o.callbacks.push(done)//等待加载
+            }
+            return 
+        }
+        
+        
+        
+        let callbacks = []
+        let tex = texLoader.load(src,(tex)=>{
+            callbacks.forEach(done=>done(tex)) 
+        }) 
+        done && callbacks.push(done)
+        texs.set(src,{tex,callbacks})
+        return tex
+    }
+}

+ 6 - 1
project/src/pages/A5view/index.module.scss

@@ -1,4 +1,9 @@
-.AAAAA {
+.A5view {
+  position: relative;
   :global {
+    iframe{
+      width: 100%;
+      height: 100%;
+    }
   }
 }

+ 18 - 8
project/src/pages/A5view/index.tsx

@@ -1,14 +1,24 @@
-import React from "react";
-import styles from "./index.module.scss";
- function AAAAA() {
-  
+import React, { useEffect } from 'react'
+import styles from './index.module.scss'
+import MenuSider from '@/components/MenuSider'
+function A5view() {
+
+  useEffect(()=>{
+     // 点击图片
+    (window as any).clickObject = (val:any) => {
+      console.log("000", val);
+    };
+  },[])
+
   return (
-    <div className={styles.AAAAA}>
-      <h1>AAAAA</h1>
+    <div className={styles.A5view}>
+      <iframe title='three' id='iframe' src='./myData/three/index.html' frameBorder='0'></iframe>
+
+      <MenuSider isSidebarOpen={false} />
     </div>
   )
 }
 
-const MemoAAAAA = React.memo(AAAAA);
+const MemoA5view = React.memo(A5view)
 
-export default MemoAAAAA;
+export default MemoA5view

Разница между файлами не показана из-за своего большого размера
+ 424 - 202
project/yarn.lock