forked from opentiny/tiny-engine
163 lines
3.8 KiB
Vue
163 lines
3.8 KiB
Vue
<template>
|
|
<div class="slider-container">
|
|
<input v-model="value" type="range" @change="onSliderStop" />
|
|
<meta-number
|
|
:min="0"
|
|
:max="100"
|
|
:controls="controls"
|
|
:modelValue="value"
|
|
:selectedUnit="unitRef"
|
|
:showUnit="showUnit"
|
|
:disabled="disabled"
|
|
:unit="[
|
|
{ value: 'px', label: 'px' },
|
|
{ value: '%', label: '%' }
|
|
]"
|
|
@numberChange="onNumberCompChange"
|
|
@unitChange="onUnitChange"
|
|
></meta-number>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { ref, watch } from 'vue'
|
|
import MetaNumber from './MetaNumber.vue'
|
|
|
|
export default {
|
|
components: {
|
|
MetaNumber
|
|
},
|
|
props: {
|
|
modelValue: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
controls: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
// 默认选中的单位
|
|
selectedUnit: {
|
|
type: String,
|
|
default: '%'
|
|
},
|
|
// 是否显示单位
|
|
showUnit: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
disabled: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
},
|
|
setup(props, { emit }) {
|
|
const value = ref(props.modelValue)
|
|
const unitRef = ref(props.selectedUnit || 'px')
|
|
|
|
watch(
|
|
() => props.modelValue,
|
|
(val) => {
|
|
value.value = val
|
|
}
|
|
)
|
|
|
|
const triggerUpdate = (value, unitValue = unitRef.value) => {
|
|
emit('update:modelValue', value, unitValue)
|
|
}
|
|
|
|
const onSliderStop = (event) => {
|
|
triggerUpdate(Number(event.target.value))
|
|
}
|
|
|
|
const onNumberCompChange = (val) => {
|
|
value.value = val
|
|
triggerUpdate(val)
|
|
}
|
|
|
|
const onUnitChange = (val) => {
|
|
unitRef.value = val
|
|
value.value = 0
|
|
triggerUpdate(0, val)
|
|
}
|
|
|
|
return { value, unitRef, onNumberCompChange, onUnitChange, onSliderStop }
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.slider-container {
|
|
display: grid;
|
|
grid-template-columns: minmax(80px, 50%) minmax(0, 1fr); // 最后一个元素自适应布局
|
|
column-gap: 6%;
|
|
:deep(.tiny-slider) {
|
|
height: 3px;
|
|
width: 100%;
|
|
border-radius: 2px;
|
|
background-color: var(--ti-lowcode-canvas-wrap-bg);
|
|
.tiny-slider__handle {
|
|
width: 10px;
|
|
height: 10px;
|
|
margin: -4px -5px 0 -5px;
|
|
border-radius: 50%;
|
|
border: none;
|
|
cursor: ew-resize;
|
|
background-color: var(--ti-lowcode-toolbar-breadcrumb-color);
|
|
box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 1px, rgba(0, 0, 0, 0.3) 0px 0px 0px 0.5px;
|
|
}
|
|
.tiny-slider__range {
|
|
height: 3px;
|
|
border-radius: 3px;
|
|
margin-top: 0;
|
|
background: var(--ti-lowcode-canvas-wrap-bg);
|
|
}
|
|
|
|
.tiny-slider__tips {
|
|
color: var(--ti-lowcode-breadcrumb-color);
|
|
background: var(--ti-lowcode-breadcrumb-bg);
|
|
padding: 4px 6px;
|
|
border-radius: 2px;
|
|
box-shadow: rgb(0 0 0 / 15%) 0px 5px 10px;
|
|
margin-top: -8px;
|
|
&::before,
|
|
&::after {
|
|
border-color: var(--ti-lowcode-breadcrumb-bg) transparent;
|
|
}
|
|
}
|
|
}
|
|
input[type='range'] {
|
|
height: 4px;
|
|
border-radius: 8px;
|
|
margin: 0.8em 0;
|
|
padding: 0;
|
|
cursor: pointer;
|
|
border: 0;
|
|
background: -webkit-linear-gradient(#fff, #fff) no-repeat #999999;
|
|
background-size: 0% 100%;
|
|
position: relative;
|
|
outline: 0;
|
|
top: -1px;
|
|
-webkit-appearance: none !important;
|
|
}
|
|
input[type='range']::-webkit-slider-thumb {
|
|
width: 10px;
|
|
height: 10px;
|
|
border-radius: 50%;
|
|
border: 0;
|
|
background-color: #fff;
|
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.21);
|
|
-webkit-transition: border-color 0.15s, background-color 0.15s;
|
|
transition: border-color 0.15s, background-color 0.15s;
|
|
cursor: pointer;
|
|
background-clip: padding-box;
|
|
box-sizing: border-box;
|
|
-webkit-appearance: none !important;
|
|
}
|
|
input[type='range']::-webkit-slider-thumb:active {
|
|
border: 0;
|
|
background-color: #fff;
|
|
}
|
|
}
|
|
</style>
|