Jigsaw Puzzle Button button
A button that can only be clicked after you finish the jigsaw puzzle ◝( ゚∀゚ )◟
Usage Examples
Basic Usage
Drag the pieces and complete the puzzle!
View example source code
vue
<template>
<div class="w-full flex flex-col gap-4 border border-gray-200 rounded-xl p-6">
<div class="flex justify-center">
<btn-jigsaw-puzzle
:label="t('clickMe')"
@click="handleClick"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import BtnJigsawPuzzle from '../btn-jigsaw-puzzle.vue'
const { t } = useI18n()
function handleClick() {
// eslint-disable-next-line no-alert
alert(t('congratulations'))
}
</script>Form Example
Block bots and annoying complaints! (・∀・)9 (eh?)
Complaint Feedback Form
If you have any concerns, please fill in your feedback here, we will handle your problem as soon as possible.
To prevent abuse, the jigsaw puzzle must be completed before submitting (*´∀`)~♥
View example source code
vue
<template>
<div class="relative w-full flex flex-col gap-10 border border-gray-200 rounded-xl p-6">
<div class="flex flex-col gap-3">
<div class="text-3xl font-bold">
{{ t('complaintFeedbackForm') }}
</div>
<div class="text-sm text-gray-500">
{{ t('complaintFeedbackFormTip') }}
</div>
<div class="flex justify-center border border-gray-200 rounded-lg p-3">
<textarea
v-model="text"
:placeholder="t('inputPlaceholder')"
class="min-h-[30vh] w-full"
/>
</div>
<div class="w-full flex justify-center">
<btn-jigsaw-puzzle
ref="jigsawPuzzleRef"
:row-count="3"
:col-count="4"
@click="handleSubmit"
>
<button class="btn w-full select-none rounded p-3 px-20 text-3xl">
{{ t('submitBtn') }}
</button>
</btn-jigsaw-puzzle>
</div>
<div class="mt-2 text-center text-xs text-gray-500">
{{ t('jigsawPuzzleTip') }}
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, useTemplateRef } from 'vue'
import { useI18n } from 'vue-i18n'
import BtnJigsawPuzzle from '../btn-jigsaw-puzzle.vue'
const { t } = useI18n()
const jigsawPuzzleRef = useTemplateRef('jigsawPuzzleRef')
const text = ref('')
function handleSubmit() {
// eslint-disable-next-line no-alert
alert(t('thanks'))
text.value = ''
jigsawPuzzleRef.value?.scatter()
}
</script>
<style scoped lang="sass">
.btn
background-color: light-dark(#444, #EEE)
color: light-dark(#EEE, #444)
transition-duration: 0.2s
&:active
transition-duration: 0.1s
transform: scale(0.98)
</style>How It Works
Uses an SVG mask to implement the jigsaw splitting, and Pointer events to implement the drag-and-drop behavior.
Source Code
API
Props
interface Props {
/** 按鈕內文字 */
label?: string;
/** 是否停用 */
disabled?: boolean;
/** 同 CSS z-index */
zIndex?: number | string;
/** 同 html tabindex */
tabindex?: number | string;
/** 拼圖行數 */
rowCount?: number;
/** 拼圖列數 */
colCount?: number;
}Emits
const emit = defineEmits<{
/** 開始拖動 */
dragStart: [piece: Piece, evt: PointerEvent];
dragging: [piece: Piece, evt: PointerEvent];
dragStop: [piece: Piece, evt: PointerEvent];
completed: [];
click: [];
}>()Methods
defineExpose({
/** 打散拼圖 */
scatter,
/** 自動完成 */
autoComplete,
})Slots
defineSlots<{
/** 按鈕 */
default?: (params: { isAllCompleted: boolean }) => unknown;
}>()