Browse Source

fix: 增加新手引导

lvkun996 1 year ago
parent
commit
1d8979beca

BIN
src/assets/intro.gif


+ 43 - 56
src/components/luojigou-board/luojigou-board.vue

@@ -2,7 +2,7 @@
   <view class="luojigou-board" >
     <view class="board" :style="{scale: adaptatio, transformOrigin: '50% 0%'}" >
       <image class="board-img" :src="boardUrl" />
-      <view class="board-header" id="game-label">
+      <view class="board-header" :style="{zIndex: viewZindex.headerView}" id="game-label" >
         <view class="trumpt" @click="emits('playAudio')">
           <!-- <image class="dog" :src="staticImg.trumptDog"   /> -->
           <image
@@ -32,12 +32,11 @@
       <view class="ans"  id="ansRef" :style="{zIndex: viewZindex.quesView}">
         <image :src="props.board.ansUrl" alt="" />
       </view>
-
       <canvas
         type="2d"
         canvas-id="magnifier-canvas"
         id="magnifier-canvas"
-        :style="{width: '300px', height: '386px', zIndex: viewZindex.magnifierView}"
+        :style="{width: '600rpx', height: '772rpx', zIndex: viewZindex.magnifierView}"
       ></canvas>
       <movable-area 
       v-if="props.cardType !== undefined" 
@@ -85,16 +84,16 @@
       </movable-view>
       </movable-area>
       <!-- 新手引导 -->
-      <view class="intro">
-        <view class="lingheight" >
-
+      <view class="intro" v-if="viewZindex.introView > 0" :style="{zIndex: viewZindex.introView}" @click="nextIntro" >
+        <view class="lingheight"  >
         </view>
       </view>
     </view>
 
+   
   </view>
-</template>
 
+</template>
 
 <script setup lang="ts" name="luojigou-board" >
 import { defineProps, reactive, ref, computed, getCurrentInstance, defineEmits, watch } from 'vue'
@@ -103,7 +102,7 @@ import type { CardModeEnum } from '@/enum/constant';
 import { useCalcQuantityStore } from '@/store/index';
 import { AudioController } from '@/controller/AudioController';
 import Hammer from 'hammerjs'
-import { onMounted } from 'vue';
+import { onMounted, nextTick } from 'vue';
 
 
 interface Buttons {
@@ -150,9 +149,11 @@ const state = reactive({
 })
 
 const viewZindex = ref({
-  moveView: 30,
-  magnifierView: 31,
-  quesView: 29
+  moveView: 30, // 拖拽层
+  magnifierView: 31, // 放大镜
+  quesView: 29, // 题卡
+  headerView: 33,
+  introView: 32 // 引导层
 })
 
 
@@ -367,27 +368,21 @@ const checkAns = (index: number, itemData: Buttons) => {
   }
 }
 
+const nextIntro = () => {
 
+  viewZindex.value.introView = viewZindex.value.headerView + 1
 
+  viewZindex.value.quesView = viewZindex.value.introView + 1
 
- 
-
-/**
- * 新手引导功能
- */
-const getIntro = () => {
-  // 先判断有没有玩过,如果没有玩过
+  viewZindex.value.magnifierView = viewZindex.value.quesView + 1
 
-  const played = uni.getStorageSync('played')
-  if (!played) {
-    uni.setStorageSync('played', 1)
-  }
+  createMagnifier()
+  nextTick(() => {
+    a()
+  })
   
 }
 
-
-
-
 /**
  * @description 放在onMounted生命周期里就可以生效,功能:把题卡放大缩小
  * @description 需要在touchStart时 设置 viewZindex.value.moveView = viewZindex.value.quesView + 1 
@@ -486,21 +481,30 @@ watch(
   }
 )
 
+/**
+ * 题卡的放大镜功能
+ */
 
-onMounted(() => {
+const createMagnifier = () => {
   useMagnifier(
-    document.getElementById('magnifier-canvas') as HTMLCanvasElement, 
-    'magnifier-canvas',
-    {
-      ansUrl:  props.board.ansUrl,
-      quesUrl:  props.board.quesUrl,
-      instance: getCurrentInstance()!
-    }
-).then(r => {
-  console.log(r.draw);
-  a = r.draw
-  b = r.clear
-})
+      document.getElementById('magnifier-canvas') as HTMLCanvasElement, 
+      'magnifier-canvas',
+      {
+        ansUrl:  props.board.ansUrl,
+        quesUrl:  props.board.quesUrl,
+        instance: getCurrentInstance()!,
+        rate: rate
+      }
+  ).then(r => {
+    a = r.draw
+    b = r.clear
+  })
+}
+
+
+
+onMounted(() => {
+  createMagnifier()
 })
 
 </script>
@@ -683,25 +687,8 @@ onMounted(() => {
           }
         }
       }
-
-  
-  }
-
-  .intro {
-    width: 100vw;
-    height: 100vh;
-    background-color: rgba(0, 0, 0, 0.3);
-    position: fixed;
-    top: 0;
-    left: 0;
-    z-index: 31;
-    scale: 2;
-    .lingheight {
-      width: 200px;
-      height: 200px;
-      // background-color: #fff;
-    }
   }
+  
   .mark-button {
     width: 100%;
     height: 100%;

+ 69 - 20
src/hooks/index.ts

@@ -4,6 +4,7 @@ import { toRefs } from 'vue'
 import { reactive } from 'vue'
 import { inject, onUnmounted, onMounted, type ComponentInternalInstance, ref} from 'vue'
 import { encode, decode} from 'js-base64'
+import hand from '@/assets/3-4.png'
 
 /**
  * 它从 `inject` 函数返回 `StaticImg` 服务
@@ -224,7 +225,6 @@ export const useAdaptationIpadAndPhone = () => {
 }
 
 export const useQueryParmas = async () => {
-  console.log(1);
   let state = reactive({})
   
   state = await new Promise( (resolve) => {
@@ -283,25 +283,31 @@ export const useDeviceDire = (cb: (dire: 'H' | 'V') => void) => {
 export const useMagnifier = async (
   canvas: HTMLCanvasElement, 
   canvasId: string, 
-  { ansUrl,  quesUrl, instance  }: { ansUrl: string,  quesUrl: string, instance: ComponentInternalInstance}
+  { ansUrl,  quesUrl, instance, rate } 
+  : 
+  { ansUrl: string,  quesUrl: string, instance: ComponentInternalInstance, rate: number}
 ) => {
-  
+
+  const adaptatio = useAdaptationIpadAndPhone()
+
   let ctx: UniApp.CanvasContext = uni.createCanvasContext(canvasId)
 
+  const deviceWidthRate = uni.getSystemInfoSync().windowWidth / 375
+  
   const draw = async () => {
-    ctx.drawImage(quesUrl, 0, 0, 225, 386)
+    ctx.drawImage(quesUrl, 0, 0, 225 * deviceWidthRate, 386 * deviceWidthRate)
     ctx.save()
-    ctx.drawImage(ansUrl, 225, 0, 75, 386)
+    ctx.drawImage(ansUrl, 225 * deviceWidthRate , 0, 75  * deviceWidthRate, 386 * deviceWidthRate)
     ctx.save()
     ctx.draw()
     ctx.restore();
     // 创建 Image 对象并加载图片
-    
+  
     // 初始化放大镜的参数
-    const magnifierSize = 150; // 放大镜尺寸
-    const magnification = 1.5; // 放大倍数
-    const lineWidth = 4 // 放大镜边框宽度
-
+    const magnifierSize = 150 * deviceWidthRate  ; // 放大镜尺寸
+    const magnification = 1.5 ; // 放大倍数
+    const lineWidth = 4 * deviceWidthRate// 放大镜边框宽度
+    
     await new Promise( resolve => {
       useSchedulerOnce(() => {
         resolve(true)
@@ -314,15 +320,15 @@ export const useMagnifier = async (
         canvasId: canvasId,
         fileType: 'png',
         quality: 1,
-        destWidth: 300,
-        destHeight: 386,
+        destWidth: 300 * deviceWidthRate,
+        destHeight: 386 * deviceWidthRate,
         success: (res) => resolve( res.tempFilePath),
         fail: (error) => {
           console.error('canvasToTempFilePath failed: ', error);
         }
       }, instance);
     }) as string
-
+    
       function initMagnifier () {
         // 计算放大镜区域的位置和尺寸
         const startX = 0;
@@ -358,22 +364,23 @@ export const useMagnifier = async (
         );
         ctx.draw()
         ctx.restore();
-        console.log('初始化放大镜');
-        
       }
     
       initMagnifier();
 
+      // moveMagnifier({ touches: [{pageX:132 + i * 5, pageY: 340 + i * 12 }] })
+
       function moveMagnifier (event: TouchEvent) {
-        const mouseX = event.touches[0].pageX - canvas.getBoundingClientRect().left;
-        const mouseY = event.touches[0].pageY - canvas.getBoundingClientRect().top;
+         
+        const mouseX = (event.touches[0].pageX - canvas.getBoundingClientRect().left) * adaptatio * deviceWidthRate
+        const mouseY = (event.touches[0].pageY - canvas.getBoundingClientRect().top ) * adaptatio * deviceWidthRate
 
         // 清空 Canvas
         ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
     
         // 计算放大镜区域的位置和尺寸
-        const startX = mouseX - magnifierSize / 2;
-        const startY = mouseY - magnifierSize / 2;
+        const startX = (mouseX - magnifierSize / 2)
+        const startY = (mouseY - magnifierSize / 2)
         const width = magnifierSize;
         const height = magnifierSize;
     
@@ -401,6 +408,48 @@ export const useMagnifier = async (
         ctx.restore();
       }
 
+      const move = () => {
+
+          let x = canvas.getBoundingClientRect().left + magnifierSize / 2
+          let y = canvas.getBoundingClientRect().top + magnifierSize / 2
+  
+          // 设置目标位置
+          const targetX = 170;
+          const targetY = 460;
+  
+          // 设置动画参数
+          const animationDuration = 1000; // 1秒
+          let startTime: number = 0;
+          
+          // 动画函数
+          function animate() {
+  
+            if (!startTime) startTime = new Date().getTime();
+            const elapsedTime = new Date().getTime() - startTime;
+  
+            if (elapsedTime < animationDuration) {
+
+              // 计算当前位置
+              const progress = elapsedTime / animationDuration;
+              x = interpolate(x, targetX, progress);
+              y = interpolate(y, targetY, progress);
+              moveMagnifier({touches: [{pageX: x, pageY: y}]})
+  
+              // 继续下一帧绘制
+              requestAnimationFrame(animate);
+            }
+          }
+  
+          // 线性插值函数
+          function interpolate(start: number, end: number, progress: number) {
+            return start + (end - start) * progress;
+          }
+
+          requestAnimationFrame(animate);
+      }
+  
+      // move()
+
       // 监听鼠标移动事件,实现放大镜效果
       canvas.addEventListener("touchmove", moveMagnifier );
     }
@@ -414,7 +463,7 @@ export const useMagnifier = async (
     onUnmounted(() => {
       canvas.removeEventListener('touchmove', () => {})
     })
-
+    
     return {
       draw, clear
     }

+ 22 - 4
src/pages/GameView/index.vue

@@ -42,10 +42,13 @@
       <view class="desc" >为了更好的体验,请使用竖屏浏览</view>
     </view>
   </view> 
+
+  <img v-if="gamePlayed" style="width: 100vw;height: 100vh;position: fixed; z-index: 1000000;scale: 1;" :src="staticImg.intro" alt="">
 </template>
 
 
 <script setup lang="ts" >
+
 import { CardModeEnum, OpraModeEnum } from '@/enum/constant';
 import { onLoad } from '@dcloudio/uni-app';
 import { reactive, onMounted } from 'vue'
@@ -119,6 +122,9 @@ onLoad(query => {
 
 const riveAniRef = ref()
 
+// 0 代表已经播放过了 1 代表没有播放过
+const gamePlayed = ref<0 | 1>( uni.getStorageSync('played') ? 0 : 1)
+
 const navbarState = reactive({
   progress: 1,
   countdownTotal: 0,
@@ -151,9 +157,22 @@ const state = reactive<State>({
 
 const stx = useScheduler(() => {
   navbarState.countdownTotal++
-
 }, 1000)
 
+const getIntro = () => {
+  // 先判断有没有玩过,如果没有玩过
+
+  const played = uni.getStorageSync('played')
+  if (!played) {
+    uni.setStorageSync('played', 1)
+
+    useSchedulerOnce(() => {
+      gamePlayed.value = 0
+    }, 6000)
+  }
+
+}
+
 
 // 控制是否开启动画模式
 const changeMagnifier = (status: boolean) => {
@@ -251,6 +270,7 @@ const playAudio = () => {
 }
 
 // 获取试题集详情
+
 const GetCollectionDetailById = async () => {
   const { data } = await getCollectionDetailById(state.collectionId)
   if ( state.opraMode === OpraModeEnum.PRACTICE) {
@@ -275,7 +295,6 @@ const GetCardDetailById = async () => {
   }
 }
 
-
 // 返回上一级菜单 学习计划是返回 app 大赛是返回上一级路由
 const goback = () => {
   if (usePlatform() == 'web') {
@@ -285,7 +304,6 @@ const goback = () => {
   }
 }
 
-
 // 监听设备方向,如果是横屏,立马停止所有的计时
 useDeviceDire((dire: 'H' | 'V') => device.dire = dire)
 
@@ -296,9 +314,9 @@ onMounted(async () => {
   } else {
     GetCollectionDetailById()
   }
+  getIntro()
 })
 
-
 </script>
 
 

+ 5 - 0
src/pages/Home/index.vue

@@ -50,12 +50,16 @@
       </view>
 
     </view>
+
   </view>
+
+
 </template>
 
 
 <script lang="ts" setup >
 import { reactive } from 'vue'
+import { useStaticImg } from '@/hooks'
 
 const staticImg = {
   bgi: "https://app-resources-luojigou.luojigou.vip/Fh9jOblR745LCJKFSyxVnzPKy2Fn",
@@ -68,6 +72,7 @@ const staticImg = {
   tip: "https://app-resources-luojigou.luojigou.vip/FqEuou75mlFUcFqOS2Ph7wOax86n"
 };
 
+
   const state = reactive({
     videoUrl: 'https://cdn.video.luojigou.vip/liRfj13zjas7Tka6oAtnTmtYF1fT.mp4'
   })

+ 4 - 1
src/utils/static.ts

@@ -25,6 +25,7 @@ import luojigouDog from '@/assets/luojigou-dog.png'
 import dire from '@/assets/dire.gif'
 import magnifierClose from '@/assets/magnifier-close.png'
 import magnifierOpen from '@/assets/magnifier-open.png'
+import intro from '@/assets/intro.gif'
 
 export interface StaticImg {
   logo: string
@@ -57,6 +58,7 @@ export interface StaticImg {
   dire: string
   magnifierClose: string
   magnifierOpen: string
+  intro: string
 }
 
 let staticImg: Partial<StaticImg> = {
@@ -90,7 +92,8 @@ let staticImg: Partial<StaticImg> = {
   luojigouDog,
   dire,
   magnifierClose,
-  magnifierOpen
+  magnifierOpen,
+  intro
 }