|
@@ -1,98 +1,540 @@
|
|
<template>
|
|
<template>
|
|
- <view class="luojigou-board-v2" >
|
|
|
|
- <view class="process" >
|
|
|
|
- <span>{{process + 1}}</span>/6
|
|
|
|
- </view>
|
|
|
|
|
|
+ <view class="luojigou-board-v2" :style="{width: widget.boardWidth + 'px', height: widget.boardHeight + 'px'}">
|
|
|
|
+ <canvas canvas-id='canvasId' id="canvasId" style="width: 111px;height: 584px;position: fixed;left: -2000px;" ref="canvasDom" ></canvas>
|
|
<view class="board" >
|
|
<view class="board" >
|
|
|
|
+ <view class="process" >
|
|
|
|
+ <view class="count" >{{process + 1}}</view>
|
|
|
|
+ <view class="symbol" >/</view>
|
|
|
|
+ <view>6</view>
|
|
|
|
+ </view>
|
|
<view class="button-list" >
|
|
<view class="button-list" >
|
|
- <view class="button" v-for="(item, index) in buttonListCpd" :key="item" >
|
|
|
|
- <image class="icon" :src="staticImg[item]" alt="" />
|
|
|
|
|
|
+ <view class="button" :style="{opacity: index < process ? 0.4 : 1 }" v-for="(item, index) in buttonListCpd" :key="item" >
|
|
|
|
+ <image class="icon" :src="staticImg[item]" alt="" />
|
|
<image v-if="index < process" class="right-icon" :src="staticImg.rightIcon" alt="" />
|
|
<image v-if="index < process" class="right-icon" :src="staticImg.rightIcon" alt="" />
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
- <view :class="['question-card', aniState ? 'question-card-small' : 'question-card-ani']" >
|
|
|
|
- <!-- <image :src="staticImg.green" alt="" /> -->
|
|
|
|
|
|
+ <view class="question-card" >
|
|
|
|
+ <view :class="questionCardAni" >
|
|
|
|
+ <image class="ques-item-url" :src="quesCard.current" />
|
|
|
|
+ </view>
|
|
|
|
+ <view class="ques-card-next" >
|
|
|
|
+ <image class="ques-item-url" :src="quesCard.next" />
|
|
|
|
+ </view>
|
|
|
|
+ <view :class="questionAni" @click="previewCard" >
|
|
|
|
+ <image class="card" :src="props.card.board.quesUrl" alt="" />
|
|
|
|
+ <image class="open-icon" v-if="aniState" :src="staticImg.openIcon" />
|
|
|
|
+ </view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="answer" >
|
|
<view class="answer" >
|
|
- <view class="answer-list" >
|
|
|
|
- <view class="answer-item" >
|
|
|
|
-
|
|
|
|
|
|
+ <!-- :key="keyCount" -->
|
|
|
|
+ <view class="answer-list" >
|
|
|
|
+ <view
|
|
|
|
+ class="answer-item"
|
|
|
|
+ v-for="(item, index) in ansList"
|
|
|
|
+ :key="item.id"
|
|
|
|
+ :style="{top: item.top + 'px', left: item.left + 'px'}"
|
|
|
|
+ :animation="aniListRef[index]"
|
|
|
|
+ @click="selectAnswer(item)"
|
|
|
|
+ >
|
|
|
|
+ <image class="ans-img" :src="item.url" />
|
|
|
|
+ <view :class="ansResultClass" v-if="item.select" >
|
|
|
|
+ <image :src="ans === 1 ? staticImg.success : staticImg.wrong" />
|
|
|
|
+ </view>
|
|
|
|
+ <image class="hand" v-if="tipState && item.isAns" :src="staticImg.hand" />
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
+
|
|
|
|
+ <view class="opra-container" >
|
|
|
|
+ <view class="read" :style="{opacity: !readState ? 0 : 1}" id="lottie-dom-read" @click="stopReadQuestion" > </view>
|
|
|
|
+ <image class="read" v-if="!readState" @click="readQuestion" :src="staticImg.read" />
|
|
|
|
+ <image class="tip" @click="openTip" :src="staticImg.tip" />
|
|
|
|
+ </view>
|
|
|
|
+
|
|
|
|
+ <view class="lottie-dom" id="lottie-dom-wrong"></view>
|
|
|
|
+ <view class="lottie-dom" id="lottie-dom-success"></view>
|
|
|
|
+
|
|
|
|
+ <view class="preview-card" v-if="previewState" @click="previewCard" >
|
|
|
|
+ <image :src="props.card.board.quesUrl" />
|
|
|
|
+ </view>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts" >
|
|
<script setup lang="ts" >
|
|
-import { useStaticImg, useSchedulerOnce } from '@/hooks'
|
|
|
|
-import { computed, onMounted, ref } from 'vue';
|
|
|
|
|
|
+import { useStaticImg,useScheduler, useSchedulerOnce, useAudioMange } from '@/hooks'
|
|
|
|
+import { computed, ref, nextTick, watch, onMounted, getCurrentInstance } from 'vue';
|
|
|
|
+import { useCalcQuantityV2Store } from '@/store/gameTool';
|
|
|
|
+import ao from '@/audio/ao.mp3'
|
|
|
|
+import successMp3 from '@/audio/success.mp3'
|
|
|
|
+import wrongMp3 from '@/audio/wrong.mp3'
|
|
|
|
+import timeoutMp3 from '@/audio/timeout.mp3'
|
|
|
|
+import lottie from 'lottie-web'
|
|
|
|
|
|
interface IProps {
|
|
interface IProps {
|
|
- process: number
|
|
|
|
-}
|
|
|
|
|
|
+ card: {
|
|
|
|
+ board: API.BoardV2,
|
|
|
|
+ cardAble: string
|
|
|
|
+ cardDesc: string
|
|
|
|
+ cardName: string
|
|
|
|
+ cardType: number
|
|
|
|
+ audio: string
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+interface AnsList {
|
|
|
|
+ top: number,
|
|
|
|
+ left: number,
|
|
|
|
+ url: string,
|
|
|
|
+ isAns: boolean,
|
|
|
|
+ select: boolean
|
|
|
|
+ id: string
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const {
|
|
|
|
+ proxy: { $forceUpdate },
|
|
|
|
+}: any = getCurrentInstance();
|
|
|
|
+
|
|
|
|
+const { windowWidth, windowHeight } = uni.getSystemInfoSync()
|
|
|
|
+
|
|
|
|
+const isPad = windowHeight / windowWidth > 0.6
|
|
|
|
+
|
|
|
|
+const posValue = isPad ? 180 : 125
|
|
|
|
+
|
|
|
|
+const ansListData: AnsList[] = [
|
|
|
|
+ {top: 0, left: 0, url: '', isAns: false, select: false, id: '0' },
|
|
|
|
+ {top: 0, left: posValue, url: '', isAns: false, select: false, id: '1'},
|
|
|
|
+ {top: posValue, left: 0, url: '', isAns: false, select: false, id: '2'},
|
|
|
|
+ {top: posValue, left: posValue, url: '', isAns: false, select: false, id: '3'}
|
|
|
|
+]
|
|
|
|
+
|
|
|
|
+const props = defineProps<IProps>()
|
|
|
|
|
|
const staticImg = useStaticImg()
|
|
const staticImg = useStaticImg()
|
|
|
|
|
|
-const aniState = ref<boolean>(false)
|
|
|
|
|
|
+const audioMange = useAudioMange()
|
|
|
|
+
|
|
|
|
+const luojigouBoardV2Dom = ref()
|
|
|
|
+
|
|
|
|
+const calcQuantityV2Store = useCalcQuantityV2Store()
|
|
|
|
+
|
|
|
|
+const process = ref(0)
|
|
|
|
|
|
const buttonList = ['red', 'green', 'blue', 'orange', 'purple', 'yellow']
|
|
const buttonList = ['red', 'green', 'blue', 'orange', 'purple', 'yellow']
|
|
|
|
|
|
-const buttonListCpd = computed(() => buttonList.slice(0, props.process + 1))
|
|
|
|
|
|
+const buttonListCpd = computed(() => buttonList.slice(0, process.value + 1))
|
|
|
|
|
|
-const props = defineProps<IProps>()
|
|
|
|
|
|
+const keyCount = ref(0)
|
|
|
|
|
|
-useSchedulerOnce(() => {
|
|
|
|
- aniState.value = true
|
|
|
|
-}, 1900)
|
|
|
|
|
|
+const canvasDom = ref()
|
|
|
|
|
|
|
|
+const ans = ref(0) // 0 未选择 1 正确 2 错误
|
|
|
|
|
|
-// 卡片展示的1s动画
|
|
|
|
-onMounted(() => {
|
|
|
|
|
|
+const ansList = ref<AnsList[]>(JSON.parse(JSON.stringify(ansListData)))
|
|
|
|
+
|
|
|
|
+const answerPictureList = ref<string[]>([])
|
|
|
|
+
|
|
|
|
+const tipState = ref<boolean>(false)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+const questionAni = ref(['ques-url'])
|
|
|
|
+
|
|
|
|
+const ansResultClass = ref(['result'])
|
|
|
|
+
|
|
|
|
+const questionCardAni = ref(['ques-card-current'])
|
|
|
|
+
|
|
|
|
+const aniState = ref(false)
|
|
|
|
+
|
|
|
|
+const previewState = ref(false)
|
|
|
|
+
|
|
|
|
+const widget = { boardWidth: 581 / (812 / windowWidth), boardHeight: 398 / (812 / windowWidth)}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+const emits = defineEmits(['loadingStart', 'loadingEnd', 'gameover'])
|
|
|
|
+
|
|
|
|
+const readState = ref(false)
|
|
|
|
+
|
|
|
|
+const stopReadQuestion = () => {
|
|
|
|
+ readState.value = false
|
|
|
|
+ audioMange.destroy()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const readQuestion = () => {
|
|
|
|
+
|
|
|
|
+ audioMange.play(props.card.audio)
|
|
|
|
+ readState.value = true
|
|
|
|
+ audioMange.onplayend(() => {
|
|
|
|
+ lottieReadRef.value.stop()
|
|
|
|
+ readState.value = false
|
|
|
|
+ })
|
|
|
|
+ lottieReadRef.value.play()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const ansPictureRandom = () => {
|
|
|
|
+
|
|
|
|
+ const r: number[] = []
|
|
|
|
+
|
|
|
|
+ const arr = [0, 1, 2, 3, 4, 5]
|
|
|
|
+
|
|
|
|
+ const count = 3
|
|
|
|
|
|
|
|
+ const ansIndex = props.card.board.list[process.value].ansIndex
|
|
|
|
+
|
|
|
|
+ const randomArr = arr.filter( item => item !== ansIndex )
|
|
|
|
+
|
|
|
|
+ for (let i = 0; i < count; i++) {
|
|
|
|
+ const randomCount = randomArr[ Math.floor(Math.random() * 5)]
|
|
|
|
+ if (r.includes(randomCount)) {
|
|
|
|
+ i--
|
|
|
|
+ } else {
|
|
|
|
+ r.push(randomCount)
|
|
|
|
+ ansList.value[i].url = answerPictureList.value[randomCount]
|
|
|
|
+ ansList.value[i].isAns = false
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const rc = Math.floor(Math.random() * 4)
|
|
|
|
+
|
|
|
|
+ ansList.value[3].url = ansList.value[rc].url
|
|
|
|
+
|
|
|
|
+ ansList.value[3].isAns = false
|
|
|
|
+
|
|
|
|
+ ansList.value[rc].url = answerPictureList.value[ansIndex]
|
|
|
|
+
|
|
|
|
+ ansList.value[rc].isAns = true
|
|
|
|
+
|
|
|
|
+ console.log( ansList.value[rc].url);
|
|
|
|
+
|
|
|
|
+ $forceUpdate()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const reset = () => {
|
|
|
|
+
|
|
|
|
+ ansResultClass.value = ['result']
|
|
|
|
+
|
|
|
|
+ useSchedulerOnce(() => {
|
|
|
|
+ emits('gameover', process.value, () => {
|
|
|
|
+ ansList.value.forEach( item => item.id = Math.random().toString(16).slice(2) )
|
|
|
|
+ questionCardAni.value.push('ques-card-ani')
|
|
|
|
+ useSchedulerOnce(() => {
|
|
|
|
+ process.value++
|
|
|
|
+ useSchedulerOnce(() => {
|
|
|
|
+ questionCardAni.value.pop()
|
|
|
|
+ }, 1000)
|
|
|
|
+ }, 1000)
|
|
|
|
+ useSchedulerOnce(() => {
|
|
|
|
+ ansPictureRandom()
|
|
|
|
+ }, 1000)
|
|
|
|
+
|
|
|
|
+ })
|
|
|
|
+ }, 1200)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const clearTimeRef = ref()
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+const selectAnswer = (record: {isAns: boolean, select: boolean}) => {
|
|
|
|
+ // 关闭一些状态
|
|
|
|
+ readState.value = false
|
|
|
|
+ tipState.value = false
|
|
|
|
+ ansList.value.forEach( item => item.select = false)
|
|
|
|
+ if (ansResultClass.value.length === 2) ansResultClass.value.pop()
|
|
|
|
+ record.select = true
|
|
|
|
+ lottieReadRef.value.stop()
|
|
|
|
+ clearTimeRef.value && clearTimeRef.value()
|
|
|
|
+ // 关闭一些状态
|
|
|
|
+
|
|
|
|
+ if (record.isAns) {
|
|
|
|
+
|
|
|
|
+ emits('loadingStart')
|
|
|
|
+
|
|
|
|
+ ansResultClass.value.push('success')
|
|
|
|
+
|
|
|
|
+ ans.value = 1
|
|
|
|
+
|
|
|
|
+ lottieSuccessRef.value.play()
|
|
|
|
+
|
|
|
|
+ if (calcQuantityV2Store.wrongCount <= 1) {
|
|
|
|
+ audioMange.play(successMp3)
|
|
|
|
+ } else {
|
|
|
|
+ audioMange.play(wrongMp3)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ clearTimeRef.value = useSchedulerOnce(() => {
|
|
|
|
+ reset()
|
|
|
|
+ record.select = false
|
|
|
|
+ ans.value = 0
|
|
|
|
+ }, 1000)
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+ ansResultClass.value.push('wrong')
|
|
|
|
+ ans.value = 2
|
|
|
|
+ audioMange.play(ao)
|
|
|
|
+ calcQuantityV2Store.wrongCount++
|
|
|
|
+ clearTimeRef.value = useSchedulerOnce(() => {
|
|
|
|
+ record.select = false
|
|
|
|
+ ansResultClass.value.pop()
|
|
|
|
+ ans.value = 0
|
|
|
|
+ }, 2000)
|
|
|
|
+
|
|
|
|
+ lottieWrongRef.value.play()
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ calcQuantityV2Store.totalCount++
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const quesCard = computed(() => {
|
|
|
|
+ if (props.card.board.list && process.value <= 6) {
|
|
|
|
+ return {
|
|
|
|
+ current: props.card.board.list[process.value].quesImg,
|
|
|
|
+ next: process.value === 6 ? '' : props.card.board.list[process.value].quesImg,
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return {
|
|
|
|
+ current: '',
|
|
|
|
+ next: ''
|
|
|
|
+ }
|
|
})
|
|
})
|
|
|
|
|
|
|
|
+watch(
|
|
|
|
+ () => props.card.board.ansUrl,
|
|
|
|
+ async () => {
|
|
|
|
+ console.log('card.board.quesUrl:', props.card.board.ansUrl);
|
|
|
|
+
|
|
|
|
+ if ( props.card.board.quesUrl) {
|
|
|
|
+ nextTick(async () => {
|
|
|
|
+ await croppingPicture(props.card.board.ansUrl)
|
|
|
|
+ nextTick(() => {
|
|
|
|
+ ansPictureRandom()
|
|
|
|
+ readQuestion()
|
|
|
|
+ questionAni.value.push('question-card-ani')
|
|
|
|
+ useSchedulerOnce(() => {
|
|
|
|
+ questionAni.value.push('question-card-small')
|
|
|
|
+ aniState.value = true
|
|
|
|
+ }, 1700)
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ deep: true,
|
|
|
|
+ // immediate: true
|
|
|
|
+ }
|
|
|
|
+)
|
|
|
|
|
|
-</script>
|
|
|
|
|
|
+// 预览题卡
|
|
|
|
+const previewCard = () => previewState.value = !previewState.value
|
|
|
|
+
|
|
|
|
+const openTip = () => {
|
|
|
|
+ console.log('tipState.value = true');
|
|
|
|
+
|
|
|
|
+ tipState.value = true
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const aniListRef = ref()
|
|
|
|
+// 动画列表
|
|
|
|
+const aniList = () => {
|
|
|
|
+ const a1 = uni.createAnimation({duration: 300, timingFunction: 'ease'})
|
|
|
|
+ const a2 = uni.createAnimation({duration: 300, timingFunction: 'ease'})
|
|
|
|
+ const a3 = uni.createAnimation({duration: 300, timingFunction: 'ease'})
|
|
|
|
+ const a4 = uni.createAnimation({duration: 300, timingFunction: 'ease'})
|
|
|
|
+ return [
|
|
|
|
+ a1.top(60).left(60).step({delay: 0}).top(0).left(0).step({delay: 300}).export(),
|
|
|
|
+ a2.top(60).left(60).step({delay: 0}).top(0).left(posValue).step({delay: 300}).export(),
|
|
|
|
+ a3.top(60).left(60).step({delay: 0}).top(posValue).left(0).step({delay: 300}).export(),
|
|
|
|
+ a4.top(60).left(60).step({delay: 0}).top(posValue).left(posValue).step({delay: 300}).export(),
|
|
|
|
+ ]
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+aniListRef.value = aniList()
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+// 切割答案的图片
|
|
|
|
+const croppingPicture = (img: string) => {
|
|
|
|
+
|
|
|
|
+ return new Promise((resolve) => {
|
|
|
|
+ const ctx = uni.createCanvasContext('canvasId')
|
|
|
|
+
|
|
|
|
+ const imgae = new Image()
|
|
|
|
+
|
|
|
|
+ imgae.src = img
|
|
|
|
+
|
|
|
|
+ imgae.onload = () => {
|
|
|
|
+ console.log(imgae.width, imgae.height);
|
|
|
|
+
|
|
|
|
+ // const imgPng = img.endsWith('jpeg') ? img.replace('jpeg', 'png') : img
|
|
|
|
|
|
|
|
+ // console.log('imgPng:', imgPng);
|
|
|
|
+
|
|
|
|
+ uni.downloadFile({
|
|
|
|
+ url: img,
|
|
|
|
+ header: {
|
|
|
|
+ "Content-Type": "application/x-www-form-urlencoded",
|
|
|
|
+ "Content-Disposition": 'attachment;filename=',
|
|
|
|
+ },
|
|
|
|
+ success(result) {
|
|
|
|
+ nextTick(() => {
|
|
|
|
+ console.log('会出错嘛:', result);
|
|
|
|
+
|
|
|
|
+//
|
|
|
|
+ // canvasDom.value.width = imgae.width / 4
|
|
|
|
+ // canvasDom.value.height = imgae.height / 4
|
|
|
|
+
|
|
|
|
+ // ctx.drawImage(result.tempFilePath, 0, 0, 222, imgae.height / 2)
|
|
|
|
+ ctx.drawImage(result.tempFilePath, 0, 0, imgae.width / 8, imgae.height / 8)
|
|
|
|
+
|
|
|
|
+ ctx.draw(false, () => {
|
|
|
|
+ useSchedulerOnce(() => {
|
|
|
|
+ for (let i = 0; i < 6; i++) {
|
|
|
|
+ uni.canvasToTempFilePath({
|
|
|
|
+ x: 0,
|
|
|
|
+ y: 184 * i / 4 + 12 * i / 4,
|
|
|
|
+ width: 222 / 4,
|
|
|
|
+ height: 184 / 4,
|
|
|
|
+ canvasId: 'canvasId',
|
|
|
|
+
|
|
|
|
+ success: function(res) {
|
|
|
|
+
|
|
|
|
+ answerPictureList.value.push(res.tempFilePath)
|
|
|
|
+ resolve(true)
|
|
|
|
+ },
|
|
|
|
+ fail(result) {
|
|
|
|
+ console.log('canvasToTempFilePath:', result);
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+ complete(result) {
|
|
|
|
+ console.log('complete--->canvasToTempFilePath:', result);
|
|
|
|
+ },
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }, 5)
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+ fail(result) {
|
|
|
|
+ console.log('downloadFile:', result);
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const lottieWrongRef = ref()
|
|
|
|
+
|
|
|
|
+const lottieSuccessRef = ref()
|
|
|
|
+
|
|
|
|
+const lottieReadRef = ref()
|
|
|
|
+
|
|
|
|
+// lottie-web
|
|
|
|
+const initLottieWeb = () => {
|
|
|
|
+ lottieWrongRef.value = lottie.loadAnimation({
|
|
|
|
+ container: document.getElementById('lottie-dom-wrong'),
|
|
|
|
+ renderer: 'svg',
|
|
|
|
+ loop: false,
|
|
|
|
+ autoplay: false,
|
|
|
|
+ path: 'https://luojigou-game-res.luojigou.vip/lottie-wrong.json',
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ lottieWrongRef.value.onComplete = function () {lottieWrongRef.value.stop() }
|
|
|
|
+
|
|
|
|
+ lottieSuccessRef.value = lottie.loadAnimation({
|
|
|
|
+ container: document.getElementById('lottie-dom-success'),
|
|
|
|
+ renderer: 'svg',
|
|
|
|
+ loop: false,
|
|
|
|
+ autoplay: false,
|
|
|
|
+ path: 'https://luojigou-game-res.luojigou.vip/lottie-success-1.json'
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ lottieSuccessRef.value.onComplete = function () {lottieSuccessRef.value.stop() }
|
|
|
|
+
|
|
|
|
+ lottieReadRef.value = lottie.loadAnimation({
|
|
|
|
+ container: document.getElementById('lottie-dom-read'),
|
|
|
|
+ renderer: 'svg',
|
|
|
|
+ loop: true,
|
|
|
|
+ autoplay: false,
|
|
|
|
+ path: 'https://luojigou-game-res.luojigou.vip/trump.json'
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ lottieReadRef.value.stop()
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+onMounted(() => {
|
|
|
|
+ initLottieWeb()
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+const stx = useScheduler(() => audioMange.play(timeoutMp3), 15000)
|
|
|
|
+stx.start()
|
|
|
|
+
|
|
|
|
+document.body.addEventListener('click', () => {
|
|
|
|
+ stx.stop()
|
|
|
|
+ stx.start()
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+</script>
|
|
|
|
|
|
<style lang="less" scoped >
|
|
<style lang="less" scoped >
|
|
.luojigou-board-v2 {
|
|
.luojigou-board-v2 {
|
|
position: relative;
|
|
position: relative;
|
|
- .process {
|
|
|
|
- width: 32rpx;
|
|
|
|
- height: 65rpx;
|
|
|
|
- background: #FFC047;
|
|
|
|
- position: absolute;
|
|
|
|
- top: 61rpx;
|
|
|
|
- left: -5rpx;
|
|
|
|
- font-size: 10rpx;
|
|
|
|
- font-family: PingFang SC-Semibold, PingFang SC;
|
|
|
|
- font-weight: 400;
|
|
|
|
- color: #FFFFFF;
|
|
|
|
- white-space: normal;
|
|
|
|
- display: flex;
|
|
|
|
- justify-content: center;
|
|
|
|
- align-items: center;
|
|
|
|
- border-top-left-radius: 14rpx;
|
|
|
|
- border-bottom-left-radius: 14rpx;
|
|
|
|
- span {
|
|
|
|
- font-size: 16rpx;
|
|
|
|
- font-weight: 600;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
.board {
|
|
.board {
|
|
- width: 354rpx;
|
|
|
|
- height: 354rpx;
|
|
|
|
- background: url('@/assets/GameViewV2/board.png') no-repeat top right;
|
|
|
|
|
|
+ width: 60%;
|
|
|
|
+ height: 100%;
|
|
|
|
+ background: url('@/assets/GameViewV2/board.png') no-repeat top left;
|
|
|
|
+ background-size: 100%;
|
|
|
|
+ position: relative;
|
|
|
|
+ top: 10%;
|
|
|
|
+ .process {
|
|
|
|
+ width: 10.5%;
|
|
|
|
+ height: 16.33%;
|
|
|
|
+ background: #FFC047;
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 16.33%;
|
|
|
|
+ left: -10.5%;
|
|
|
|
+ z-index: 2;
|
|
|
|
+ // font-size: 90%;
|
|
|
|
+ font-family: PingFang SC-Semibold, PingFang SC;
|
|
|
|
+ font-weight: 400;
|
|
|
|
+ color: #FFFFFF;
|
|
|
|
+ white-space: normal;
|
|
|
|
+ display: flex;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ align-items: center;
|
|
|
|
+ border-top-left-radius: 14rpx;
|
|
|
|
+ border-bottom-left-radius: 14rpx;
|
|
|
|
+ vertical-align: bottom;
|
|
|
|
+ .count {
|
|
|
|
+ font-size: 130%;
|
|
|
|
+ font-weight: 600;
|
|
|
|
+ vertical-align: bottom;
|
|
|
|
+ margin-bottom: 6%;
|
|
|
|
+ }
|
|
|
|
+ .symbol {
|
|
|
|
+ margin-bottom: 6%;
|
|
|
|
+ }
|
|
|
|
+ view {
|
|
|
|
+ display: inline-block;
|
|
|
|
+ line-height: 24px;
|
|
|
|
+ vertical-align: bottom;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
.button-list {
|
|
.button-list {
|
|
|
|
+ width: 20%;
|
|
|
|
+ height: 60%;
|
|
position: absolute;
|
|
position: absolute;
|
|
- top: 24rpx;
|
|
|
|
- right: 12rpx;
|
|
|
|
|
|
+ top: 6%;
|
|
|
|
+ right: -6%;
|
|
.button {
|
|
.button {
|
|
- width: 36rpx;
|
|
|
|
- height: 36rpx;
|
|
|
|
- margin-bottom: 11rpx;
|
|
|
|
|
|
+ width: 55%;
|
|
|
|
+ height: 16%;
|
|
|
|
+ margin-bottom: 17%;
|
|
display: flex;
|
|
display: flex;
|
|
justify-content: center;
|
|
justify-content: center;
|
|
align-items: center;
|
|
align-items: center;
|
|
@@ -103,8 +545,8 @@ onMounted(() => {
|
|
display: block;
|
|
display: block;
|
|
}
|
|
}
|
|
.right-icon {
|
|
.right-icon {
|
|
- width: 20rpx;
|
|
|
|
- height: 20rpx;
|
|
|
|
|
|
+ width: 60%;
|
|
|
|
+ height: 60%;
|
|
position: absolute;
|
|
position: absolute;
|
|
top: 50%;
|
|
top: 50%;
|
|
left: 50%;
|
|
left: 50%;
|
|
@@ -113,43 +555,261 @@ onMounted(() => {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.question-card {
|
|
.question-card {
|
|
- width: 254rpx;
|
|
|
|
- height: 284rpx;
|
|
|
|
- background-color: #fff;
|
|
|
|
- border-radius: 20rpx;
|
|
|
|
|
|
+ width: 78%;
|
|
|
|
+ height: 72%;
|
|
position: absolute;
|
|
position: absolute;
|
|
- top: 12rpx;
|
|
|
|
- left: 41rpx;
|
|
|
|
- transform-origin: 100% 0%;
|
|
|
|
- image {
|
|
|
|
|
|
+ top: 6%;
|
|
|
|
+ left: 4%;
|
|
|
|
+ // background-color: #fff;
|
|
|
|
+ border-radius: 6%;
|
|
|
|
+ z-index: 11;
|
|
|
|
+ .ques-card-current {
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 100%;
|
|
|
|
+ background-color: #fff;
|
|
|
|
+ border-radius: 6%;
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 50%;
|
|
|
|
+ left: 50%;
|
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
|
+ z-index: 11;
|
|
|
|
+ transform-origin: 50% 50%;
|
|
|
|
+ .ques-item-url {
|
|
|
|
+ width: 76%;
|
|
|
|
+ height: 79%;
|
|
|
|
+ display: block;
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 50%;
|
|
|
|
+ left: 50%;
|
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
|
+ z-index: 1;
|
|
|
|
+ border-radius: 6%;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .ques-card-ani {
|
|
|
|
+ animation: ques-card-current-ani 0.9s;
|
|
|
|
+ }
|
|
|
|
+ @keyframes ques-card-current-ani {
|
|
|
|
+ 0% {
|
|
|
|
+ rotate: 0deg;
|
|
|
|
+ left: 50%;
|
|
|
|
+ opacity: 1;
|
|
|
|
+ }
|
|
|
|
+ 33% {
|
|
|
|
+ rotate: 4deg;
|
|
|
|
+ left: 50%;
|
|
|
|
+ opacity: 1;
|
|
|
|
+ }
|
|
|
|
+ 66% {
|
|
|
|
+ rotate: 0deg;
|
|
|
|
+ left: 50%;
|
|
|
|
+ opacity: 1;
|
|
|
|
+ }
|
|
|
|
+ 100% {
|
|
|
|
+ opacity: 0;
|
|
|
|
+ left: 20%;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .ques-card-next {
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 100%;
|
|
|
|
+ background-color: #fff;
|
|
|
|
+ border-radius: 6%;
|
|
|
|
+ .ques-item-url {
|
|
|
|
+ width: 76%;
|
|
|
|
+ height: 79%;
|
|
|
|
+ display: block;
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 50%;
|
|
|
|
+ left: 50%;
|
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
|
+ z-index: 1;
|
|
|
|
+ border-radius: 6%;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .ques-url {
|
|
width: 100%;
|
|
width: 100%;
|
|
height: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
display: block;
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 0%;
|
|
|
|
+ left: 0%;
|
|
|
|
+ z-index: 22;
|
|
|
|
+ transform-origin: 96% 4%;
|
|
|
|
+ border-radius: 6%;
|
|
|
|
+ display: flex;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ align-items: center;
|
|
|
|
+ background-color: #fff;
|
|
|
|
+ .card {
|
|
|
|
+ width: 58%;
|
|
|
|
+ height: 100%;
|
|
|
|
+ border-radius: 6%;
|
|
|
|
+ object-fit: contain;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ .open-icon {
|
|
|
|
+ width: 30%;
|
|
|
|
+ height: 30%;
|
|
|
|
+ position: absolute;
|
|
|
|
+ bottom: 2vw;
|
|
|
|
+ right: 8vw;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
.question-card-ani {
|
|
.question-card-ani {
|
|
- animation: card-ani 1s ease 1s;
|
|
|
|
|
|
+ animation: card-ani 1s ease 0.9s;
|
|
}
|
|
}
|
|
|
|
|
|
.question-card-small {
|
|
.question-card-small {
|
|
- scale: 20%;
|
|
|
|
|
|
+ transform: scale(32%) translateX(20%);
|
|
|
|
+ background-color: transparent !important;
|
|
|
|
+ .card {
|
|
|
|
+ border: 2px solid #D0D0D0;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.answer {
|
|
.answer {
|
|
|
|
+ width: 45%;
|
|
|
|
+ height: 60%;
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 50%;
|
|
|
|
+ left: 66%;
|
|
|
|
+ transform: translateY(-50%);
|
|
.answer-list {
|
|
.answer-list {
|
|
-
|
|
|
|
|
|
+ display: grid;
|
|
|
|
+ grid-template-columns: 11vw 6vw 11vw;
|
|
|
|
+ grid-template-rows: 11vw 6vw 11vw;
|
|
|
|
+ // width: 34%;
|
|
|
|
+ // height: 37%;
|
|
|
|
+ .answer-item {
|
|
|
|
+ width: 11vw;
|
|
|
|
+ height: 11vw;
|
|
|
|
+ background-color: #fff;
|
|
|
|
+ box-shadow: 0px 0px 1vw 0px #FFC04C;
|
|
|
|
+ border-radius: 16%;
|
|
|
|
+ border: 0.5vw solid rgba(255, 192, 76, 0.2);
|
|
|
|
+ position: absolute;
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ // overflow: hidden;
|
|
|
|
+ .ans-img {
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 100%;
|
|
|
|
+ border-radius: 16%;
|
|
|
|
+ object-fit: cover;
|
|
|
|
+ }
|
|
|
|
+ .hand {
|
|
|
|
+ width: 6vw;
|
|
|
|
+ height: 6vw;
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 50%;
|
|
|
|
+ left: 50%;
|
|
|
|
+ animation: hand-ani 1s infinite;
|
|
|
|
+ }
|
|
|
|
+ .result {
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 100%;
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 50%;
|
|
|
|
+ left: 50%;
|
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
|
+ display: flex;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ align-items: center;
|
|
|
|
+ border-radius: 16%;
|
|
|
|
+ image {
|
|
|
|
+ width: 37.5%;
|
|
|
|
+ height: 37.5%;
|
|
|
|
+ display: block;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .success {
|
|
|
|
+ background: rgba(34,193,52,0.5);
|
|
|
|
+ border: 0.5vw solid #22C134;
|
|
|
|
+ }
|
|
|
|
+ .wrong {
|
|
|
|
+ background: rgba(234,71,71,0.5);
|
|
|
|
+ border: 0.5vw solid #EA4747;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+.opra-container {
|
|
|
|
+ position: fixed;
|
|
|
|
+ right: 3vw;
|
|
|
|
+ bottom: 3vw;
|
|
|
|
+ display: flex;
|
|
|
|
+ flex-direction: column;
|
|
|
|
+ .read {
|
|
|
|
+ width: 5.5vw;
|
|
|
|
+ height: 5.5vw;
|
|
|
|
+ position: absolute;
|
|
|
|
+ bottom: 6.5vw;
|
|
|
|
+ }
|
|
|
|
+ image {
|
|
|
|
+ width: 5.5vw;
|
|
|
|
+ height: 5.5vw;
|
|
|
|
+ margin-top: 2vw;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+.lottie-dom {
|
|
|
|
+ width: 24vw;
|
|
|
|
+ height: 24vw;
|
|
|
|
+ position: fixed;
|
|
|
|
+ left: 0;
|
|
|
|
+ bottom: 0;
|
|
|
|
+ z-index: 120;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+.preview-card {
|
|
|
|
+ width: 100vw;
|
|
|
|
+ height: 100vh;
|
|
|
|
+ background-color: rgba(0, 0, 0, 0.6);
|
|
|
|
+ position: fixed;
|
|
|
|
+ top: 0;
|
|
|
|
+ left: 0;
|
|
|
|
+ z-index: 11;
|
|
|
|
+ display: flex;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ align-items: center;
|
|
|
|
+ image {
|
|
|
|
+ width: 58vh;
|
|
|
|
+ height: 100vh;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+@keyframes hand-ani {
|
|
|
|
+ 0% {
|
|
|
|
+ transform: translate(0vw, 0vw)
|
|
|
|
+ };
|
|
|
|
+ 50% {
|
|
|
|
+ transform: translate(2vw, 2vw)
|
|
|
|
+ };
|
|
|
|
+ 100% {
|
|
|
|
+ transform: translate(0vw, 0vw)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
|
|
@keyframes card-ani {
|
|
@keyframes card-ani {
|
|
0% {
|
|
0% {
|
|
- scale: 100%;
|
|
|
|
|
|
+ transform: scale(100%);
|
|
|
|
+ };
|
|
|
|
+ 78% {
|
|
|
|
+ transform: scale(100%);
|
|
|
|
+ background-color: #fff;
|
|
|
|
+ };
|
|
|
|
+ 80% {
|
|
|
|
+ background-color: transparent;
|
|
};
|
|
};
|
|
100% {
|
|
100% {
|
|
- scale: 20%;
|
|
|
|
|
|
+ transform: scale(32%) translateX(20%);
|
|
|
|
+ background-color: transparent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|
|
</style>
|