This commit is contained in:
2026-01-05 12:47:14 +08:00
commit 1fc846fae3
1614 changed files with 162035 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
.nut-shakedice {
position: relative;
width: 100px;
height: 100px;
transition: all 1s;
transform-style: preserve-3d;
.page {
position: absolute;
top: 0;
left: 0;
box-sizing: border-box;
display: flex;
width: 100px;
height: 100px;
font-size: 100px;
color: #fff;
text-align: center;
background: rgb(253 250 250);
border: 1px solid #000;
border-radius: 20px;
> text {
display: block;
width: 25px;
height: 25px;
background: black;
border-radius: 50%;
}
}
.page1 {
align-items: center;
justify-content: center;
transform: translateZ(50px);
}
.page2 {
align-items: center;
justify-content: space-around;
transform: rotateX(-90deg) translateZ(50px);
}
.page3 {
position: relative;
transform: rotateY(90deg) translateZ(50px);
> text {
position: absolute;
&:first-child {
top: 10px;
right: 10px;
}
&:nth-child(2) {
top: 37%;
left: 37%;
}
&:nth-child(3) {
bottom: 10px;
left: 10px;
}
}
}
.page4 {
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
padding: 15px;
transform: rotateY(-90deg) translateZ(50px);
}
.page5 {
flex-wrap: wrap;
align-items: center;
justify-content: center;
transform: rotateX(90deg) translateZ(50px);
> text {
margin: 0 10px;
&:nth-child(3) {
position: absolute;
top: 37%;
left: 37%;
margin: 0;
}
}
}
.page6 {
flex-wrap: wrap;
align-items: center;
justify-content: center;
transform: translateZ(-50px);
}
}
@keyframes rotate {
to {
transform: rotateX(360deg) rotateY(360deg);
}
}

View File

@@ -0,0 +1 @@
export type * from './shakedice'

View File

@@ -0,0 +1,29 @@
import type { ExtractPropTypes } from 'vue'
import { commonProps, makeNumberProp } from '../_utils'
export const shakediceProps = {
...commonProps,
/**
* @description 旋转时间,秒
*/
time: makeNumberProp(1),
/**
* @description 旋转速度,ms
*/
speed: makeNumberProp(3000),
/**
* @description 中奖的 id(1 为 1 点,依次类推)
*/
id: makeNumberProp(4),
}
export type ShakeDiceProps = ExtractPropTypes<typeof shakediceProps>
export const shakediceEmits = {
end: () => true,
}
export type ShakeDiceEmits = typeof shakediceEmits
export interface ShakeDiceInst {
shake: () => true
}

View File

@@ -0,0 +1,101 @@
<script setup lang="ts">
import { computed, defineComponent, ref, watch } from 'vue'
import { PREFIX } from '../_constants'
import { getMainClass } from '../_utils'
import { shakediceEmits, shakediceProps } from './shakedice'
const props = defineProps(shakediceProps)
const emit = defineEmits(shakediceEmits)
defineExpose({ shake })
const dice = ref<number>(6)
const clickTag = ref<boolean>(false)
const animationStyle = ref({})
const isShake = ref(false)
const transformStyle = ref({
transform: '',
})
const classes = computed(() => {
return getMainClass(props, componentName)
})
watch(
() => isShake.value,
(value) => {
if (value) {
const params = {
animation: `rotate ${props.time}s infinite linear`,
}
animationStyle.value = { ...animationStyle.value, ...params }
setTimeout(() => {
isShake.value = false
animationStyle.value = { animation: 'none' }
const posible: any = [
{ value: 1, x: 0, y: 0 },
{ value: 1, x: 0, y: 0 },
{ value: 2, x: 90, y: 0 },
{ value: 3, x: 0, y: -90 },
{ value: 4, x: 0, y: 90 },
{ value: 5, x: -90, y: 0 },
{ value: 6, x: 0, y: 180 },
]
const _result = posible[props.id]
setTimeout(() => {
transformStyle.value.transform = `rotateX(${_result.x}deg) rotateY(${_result.y}deg)`
}, 0)
emit('end')
}, props.speed)
}
else {
animationStyle.value = {}
}
},
)
function shake() {
if (clickTag.value)
return false
clickTag.value = true
isShake.value = true
setTimeout(() => {
clickTag.value = false
}, props.speed)
}
</script>
<script lang="ts">
const componentName = `${PREFIX}-shakedice`
export default defineComponent({
name: componentName,
options: {
virtualHost: true,
addGlobalClass: true,
styleIsolation: 'shared',
},
})
</script>
<template>
<div :class="classes" :style="[animationStyle, transformStyle, customStyle]">
<div
v-for="(item, index) in new Array(dice)"
:key="index"
class="page"
:class="[`page${index + 1}`]"
>
<text v-for="(item2, index2) in new Array(index + 1)" :key="index2" />
</div>
</div>
</template>
<style lang="scss">
@import './index';
</style>
<route lang="json">
{
"style": {
"navigationBarTitleText": "ShakeDice"
}
}
</route>