hldy_app/component/public/newgame/arrowkeys.vue

237 lines
6.3 KiB
Vue

<template>
<view class="move-circle" :style="{ bottom: `${movebottom}rpx`, left: `${moveleft}rpx` }">
<!-- 返回 -->
<view
:class="beblue === 5 ? 'click-box-target' : 'click-box'"
@tap="onTap(5)"
@longpress="() => onLongPressStart(5)"
@touchend="onLongPressEnd"
@touchcancel="onLongPressEnd"
style="position: relative;"
>
<image :src="`/static/index/newruler/${beblue === 5 ? 1:0}.png`" style="position: absolute;width: 100%; height: 100%;" />
<span style="z-index: 1;font-size: 30rpx;" :class="beblue === 5 ? 'grad-text' : ''">{{leftbuttonname}}</span>
</view>
<!-- -->
<view
:class="beblue === 0 ? 'click-box-target' : 'click-box'"
@tap="onTap(0)"
@longpress="() => onLongPressStart(0)"
@touchend="onLongPressEnd"
@touchcancel="onLongPressEnd"
style="position: relative;"
>
<image :src="`/static/index/newruler/${beblue === 0 ? 1:0}.png`" style="position: absolute;width: 100%; height: 100%;" />
<image :src="`/static/index/newruler/fangxiang${beblue===0 ? 'target' : ''}.png`" class="image-photo" />
</view>
<!-- 确定 -->
<view
:class="beblue === 4 ? 'click-box-target' : 'click-box'"
@tap="onTap(4)"
@longpress="() => onLongPressStart(4)"
@touchend="onLongPressEnd"
@touchcancel="onLongPressEnd"
style="position: relative;"
>
<image :src="`/static/index/newruler/${beblue === 4 ? 1:0}.png`" style="position: absolute;width: 100%; height: 100%;" />
<span style="z-index: 1;font-size: 30rpx;" :class="beblue === 4 ? 'grad-text' : ''">{{rightbuttonname}}</span>
</view>
<!-- -->
<view
:class="beblue === 3 ? 'click-box-target' : 'click-box'"
@tap="onTap(3)"
@longpress="() => onLongPressStart(3)"
@touchend="onLongPressEnd"
@touchcancel="onLongPressEnd"
style="position: relative;"
>
<image :src="`/static/index/newruler/${beblue === 3 ? 1:0}.png`" style="position: absolute;width: 100%; height: 100%;" />
<image style="transform: rotate(270deg);transform-origin: center;" :src="`/static/index/newruler/fangxiang${beblue===3 ? 'target' : ''}.png`" class="image-photo" />
</view>
<!-- -->
<view
:class="beblue === 2 ? 'click-box-target' : 'click-box'"
@tap="onTap(2)"
@longpress="() => onLongPressStart(2)"
@touchend="onLongPressEnd"
@touchcancel="onLongPressEnd"
style="position: relative;"
>
<image :src="`/static/index/newruler/${beblue === 2 ? 1:0}.png`" style="position: absolute;width: 100%; height: 100%;" />
<image style="transform: rotate(180deg);transform-origin: center;" :src="`/static/index/newruler/fangxiang${beblue===2 ? 'target' : ''}.png`" class="image-photo" />
</view>
<!-- -->
<view
:class="beblue === 1 ? 'click-box-target' : 'click-box'"
@tap="onTap(1)"
@longpress="() => onLongPressStart(1)"
@touchend="onLongPressEnd"
@touchcancel="onLongPressEnd"
style="position: relative;"
>
<image :src="`/static/index/newruler/${beblue === 1 ? 1:0}.png`" style="position: absolute;width: 100%; height: 100%;" />
<image style="transform: rotate(90deg);transform-origin: center;" :src="`/static/index/newruler/fangxiang${beblue===1 ? 'target' : ''}.png`" class="image-photo" />
</view>
</view>
</template>
<script setup lang="ts">
import { ref, onBeforeUnmount } from 'vue'
const emit = defineEmits<{ (e : 'movecard', dir : number) : void }>()
let clickResetTimer : ReturnType<typeof setTimeout> | null = null
let longPressTimer : ReturnType<typeof setTimeout> | null = null
let isLongPress = false
const beblue = ref<number>(-1)
let activeLongPressDir : number | null = null
const props = defineProps({
movebottom: { type: Number, default: 30 },
moveleft: { type: Number, default: 10 },
leftbuttonname: { type: String, default: "返回" },
rightbuttonname: { type: String, default: "确定" },
})
function clearClickResetTimer() {
if (clickResetTimer) {
clearTimeout(clickResetTimer)
clickResetTimer = null
}
}
function clearLongPressTimer() {
if (longPressTimer) {
clearTimeout(longPressTimer)
longPressTimer = null
}
isLongPress = false
activeLongPressDir = null
}
// 单击(或短按)
function onTap(dir : number) {
clearLongPressTimer()
clearClickResetTimer()
beblue.value = dir
emit('movecard', dir)
clickResetTimer = setTimeout(() => {
beblue.value = -1
clickResetTimer = null
}, 500)
}
// 长按开始
function onLongPressStart(dir : number) {
clearClickResetTimer()
clearLongPressTimer()
beblue.value = dir
emit('movecard', dir)
activeLongPressDir = dir
isLongPress = true
function loop() {
if (!isLongPress || activeLongPressDir === null) return
// emit('movecard', activeLongPressDir)
longPressTimer = setTimeout(loop, 500)
}
longPressTimer = setTimeout(loop, 500)
}
// 长按结束
function onLongPressEnd() {
if (!isLongPress) return
clearLongPressTimer()
clearClickResetTimer()
clickResetTimer = setTimeout(() => {
beblue.value = -1
clickResetTimer = null
}, 500)
}
onBeforeUnmount(() => {
clearClickResetTimer()
clearLongPressTimer()
})
</script>
<style lang="less" scoped>
.move-circle {
position: absolute;
bottom: 0rpx;
left: 0rpx;
width: 500rpx;
display: flex;
flex-wrap: wrap;
z-index: 99;
touch-action: none;
}
.click-box,
.click-box-target {
width: 150rpx;
height: 137rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 28rpx;
transition: transform 0.18s ease, box-shadow 0.18s ease, background 0.25s ease;
-webkit-tap-highlight-color: transparent;
margin-bottom: 10rpx;
}
.click-box {
color: #888d99;
}
.click-box-target {
color: transparent;
animation: scalePulse 360ms cubic-bezier(.2, .8, .2, 1);
transform-origin: center center;
}
@keyframes scalePulse {
0% { transform: scale(1); }
25% { transform: scale(0.94); }
65% { transform: scale(1.08); }
100% { transform: scale(1); }
}
.grad-text {
background-image: linear-gradient(90deg, #5b8bb3, #87a1bd);
background-size: 200% 100%;
background-position: 0% 50%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
transition: background-position 0.8s linear;
}
.click-box-target .grad-text {
background-position: 100% 50%;
}
.image-photo {
width: 25%;
height: 25%;
transition: transform 0.18s ease, filter 0.18s ease;
}
.click-box-target .image-photo {
transform: none;
transition: transform 0.18s ease, filter 0.18s ease;
filter: none;
}
</style>