脆弱的滑動條 slider
會斷掉 (´・ω・`)
使用範例
基本用法
拉太偏會讓握把斷掉 (´・ω・`)
目前數值:50
查看範例原始碼
vue
<template>
<div class="w-full flex flex-col gap-4 py-14">
目前數值:{{ Math.floor(value) }}
<slider-stubborn
v-model="value"
class="w-full"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import SliderStubborn from '../slider-fragile.vue'
const value = ref(50)
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
修復與斷開
可以主動修復或斷開握把 (´・ω・`)ノ
查看範例原始碼
vue
<template>
<div class="w-full flex flex-col gap-4">
<div class="w-full py-12">
<slider-stubborn
ref="slider"
v-model="value"
class="w-full"
durable
thumb-color="#34c600"
joint-color="#a0d48e"
/>
</div>
<div class="flex gap-4">
<base-btn
label="修復"
class="flex-1"
@click="sliderRef?.repair()"
/>
<base-btn
label="斷開"
class="flex-1"
@click="sliderRef?.break()"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, useTemplateRef } from 'vue'
import BaseBtn from '../../base-btn.vue'
import SliderStubborn from '../slider-fragile.vue'
const sliderRef = useTemplateRef('slider')
const value = ref(50)
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
飲料表單
寧死不屈的甜度 ◝(´・ω・`)◟
飲料類型:
甜度:10 分
冰量:0 分
查看範例原始碼
vue
<template>
<div class="w-full flex flex-col gap-6 py-6">
<div class="flex flex-col items-start gap-4 border border-gray-300 rounded-xl p-6">
<div class="font-bold">
飲料類型:
</div>
<div class="w-full flex flex-wrap justify-between gap-4 whitespace-nowrap">
<label
v-for="item, i in list"
:key="i"
>
<input
v-model="value"
type="radio"
:value="item"
>
{{ item }}
</label>
</div>
</div>
<div class="grid grid-cols-6 w-full flex-nowrap items-center gap-8">
<div class="col-span-2 text-lg">
甜度:10 分
</div>
<div class="col-span-4 pr-4">
<slider-stubborn
ref="slider"
:model-value="10"
disabled
:max="10"
/>
</div>
</div>
<div class="grid grid-cols-6 w-full flex-nowrap items-center gap-8">
<div class="col-span-2 text-lg">
冰量:{{ iceValue }} 分
</div>
<div class="col-span-4 pr-4">
<slider-stubborn
v-model="iceValue"
durable
:step="3"
:max="9"
/>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, useTemplateRef, watch } from 'vue'
import SliderStubborn from '../slider-fragile.vue'
const sliderRef = useTemplateRef('slider')
const value = ref('綠茶')
const list = [
'綠茶',
'紅茶',
'蜂蜜奶茶',
'鮮奶茶',
'泰奶',
'水果茶',
'檸檬茶',
]
const iceValue = ref(0)
watch(value, () => {
sliderRef.value?.repair()
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
原理
主要由兩個元件組成:
主體(slider-fragile.vue
)
slider-fragile.vue
負責處理滑動條的基本邏輯,像是數值的計算、滑鼠在滑動條範圍內的偵測。
它會將計算好的比例 (ratio
)、滑鼠互動狀態 (isHeld
) 等資訊傳遞給握把元件 slider-fragile-thumb.vue
。
握把 (slider-fragile-thumb.vue
)
斷裂與移動效果皆由 slider-fragile-thumb.vue
負責。
當使用者按住握把 (isHeld
為 true
) 並拖曳時,計算滑鼠指標相對於握把中心的距離。
距離越大,震動效果越大,模擬被用力拉扯的感覺。
有以下狀態:
正常狀態: 握把根據父元件傳來的
ratio
定位在滑動條上。斷裂: 若拖曳的距離超過了設定的
breakLength
閾值且時間超過minSecondsToBreak
,isBroken
會變成true
,表示握把斷裂。斷裂後:
- 放開滑鼠時,執行物理模擬:給予握把一個初始速度 (基於放開前滑鼠的移動),然後模擬重力、空氣阻力,並在碰到視窗邊界時反彈,直到速度減緩至停止 (
thumbData.sleep
)。 - 斷裂後如果再次按住握把,它會跟隨滑鼠移動。
- 放開滑鼠時,執行物理模擬:給予握把一個初始速度 (基於放開前滑鼠的移動),然後模擬重力、空氣阻力,並在碰到視窗邊界時反彈,直到速度減緩至停止 (
比較特別的部分是正常狀態與斷裂狀態定位方式不同,正常狀態是 absolute
定位,斷裂狀態是 fixed
定位。
API
Props
interface Props {
modelValue: number;
disabled?: boolean;
min?: number;
max?: number;
step?: number;
thumbSize?: number;
thumbColor?: string;
jointColor?: string;
trackClass?: string;
durable?: boolean;
breakLength?: number;
minSecondsToBreak?: number;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
Emits
const emit = defineEmits<{
'update:modelValue': [value: Props['modelValue']];
}>()
1
2
3
2
3
Methods
interface Expose {
repair: () => void;
break: () => void;
}
1
2
3
4
2
3
4