任一存 3 년 전
부모
커밋
908cd546e0

+ 3 - 0
.eslintignore

@@ -0,0 +1,3 @@
+*/libs
+/node_modules
+/.vscode

+ 32 - 3
.eslintrc.js

@@ -1,10 +1,15 @@
 module.exports = {
   root: true,
   env: {
-    node: true
+    browser: true,
+    commonjs: true,
+    es6: true,
+    jest: true,
+    jquery: true,
+    node: true,
   },
   'extends': [
-    'plugin:vue/vue3-essential',
+    'plugin:vue/vue3-recommended',
     'eslint:recommended'
   ],
   parserOptions: {
@@ -12,6 +17,30 @@ module.exports = {
   },
   rules: {
     'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
-    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
+    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
+    'semi': ['error', 'never'],
+    "no-unused-vars": ["warn", {
+      "vars": "all",
+      "args": "after-used",
+      "ignoreRestSiblings": false
+    }],
+    "keyword-spacing": ["error", { "before": true, "after": true }],
+    "object-curly-spacing": ["error", "always"],
+    "space-infix-ops": ["error"],
+    'key-spacing': ["error", {
+      "mode": "strict"
+    }],
+    "indent": ["error", 2],
+    'no-trailing-spaces': 'error',
+    'no-empty': 'off',
+    // 默认不启用:为了避免细微的 bug,最好直接从 Object.prototype 调用挂载于prototype上的方法方法。例如,foo.hasOwnProperty("bar") 应该替换为 Object.prototype.hasOwnProperty.call(foo, "bar")。
+    'no-prototype-builtins': "off",
+  },
+  globals: {
+    api: true,
+    config: true,
+    // mapGetters: true,
+    store: true,
+    utils: true,
   }
 }

+ 1 - 0
.gitignore

@@ -2,6 +2,7 @@
 node_modules
 /dist
 
+*.zip
 
 # local env files
 .env.local

+ 2 - 1
jsconfig.json

@@ -15,5 +15,6 @@
       "dom.iterable",
       "scripthost"
     ]
-  }
+  },
+  "exclude": ["libs", "node_modules"]
 }

+ 1 - 0
package.json

@@ -8,6 +8,7 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "@tweenjs/tween.js": "^18.6.4",
     "core-js": "^3.8.3",
     "vue": "^3.2.13",
     "vue-router": "^4.0.3",

+ 8 - 20
src/App.vue

@@ -1,30 +1,18 @@
 <template>
-  <nav>
-    <router-link to="/">Home</router-link> |
-    <router-link to="/about">About</router-link>
-  </nav>
-  <router-view/>
+  <router-view />
 </template>
 
 <style lang="less">
+@import "@/assets/style/reset.css";
+@import "@/assets/style/my-reset.css";
+html, body {
+  height: 100%;
+}
+
 #app {
   font-family: Avenir, Helvetica, Arial, sans-serif;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
-  text-align: center;
-  color: #2c3e50;
-}
-
-nav {
-  padding: 30px;
-
-  a {
-    font-weight: bold;
-    color: #2c3e50;
-
-    &.router-link-exact-active {
-      color: #42b983;
-    }
-  }
+  height: 100%;
 }
 </style>

BIN
src/assets/background.jpg


BIN
src/assets/introduce.png


BIN
src/assets/landscape.png


BIN
src/assets/logo.png


BIN
src/assets/people-far-no-color.png


BIN
src/assets/people-far.png


BIN
src/assets/people-near.png


+ 6 - 0
src/assets/style/my-reset.css

@@ -0,0 +1,6 @@
+
+button {
+  padding: 0;
+  cursor: pointer;
+  background: transparent;
+}

+ 48 - 0
src/assets/style/reset.css

@@ -0,0 +1,48 @@
+/* http://meyerweb.com/eric/tools/css/reset/ 
+   v2.0 | 20110126
+   License: none (public domain)
+*/
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed, 
+figure, figcaption, footer, header, hgroup, 
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+	margin: 0;
+	padding: 0;
+	border: 0;
+	font-size: 100%;
+	font: inherit;
+	vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure, 
+footer, header, hgroup, menu, nav, section {
+	display: block;
+}
+body {
+	line-height: 1;
+}
+ol, ul {
+	list-style: none;
+}
+blockquote, q {
+	quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+	content: '';
+	content: none;
+}
+table {
+	border-collapse: collapse;
+	border-spacing: 0;
+}

+ 169 - 7
src/views/HomeView.vue

@@ -1,18 +1,180 @@
 <template>
-  <div class="home">
-    <img alt="Vue logo" src="../assets/logo.png">
-    <HelloWorld msg="Welcome to Your Vue.js App"/>
+  <div
+    class="home"
+    draggable="false"
+    @mousedown="onMouseDown"
+    @mousemove="onMouseMove"
+    @mouseup="onMouseUp"
+    @wheel.passive="onWheel"
+  >
+    <img
+      class="landscape"
+      src="@/assets/landscape.png"
+      alt=""
+      draggable="false"
+    >
+    <div
+      class="people-far"
+      :style="{
+        right: peopleFarPositionRight,
+      }"
+    >
+      <img
+        src="@/assets/people-far-no-color.png"
+        alt=""
+        draggable="false"
+      >
+    </div>
+    <img
+      class="people-near"
+      :style="{
+        right: peopleNearPositionRight,
+      }"
+      src="@/assets/people-near.png"
+      alt=""
+      draggable="false"
+    >
+    <img
+      class="introduce"
+      :style="{
+        left: introducePositionLeft,
+      }"
+      src="@/assets/introduce.png"
+      alt=""
+      draggable="false"
+    >
   </div>
 </template>
 
 <script>
-// @ is an alias to /src
-import HelloWorld from '@/components/HelloWorld.vue'
-
 export default {
   name: 'HomeView',
   components: {
-    HelloWorld
+  },
+  data() {
+    return {
+      landscapePositionRight: '-50%',
+      peopleFarPositionRight: '0px',
+      peopleNearPositionRight: '-30%',
+      introducePositionLeft: '2%',
+      translateLength: 0,
+      isMouseDown: false,
+
+      moveSpeed: 0,
+      lastMoveEventTimeStamp: 0,
+      lastAnimationTimeStamp: 0,
+      animationFrameId: null,
+
+      lastMoveEventX: 0,
+    }
+  },
+  watch: {
+    translateLength: {
+      handler(v) {
+        console.log(v)
+        if (v > 0) {
+          v = 0
+          this.translateLength = v
+          this.moveSpeed = 0
+        } else if (v < -window.innerWidth * 2) {
+          v = -window.innerWidth * 2
+          this.translateLength = v
+          this.moveSpeed = 0
+        }
+        this.peopleFarPositionRight = `calc(0px - ${v * 0.2}px)`
+        this.peopleNearPositionRight = `calc(-30% - ${v * 0.8}px)`
+        this.introducePositionLeft = `calc(2% + ${v * 1}px)`
+      }
+    }
+  },
+  mounted() {
+    this.animationFrameId = requestAnimationFrame(this.inertanceEffect)
+  },
+  unmounted() {
+    cancelAnimationFrame(this.animationFrameId)
+  },
+  methods: {
+    onMouseDown(e) {
+      this.isMouseDown = true
+      this.moveSpeed = 0
+      this.lastMoveEventTimeStamp = 0
+      this.lastAnimationTimeStamp = Date.now()
+    },
+    onMouseUp(e) {
+      this.isMouseDown = false
+    },
+    onMouseMove(e) {
+      if (this.isMouseDown) {
+        if (this.lastMoveEventTimeStamp) {
+          const currentMoveSpeed = e.movementX / (e.timeStamp - this.lastMoveEventTimeStamp)
+          this.moveSpeed = this.moveSpeed * 0.9 + currentMoveSpeed * 0.1
+        }
+        this.lastMoveEventTimeStamp = e.timeStamp
+      }
+    },
+    onWheel(e) {
+      this.translateLength -= e.deltaY
+    },
+    inertanceEffect() {
+      const timeStamp = Date.now()
+      const timeElapsed = timeStamp - this.lastAnimationTimeStamp
+      if (this.moveSpeed > 0) {
+        this.moveSpeed -= 0.003 * timeElapsed
+        if (this.moveSpeed < 0) {
+          this.moveSpeed = 0
+        }
+      } else if (this.moveSpeed < 0) {
+        this.moveSpeed += 0.003 * timeElapsed
+        if (this.moveSpeed > 0) {
+          this.moveSpeed = 0
+        }
+      }
+
+      this.translateLength += this.moveSpeed * timeElapsed
+
+      this.lastAnimationTimeStamp = timeStamp
+      this.animationFrameId = requestAnimationFrame(this.inertanceEffect)
+    }
   }
 }
 </script>
+
+<style lang="less" scoped>
+.home {
+  width: 100%;
+  height: 100%;
+  background-image: url(@/assets/background.jpg);
+  background-repeat: repeat;
+  background-size: contain;
+  position: relative;
+  overflow: hidden;
+  user-select: none;
+  .landscape {
+    height: 30%;
+    position: absolute;
+    top: 0;
+    right: 0;
+    user-select: none;
+  }
+  .people-far {
+    position: absolute;
+    top: 20%;
+    height: 60%;
+    user-select: none;
+    > img {
+      height: 100%;
+    }
+  }
+  .people-near {
+    position: absolute;
+    bottom: 0;
+    height: 90%;
+    user-select: none;
+  }
+  .introduce {
+    position: absolute;
+    top: 5%;
+    user-select: none;
+  }
+}
+</style>

+ 18 - 1
vue.config.js

@@ -1,4 +1,21 @@
+const webpack = require('webpack')
 const { defineConfig } = require('@vue/cli-service')
+
 module.exports = defineConfig({
-  transpileDependencies: true
+  // transpileDependencies: true,
+  configureWebpack: {
+    module: {
+      rules: [
+      ],
+    },
+    plugins: [
+      new webpack.ProvidePlugin({
+        utils: ['/src/utils.js', 'default'],
+        store: ['/src/store/index.js', 'default'],
+        api: ['/src/api.js', 'default'],
+        config: '/src/config.js',
+        // mapGetters: ['vuex', 'mapGetters'],
+      }),
+    ],
+  },
 })

+ 5 - 0
yarn.lock

@@ -1123,6 +1123,11 @@
   resolved "https://registry.npmmirror.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"
   integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==
 
+"@tweenjs/tween.js@^18.6.4":
+  version "18.6.4"
+  resolved "https://registry.npmmirror.com/@tweenjs/tween.js/-/tween.js-18.6.4.tgz#40a3d0a93647124872dec8e0fd1bd5926695b6ca"
+  integrity sha512-lB9lMjuqjtuJrx7/kOkqQBtllspPIN+96OvTCeJ2j5FEzinoAXTdAMFnDAQT1KVPRlnYfBrqxtqP66vDM40xxQ==
+
 "@types/body-parser@*":
   version "1.19.2"
   resolved "https://registry.npmmirror.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0"