Skip to content

怕鼠的文字 text

滑鼠靠近時會躲得遠遠的文字。

TIP

此元件針對滑鼠設計,建議使用電腦或可以使用滑鼠的裝置瀏覽。

使用範例

基本用法

滑鼠靠近時,文字會遠離滑鼠。

Musophobia Muriphobia

查看範例原始碼
vue
<template>
  <div class="w-full border border-gray-300 p-6">
    <text-hate-mouse
      :text="t('musophobiaDescription')"
    />
  </div>
</template>

<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import TextHateMouse from '../text-hate-mouse.vue'

const { t } = useI18n()
</script>

不同組合

不同參數有不同效果。

逆走開逆走開逆走開逆走開逆走開逆走開逆走開逆走開逆走開逆走開

🀀🀁🀂🀃🀄🀅🀆🀇🀈🀉🀊🀋🀌🀍🀎🀏🀐🀑🀒🀓🀔🀕🀖🀗🀘🀖🀗🀘🀙🀚🀛🀜🀝🀞🀟🀠🀡🀢🀣🀤🀥🀦🀧🀨🀩🀪🀫

查看範例原始碼
vue
<template>
  <div class="w-full flex flex-col gap-8 border border-gray-300 p-6 text-center">
    <text-hate-mouse
      v-for="item, i in list"
      :key="i"
      v-bind="item"
    />
  </div>
</template>

<script setup lang="ts">
import type { ComponentProps } from 'vue-component-type-helpers'
import { times } from 'remeda'
import { useI18n } from 'vue-i18n'
import TextHateMouse from '../text-hate-mouse.vue'

type Props = ComponentProps<typeof TextHateMouse> & {
  class?: string;
}

const { t } = useI18n()

const list: Props[] = [
  {
    text: t('scaredText'),
    stiffness: 0.2,
    damping: 0,
    evasionRadius: 30,
  },
  {
    text: times(10, () => t('goAway')),
    evasionRadius: 200,
  },
  {
    text: [
      '🀀🀁🀂🀃🀄🀅🀆🀇🀈🀉🀊🀋🀌🀍🀎🀏',
      '🀐🀑🀒🀓🀔🀕🀖🀗🀘🀖🀗🀘',
      '🀙🀚🀛🀜🀝🀞🀟🀠🀡',
      '🀢🀣🀤🀥🀦🀧🀨🀩🀪🀫',

    ].join(''),
    stiffness: 0.002,
    damping: 1,
    class: 'text-2xl',
  },
]
</script>

自定義參數

變出有趣的效果吧!ԅ(´∀` ԅ)

A

查看範例原始碼
vue
<template>
  <div class="w-full flex flex-col gap-4 border border-gray-300 p-6 text-center">
    <div class="flex flex-col gap-4">
      <base-input
        v-model="params.text"
        :label="t('customText')"
        type="text"
        class="w-full text-left"
      />

      <base-input
        v-model.number="params.evasionRadius"
        :label="t('evasionRadiusLabel', { value: params.evasionRadius })"
        type="range"
        class="w-full text-left"
        :max="300"
        :step="1"
        :min="20"
      />

      <base-input
        v-model.number="params.stiffness"
        :label="t('stiffnessLabel', { value: params.stiffness })"
        type="range"
        class="w-full text-left"
        :max="0.3"
        :step="0.001"
        :min="0.001"
      />

      <base-input
        v-model.number="params.damping"
        :label="t('dampingLabel', { value: params.damping })"
        type="range"
        class="w-full text-left"
        :max="1"
        :step="0.01"
        :min="0"
      />
    </div>

    <div class="border p-4">
      <text-hate-mouse v-bind="params" />
    </div>
  </div>
</template>

<script setup lang="ts">
import type { ComponentProps } from 'vue-component-type-helpers'
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
import BaseInput from '../../base-input.vue'
import TextHateMouse from '../text-hate-mouse.vue'

type Props = ComponentProps<typeof TextHateMouse>

const { t } = useI18n()

const params = ref({
  text: t('defaultText'),
  evasionRadius: 40,
  stiffness: 0.01,
  damping: 0.05,
} satisfies Props)
</script>

委婉的報價單

預算過低時,委婉地暗示客戶。

請選擇您的預算範圍:

0987-654-321

E-mailhi@codlin.me

查看範例原始碼
vue
<template>
  <div class="w-full flex flex-col gap-8 border border-gray-300 p-6 text-center">
    <!-- 預算 radio -->
    <div class="flex flex-col items-start gap-4 border border-gray-300 rounded-xl p-6">
      <div class="font-bold">
        {{ t('budgetPrompt') }}
      </div>

      <div class="w-full flex flex-wrap justify-between gap-4 whitespace-nowrap">
        <label
          v-for="item, i in budgetList"
          :key="i"
        >
          <input
            v-model="budget"
            type="radio"
            :value="i"
          >
          {{ item.text }}
        </label>
      </div>
    </div>

    <div class="flex flex-col gap-1 p-6">
      <text-hate-mouse
        v-for="item, i in list"
        :key="i"
        v-bind="item"
        :evasion-radius
        class="!m-0"
        :class="{ 'select-none': evasionRadius > 0 }"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import type { ComponentProps } from 'vue-component-type-helpers'
import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import TextHateMouse from '../text-hate-mouse.vue'

type Props = ComponentProps<typeof TextHateMouse> & {
  class?: string;
}

const { t } = useI18n()

const budget = ref(-1)
const budgetList = [
  { text: t('budget.under10k') },
  { text: t('budget.10kTo50k') },
  { text: t('budget.50kTo100k') },
  { text: t('budget.over100k') },
]

const evasionRadius = computed(() => budget.value === 0 ? 50 : 0)

const list: Props[] = [
  { text: t('contact.phone') },
  { text: t('contact.email') },
]
</script>

原理

基於 Matter.js 實現物理模擬效果。

基本上就是逐字轉場物理包裝器的融合。

原始碼

API

Props

interface Props {
  /** string[] 表示提供已分割好的文字 */
  text: string | string[];

  /** html tag
   *
   * @default 'p'
   */
  tag?: string;

  /** 如何切割文字
   *
   * 只有在 text 為 string 時有效
   *
   * @default /.*?/u
   */
  splitter?: RegExp | ((text: string) => string[]);

  /** 閃避半徑 */
  evasionRadius?: number;

  /** 約束力
   *
   * 表示回復原味的力量,1 表示最強,0.2 則類似軟彈簧作用
   */
  stiffness?: number;

  /** 阻尼
   *
   * 0.1 表示強烈阻尼,幾乎不會有任何震盪,0 表示沒有任何阻尼
   */
  damping?: number;
}

v0.38.10