139 lines
3.5 KiB
HTML
139 lines
3.5 KiB
HTML
<script>
|
|
import {createEventDispatcher} from "svelte";
|
|
import Thumb from "./Thumb.svelte";
|
|
|
|
const dispatch = createEventDispatcher();
|
|
|
|
export let name = [];
|
|
export let range = false;
|
|
export let min = 0;
|
|
export let max = 100;
|
|
export let step = 1;
|
|
export let value = [min, max];
|
|
export let pos;
|
|
export let active = false;
|
|
export let order = false;
|
|
export let tip = false;
|
|
|
|
$: if (active) setValue(pos);
|
|
$: if (!active) setPos(value);
|
|
$: if (range && order && active) pos = checkPos(pos);
|
|
$: min, max, clamp();
|
|
$: progress = `
|
|
left: ${range ? Math.min(pos[0], pos[1]) * 100 : 0}%;
|
|
right: ${100 - Math.max(pos[0], (range ? pos[1] : pos[0])) * 100}%;
|
|
`;
|
|
|
|
function setValue(pos) {
|
|
|
|
const offset = min % step;
|
|
const width = max - min
|
|
value = pos
|
|
.map(v => {
|
|
const t = min + v * width;
|
|
return t;
|
|
})
|
|
.map(v => {
|
|
let r;
|
|
if(step < 1){
|
|
const digit = getDigit(step);
|
|
const num1 = Math.round((v - offset) / step);
|
|
const num2 = step;
|
|
r = formatNum(num1 * num2, digit)
|
|
}else{
|
|
r = Math.round((v - offset) / step) * step + offset;
|
|
}
|
|
return r;
|
|
});
|
|
|
|
dispatch("change", value);
|
|
}
|
|
|
|
function setPos(value) {
|
|
pos = value
|
|
.map(v => Math.min(Math.max(v, min), max))
|
|
.map(v => (v - min) / (max - min));
|
|
}
|
|
|
|
function checkPos(pos) {
|
|
return [Math.min(...pos), Math.max(...pos)];
|
|
}
|
|
|
|
function clamp() {
|
|
setPos(value);
|
|
setValue(pos);
|
|
}
|
|
|
|
function getDigit(num) {
|
|
const strs = num.toString().split(".");
|
|
if (strs[1]) {
|
|
return strs[1].length;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
function formatNum(f, digit) {
|
|
var m = Math.pow(10, digit);
|
|
return parseInt(f * m, 10) / m;
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
input {
|
|
display: none;
|
|
}
|
|
|
|
.track {
|
|
margin: 16px 8px;
|
|
position: relative;
|
|
height: 4px;
|
|
width: calc(100% - 16px);
|
|
border-radius: 100vh;
|
|
background: var(--track-background, #ebebeb);
|
|
}
|
|
|
|
.progress-sli {
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
border-radius: 100vh;
|
|
background: var(--progress-background, #8abdff);
|
|
}
|
|
|
|
.thumb {
|
|
width: 16px;
|
|
height: 16px;
|
|
border-radius: 100vh;
|
|
background: var(--thumb-background, #5784fd);
|
|
}
|
|
</style>
|
|
|
|
<input type="number" value={value[0]} name={name[0]}/>
|
|
{#if range}
|
|
<input type="number" value={value[1]} name={name[1]}/>
|
|
{/if}
|
|
<div class="track">
|
|
<div
|
|
class="progress-sli"
|
|
style={progress}/>
|
|
<Thumb bind:pos={pos[0]} on:active={({ detail: v }) => active = v} on:dragEnd value={value[0]} {tip}>
|
|
<slot name="left">
|
|
<slot>
|
|
<div class="thumb"/>
|
|
</slot>
|
|
</slot>
|
|
</Thumb>
|
|
{#if range}
|
|
<Thumb bind:pos={pos[1]} on:active={({ detail: v }) => active = v} on:dragEnd value={value[1]} {tip}>
|
|
<slot name="right">
|
|
<slot>
|
|
<div class="thumb"/>
|
|
</slot>
|
|
</slot>
|
|
</Thumb>
|
|
{/if}
|
|
</div>
|