zhengnaiwen_citu 4 mesiacov pred
rodič
commit
9218801b97

+ 0 - 0
src/assets/face/钻石脸.jpg → src/assets/face/diamond.jpg


+ 0 - 0
src/assets/face/心形脸.jpg → src/assets/face/heart.jpg


+ 0 - 0
src/assets/face/梨形脸.jpg → src/assets/face/pear.jpg


+ 199 - 0
src/utils/program.js

@@ -0,0 +1,199 @@
+const program = [
+  // {
+  //   face: '圆形脸',
+  //   tedian: '脸部线条偏圆润/可爱/有亲和力',
+  //   detail:'https://minio.citupro.com/dev/static/glass/detail/circledetail.jpg',
+  //   quanxing: [
+  //     {
+  //       type: '猫眼型',
+  //       des: '精致优雅',
+  //       img: 'https://minio.citupro.com/dev/static/glass/catshape.png'
+  //     },
+  //     {
+  //       type: '多边形',
+  //       des: '时尚休闲',
+  //       img:'https://minio.citupro.com/dev/static/glass/poly.png'
+  //     },
+  //     {
+  //       type: '长方形',
+  //       des: '商务正式',
+  //       img: 'https://minio.citupro.com/dev/static/glass/rectangleshape.png',
+  //     }
+  //   ],
+  //   yuanze: {
+  //     title: '对比原则(平衡原则)',
+  //     des: ['推荐有棱角的圈形','平衡脸部比例,打造面部立体感'],
+  //   },
+  //   tips: '半框或纤细的镜架为首选,视觉上可拉长脸部线条不宜选择小而圆的框型',
+  // },
+  {
+    value: 'oval',
+    face: '鹅蛋脸',
+    characteristic: '脸部线条偏圆润/大方/有亲和力',
+    detail: 'https://minio.citupro.com/dev/static/glass/detail/eggdetail.jpg',
+    items: [
+      {
+        type: '多边形',
+        des: '潮流个性',
+        img: 'https://minio.citupro.com/dev/static/glass/poly.png'
+      },
+      {
+        type: '正方形',
+        des: '时尚休闲',
+        img: 'https://minio.citupro.com/dev/static/glass/squareshape.png'
+      },
+      {
+        type: '不规则',
+        des: '时尚百搭',
+        img: 'https://minio.citupro.com/dev/static/glass/unregular.png'
+      }
+    ],
+    principle: {
+      title: '对比原则(平衡原则)',
+      des: ['推荐有棱角的圈形', '平衡脸部比例,打造面部立体感']
+    },
+    tips: '全框镜架为首选,视觉上可缩短脸部长度不宜选择框缘过于上扬的框型'
+  },
+  {
+    value: 'square',
+    face: '方形脸',
+    characteristic: '下颚骨明显/ 脸部立体 / 有距离感',
+    detail: 'https://minio.citupro.com/dev/static/glass/detail/squaredetail.jpg',
+    items: [
+      {
+        type: '飞行员',
+        des: '时尚精致',
+        img: 'https://minio.citupro.com/dev/static/glass/pilotshape.png'
+      },
+      {
+        type: '潘托斯',
+        des: '文艺休闲',
+        img: 'https://minio.citupro.com/dev/static/glass/pentosshape.png'
+      },
+      {
+        type: '椭圆形',
+        des: '精致文艺',
+        img: 'https://minio.citupro.com/dev/static/glass/eclipseshape.png'
+      }
+    ],
+    principle: {
+      title: '对比原则(平衡原则)',
+      des: ['推荐圆润的圈形',
+        '平衡脸部棱角,柔化面部线条'
+      ]
+    },
+    tips: '不宜选择大而方的框型'
+  },
+  // {
+  //   face: '长形脸',
+  //   tedian: '轮廓明显/脸部立体 / 有距离感',
+  //   detail:'https://minio.citupro.com/dev/static/glass/detail/rectangledetail.jpg',
+  //   quanxing: [
+  //     {
+  //       type: '不规则',
+  //       des: '时尚百搭',
+  //       img: 'https://minio.citupro.com/dev/static/glass/unregular.png'
+  //     },
+  //     {
+  //       type: '潘托斯',
+  //       des: '文艺休闲',
+  //       img: 'https://minio.citupro.com/dev/static/glass/pentosshape.png'
+  //     },
+  //     {
+  //       type: '圆形',
+  //       des: '复古潮流',
+  //       img: 'https://minio.citupro.com/dev/static/glass/circle.png',
+  //     }
+  //   ],
+  //   yuanze: {
+  //     title: '对比原则(平衡原则)',
+  //     des: ['推荐有圆润的圈形','平衡脸部棱角,柔化面部线条'],
+  //   },
+  //   tips: '有一定高度的全框镜架为首选,视觉上可缩短脸部长度',
+  // },
+  {
+    value: 'heart',
+    face: '心形脸',
+    characteristic: '下巴尖/ 脸部立体  / 有距离感',
+    detail: 'https://minio.citupro.com/dev/static/glass/detail/heartdetail.jpg',
+    items: [
+      {
+        type: '飞行员',
+        des: '时尚精致',
+        img: 'https://minio.citupro.com/dev/static/glass/pilotshape.png'
+      },
+      {
+        type: '潘托斯',
+        des: '文艺休闲',
+        img: 'https://minio.citupro.com/dev/static/glass/pentosshape.png'
+      },
+      {
+        type: '圆形',
+        des: '复古潮流',
+        img: 'https://minio.citupro.com/dev/static/glass/circle.png'
+      }
+    ],
+    principle: {
+      title: '对比原则(平衡原则)',
+      des: ['推荐有圆润的圈形', '平衡脸部棱角,柔化面部线条']
+    },
+    tips: '不宜选择半框或者框缘上扬的镜架'
+  },
+  {
+    value: 'diamond',
+    face: '钻石脸',
+    characteristic: '颧骨高/ 脸部立体  / 有距离感',
+    detail: 'https://minio.citupro.com/dev/static/glass/detail/diamonddetail.jpg',
+    items: [
+      {
+        type: '不规则',
+        des: '时尚百搭',
+        img: 'https://minio.citupro.com/dev/static/glass/unregular.png'
+      },
+      {
+        type: '潘托斯',
+        des: '时尚休闲',
+        img: 'https://minio.citupro.com/dev/static/glass/pentosshape.png'
+      },
+      {
+        type: '圆形',
+        des: '复古潮流',
+        img: 'https://minio.citupro.com/dev/static/glass/circle.png'
+      }
+    ],
+    principle: {
+      title: '对比原则(平衡原则)',
+      des: ['推荐圆润的圈形', '平衡脸部棱角,柔化面部线条']
+    },
+    tips: '有一定宽度的框型为首选,视觉上可弱化颧骨高度'
+  },
+  {
+    value: 'pear',
+    face: '梨形脸',
+    characteristic: '脸部线条偏圆润/可爱/有亲和力',
+    detail: 'https://minio.citupro.com/dev/static/glass/detail/peardetail.jpg',
+    items: [
+      {
+        type: '蝴蝶型',
+        des: '时尚个性',
+        img: 'https://minio.citupro.com/dev/static/glass/butterfly.png'
+      },
+      {
+        type: '正方形',
+        des: '时尚休闲',
+        img: 'https://minio.citupro.com/dev/static/glass/squareshape.png'
+      },
+      {
+        type: '多边形',
+        des: '潮流个性',
+        img: 'https://minio.citupro.com/dev/static/glass/poly.png'
+      }
+    ],
+    principle: {
+      title: '对比原则(平衡原则)',
+      des: ['推荐有棱角的圈形', '平衡脸部比例,打造面部立体感']
+    },
+    tips: '全框或者有颜色的镜架为首选,视觉上可加重脸上半部分份量,以达到整体平衡。'
+  }
+]
+export default program

+ 6 - 5
src/views/Home.vue

@@ -1,15 +1,16 @@
 <template>
   <div class="home">
-    <section v-if="tab === 0">
-      <MCover @to="tab = 1">
+    <section>
+      <MCover>
         <template #center="{ active, target }">
-          <MCamera v-if="active" @reject="$event => handleReject($event, target)" @photo="handleGet" @close="target(false)"></MCamera>
+          <MCamera v-if="active && tab === 0" @reject="$event => handleReject($event, target)" @photo="handleGet" @close="target(false)"></MCamera>
+          <MFeature v-if="active && tab === 1" :src="imgBase64" :items="face" @reTake="tab = 0"></MFeature>
         </template>
       </MCover>
     </section>
-    <section v-if="tab === 1">
+    <!-- <section v-if="tab === 1">
       <MFeature :src="imgBase64" :items="face" @reTake="tab = 0"></MFeature>
-    </section>
+    </section> -->
     <modal name="VueDialog" height="150" width="300">
       <div class="model">
         <div class="model-title">提示</div>

+ 49 - 174
src/views/components/MCamera.vue

@@ -12,11 +12,11 @@
       <template v-if="ready">
         <div class="box-tool d-flex align-center justify-center">
           <div class="item" @click="handleTake">
-            <v-icon color="#000" size="36">mdi mdi-camera</v-icon>
+            <v-icon color="#FFF" size="36">mdi mdi-camera</v-icon>
           </div>
         </div>
         <div class="close" @click="$emit('close')">
-          <v-icon color="#000" size="36">mdi mdi-close-circle</v-icon>
+          <v-icon color="#FFF" size="36">mdi mdi-close-circle</v-icon>
         </div>
       </template>
 
@@ -26,12 +26,17 @@
       </div>
     </div>
 
-    <v-overlay :value="loading" opacity="0">
+    <!-- <v-overlay :value="loading" opacity="0">
       <div class="loader">
         <svg viewBox="0 0 80 80">
           <rect height="64" width="64" y="8" x="8"></rect>
         </svg>
       </div>
+    </v-overlay> -->
+    <v-overlay :value="loading" opacity="0">
+      <div class="cover">
+        <div class="cover-move"></div>
+      </div>
     </v-overlay>
   </div>
 </template>
@@ -46,7 +51,7 @@ export default {
       videoStream: null,
       animationId: null,
       src: '',
-      loading: true,
+      loading: false,
       ready: false,
       faceShape: '',
       showImg: false,
@@ -205,27 +210,57 @@ export default {
 </script>
 
 <style lang="less" scoped>
+.cover {
+  @width: 300px;
+  @height: 350px;
+  width: @width;
+  height: @height;
+  margin: 0 auto;
+  @color: #FFF;
+  background: linear-gradient(@color, @color) left top,
+      linear-gradient(@color, @color) left top,
+      linear-gradient(@color, @color) right top,
+      linear-gradient(@color, @color) right top,
+      linear-gradient(@color, @color) left bottom,
+      linear-gradient(@color, @color) left bottom,
+      linear-gradient(@color, @color) right bottom,
+      linear-gradient(@color, @color) right bottom;
+  background-repeat: no-repeat;
+  background-size: 8px 24px, 24px 8px;
+  position: relative;
+  &-move {
+    height: 10px;
+    width: 100%;
+    top: 0;
+    left: 0;
+    position: absolute;
+    background: linear-gradient(45deg, rgba(255,255,255,0), #fff, rgba(255,255,255,0));
+    animation: pathTriangle 1s linear infinite;
+  }
+
+  @keyframes pathTriangle {
+    0% {
+      top: 0;
+    }
+    100% {
+      top: calc(@height - 10px);
+    }
+  }
+}
+
 .faceRecognition {
   font-size: 14px;
   width: 100%;
   height: 100%;
   overflow: hidden;
-  // background: #000;
 }
 
 .box {
   margin: 0 auto;
-  max-width: 600px;
+  width: 480px;
+  background: #000;
   position: relative;
   height: 100%;
-  // &-tool {
-  //   position: fixed;
-  //   width: calc(100% - 600px);
-  //   height: 100%;
-  //   right: 0;
-  //   top: 0;
-  //   font-size: 16px;
-  // }
   &-tool {
     position: absolute;
     height: 150px;
@@ -233,7 +268,6 @@ export default {
     bottom: 0;
     left: 0;
     font-size: 16px;
-    // background: rgba(0, 0, 0, .5);
     .item {
       padding: 10px;
       border: 1px solid #999;
@@ -268,163 +302,4 @@ export default {
   background: greenyellow;
 }
 
-/* From Uiverse.io by mobinkakei */
-.loader {
-  --path: #FFF;
-  --dot: #141e8c;
-  --duration: 3s;
-  width: 44px;
-  height: 44px;
-  position: relative;
-}
-
-.loader:before {
-  content: "";
-  width: 6px;
-  height: 6px;
-  border-radius: 50%;
-  position: absolute;
-  display: block;
-  background: var(--dot);
-  top: 37px;
-  left: 19px;
-  transform: translate(-18px, -18px);
-  animation: dotRect var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86)
-    infinite;
-}
-
-.loader svg {
-  display: block;
-  width: 100%;
-  height: 100%;
-}
-
-.loader svg rect,
-.loader svg polygon,
-.loader svg circle {
-  fill: none;
-  stroke: var(--path);
-  stroke-width: 10px;
-  stroke-linejoin: round;
-  stroke-linecap: round;
-}
-
-.loader svg polygon {
-  stroke-dasharray: 145 76 145 76;
-  stroke-dashoffset: 0;
-  animation: pathTriangle var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86)
-    infinite;
-}
-
-.loader svg rect {
-  stroke-dasharray: 192 64 192 64;
-  stroke-dashoffset: 0;
-  animation: pathRect 3s cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
-}
-
-.loader svg circle {
-  stroke-dasharray: 150 50 150 50;
-  stroke-dashoffset: 75;
-  animation: pathCircle var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86)
-    infinite;
-}
-
-.loader.triangle {
-  width: 48px;
-}
-
-.loader.triangle:before {
-  left: 21px;
-  transform: translate(-10px, -18px);
-  animation: dotTriangle var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86)
-    infinite;
-}
-
-@keyframes pathTriangle {
-  33% {
-    stroke-dashoffset: 74;
-  }
-
-  66% {
-    stroke-dashoffset: 147;
-  }
-
-  100% {
-    stroke-dashoffset: 221;
-  }
-}
-
-@keyframes dotTriangle {
-  33% {
-    transform: translate(0, 0);
-  }
-
-  66% {
-    transform: translate(10px, -18px);
-  }
-
-  100% {
-    transform: translate(-10px, -18px);
-  }
-}
-
-@keyframes pathRect {
-  25% {
-    stroke-dashoffset: 64;
-  }
-
-  50% {
-    stroke-dashoffset: 128;
-  }
-
-  75% {
-    stroke-dashoffset: 192;
-  }
-
-  100% {
-    stroke-dashoffset: 256;
-  }
-}
-
-@keyframes dotRect {
-  25% {
-    transform: translate(0, 0);
-  }
-
-  50% {
-    transform: translate(18px, -18px);
-  }
-
-  75% {
-    transform: translate(0, -36px);
-  }
-
-  100% {
-    transform: translate(-18px, -18px);
-  }
-}
-
-@keyframes pathCircle {
-  25% {
-    stroke-dashoffset: 125;
-  }
-
-  50% {
-    stroke-dashoffset: 175;
-  }
-
-  75% {
-    stroke-dashoffset: 225;
-  }
-
-  100% {
-    stroke-dashoffset: 275;
-  }
-}
-
-.loader {
-  display: inline-block;
-  margin: 0 16px;
-}
-
 </style>

+ 16 - 7
src/views/components/MCover.vue

@@ -54,9 +54,6 @@ export default {
     handleAgree () {
       this.active = true
       this.$modal.hide('example')
-      // setTimeout(() => {
-      //   this.$emit('to')
-      // }, 200)
     },
     handleTarget (bool) {
       this.active = bool
@@ -96,6 +93,14 @@ export default {
       margin-left: 30px;
       text-shadow: 1px 1px 0 white;
     }
+    @media screen and (max-width: 600px) {
+      img {
+        width: 40px;
+      }
+      .name {
+        font-size: 24px;
+      }
+    }
 
   }
   // &.active {
@@ -135,10 +140,6 @@ export default {
     overflow: hidden;
     box-shadow: 0px 0px 19px 8px rgba(0, 0, 0, 0.2);
     z-index: 9;
-    // display: flex;
-    // flex-direction: column;
-    // align-items: center;
-    // justify-content: center;
     border-radius: @width;
     width: @width;
     height: @width;
@@ -158,6 +159,14 @@ export default {
       height: 80%;
       border-radius: 10px;
     }
+    @media screen and (max-width: 600px) {
+      &.active {
+        cursor: default;
+        width: 100%;
+        height: 400px;
+        border-radius: 0;
+      }
+    }
   }
 }
 .chooseMethod {

+ 19 - 6
src/views/components/MFeature.vue

@@ -3,10 +3,10 @@
     <div class="text-center text-h5 text--indigo mb-5">检测结果</div>
     <div class="d-flex">
       <div class="text-center" v-for="face in items" :key="face.name">
-        <img :src="require(`@/assets/face/${face.name}.jpg`)" alt="" width="300">
+        <img class="faceType" :src="require(`@/assets/face/${face.name}.jpg`)" alt="">
         <div class="text-h5 text--indigo py-5">
           {{ faceType[face.name] }}
-          {{ face.similarity.toFixed(2) }}%
+          相似度 {{ face.similarity.toFixed(2) }}%
         </div>
       </div>
     </div>
@@ -19,6 +19,7 @@
 </template>
 
 <script>
+import programType from '@/utils/program'
 export default {
   name: 'm-feature',
   props: {
@@ -33,10 +34,14 @@ export default {
   },
   data () {
     return {
-      faceType: {
-        square: '方型脸',
-        oval: '鹅蛋脸'
-      }
+    }
+  },
+  computed: {
+    faceType () {
+      return programType.reduce((res, item) => {
+        res[item.value] = item.face
+        return res
+      }, {})
     }
   },
   methods: {
@@ -74,4 +79,12 @@ export default {
   background: #141e8c;
   color: #fff;
 }
+.faceType {
+  width: 300px;
+}
+@media screen and (max-width: 600px) {
+  .faceType {
+    width: 150px;
+  }
+}
 </style>