Skip to content

靈活的按鈕 button

動作極為靈活的按鈕 ◝( •ω• )◟

靈感來自劍星的 Doro 迷因連動,第一次看到時真的會笑死。(´,,•ω•,,)

技術關鍵字

名稱 描述
Pointer 事件偵測滑鼠或觸控點移動、點擊、懸停等等事件,取得座標、目標等等資訊
JS 動畫基於 JavaScript 實現的動畫,達成更複雜、精準的動畫控制,常見套件有 GSAP、anime.js 等

使用範例

基本用法

disabled 時,觸發按鈕會超高速閃避。─=≡Σ((( つ•̀ω•́)つ

查看範例原始碼
vue
<template>
  <div class="w-full flex flex-col gap-4 border border-gray-200 rounded-xl p-6">
    <div class="flex flex-col gap-4 border rounded">
      <base-checkbox
        v-model="disabled"
        label="停用按鈕"
        class="p-4"
      />
    </div>

    <div class="flex justify-center">
      <btn-agile
        label="按我"
        :disabled="disabled"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import BaseCheckbox from '../../base-checkbox.vue'
import BtnAgile from '../btn-agile.vue'

const disabled = ref(true)
</script>

表單範例

沒填完就沒得按。(╯•̀ὤ•́)╯

查看範例原始碼
vue
<template>
  <div class="relative w-full flex justify-center border border-gray-200 rounded-xl p-6 py-24">
    <div class="max-w-[20rem] flex flex-col gap-4">
      <base-input
        v-model="form.username"
        :label="t('帳號 *')"
        class="w-full"
      />

      <base-input
        v-model="form.password"
        type="password"
        :label="t('密碼 *')"
        class="w-full"
      />

      <div class="mt-3 flex justify-center">
        <btn-agile
          :label="t('登入')"
          :disabled
          z-index="30"
          @click="handleSubmit"
        />
      </div>
    </div>

    <transition name="opacity">
      <div
        v-if="isSubmitted"
        class="absolute inset-0 z-[40] flex flex-col items-center justify-center gap-6 rounded-xl bg-slate-600 bg-opacity-90 text-white"
        @click="reset"
      >
        <span class="text-xl tracking-wide">
          {{ t('表單已送出!(*´∀`)~♥') }}
        </span>

        <span class="cursor-pointer text-xs">
          {{ t('點一下再來一次') }}
        </span>
      </div>
    </transition>
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import BaseInput from '../../base-input.vue'
import BtnAgile from '../btn-agile.vue'

const { t } = useI18n()

const form = ref({
  username: '',
  password: '',
})
const disabled = computed(() => {
  return form.value.username === '' || form.value.password === ''
})

const isSubmitted = ref(false)
function handleSubmit() {
  if (disabled.value) {
    return
  }
  isSubmitted.value = true
}

function reset() {
  isSubmitted.value = false

  form.value = {
    username: '',
    password: '',
  }
}
</script>

<style lang="sass" scoped>
.rubbing
  padding: 0.75rem
  color: #ff7530
  opacity: 0.8
  border: 1px dashed #ff7530
  border-radius: 0.2rem
  white-space: nowrap
  text-align: center

.opacity-enter-active, .opacity-leave-active
  transition-duration: 0.4s
.opacity-enter-from, .opacity-leave-to
  opacity: 0 !important
</style>

原理

這次使用潮到出水的 Motion 來實現按鈕的動畫。( •̀ ω •́ )✧

Motion 會盡可能使用硬體加速,且 Vue 版本深度整合響應式系統,性能表現非常優秀,還內建許多實用元件

強力推薦看看此文章:The Web Animation Performance Tier List

裡面詳細介紹各種動畫的性能表現與 Web 動畫知識,相當有趣。

原始碼

API

Props

interface Props {
  /** 按鈕內文字 */
  label?: string;
  /** 是否停用 */
  disabled?: boolean;
  /** 同 CSS z-index */
  zIndex?: number | string;
  /** 同 html tabindex */
  tabindex?: number | string;
}

Emits

const emit = defineEmits<{
  (e: 'click'): void;
}>()

Methods

defineExpose({})

Slots

defineSlots<{
  /** 按鈕 */
  default?: () => unknown;
}>()

v0.52.0