|
|
@@ -1,43 +1,40 @@
|
|
|
<template>
|
|
|
<div :style="styleMap?.mainStyle" class="w-full h-full box-border relative">
|
|
|
<ImageBg :src="styleMap?.mainStyle?.imageSrc" :image-style="styleMap?.mainStyle?.imageStyle" />
|
|
|
- <div class="absolute" :style="indicatorStyle">
|
|
|
- <div class="absolute w-full h-full overflow-hidden">
|
|
|
- <ImageBg
|
|
|
- :src="styleMap?.indicatorStyle?.imageSrc"
|
|
|
- :image-style="styleMap?.indicatorStyle?.imageStyle"
|
|
|
- :style="{
|
|
|
- width: width + 'px',
|
|
|
- height: height + 'px'
|
|
|
- }"
|
|
|
- />
|
|
|
- </div>
|
|
|
- <!-- 左边值 -->
|
|
|
- <div
|
|
|
- v-if="mode === 'range'"
|
|
|
- :style="{
|
|
|
- ...styleMap?.knobStyle,
|
|
|
- ...otherStyle.startKnobStyle
|
|
|
- }"
|
|
|
- class="absolute aspect-square"
|
|
|
- >
|
|
|
- <ImageBg
|
|
|
- :src="styleMap?.knobStyle?.imageSrc"
|
|
|
- :image-style="styleMap?.knobStyle?.imageStyle"
|
|
|
- />
|
|
|
- </div>
|
|
|
- <!-- 右边值 -->
|
|
|
- <div
|
|
|
- :style="{
|
|
|
- ...styleMap?.knobStyle,
|
|
|
- ...otherStyle.endKnobStyle
|
|
|
- }"
|
|
|
- class="absolute aspect-square"
|
|
|
- >
|
|
|
- <ImageBg
|
|
|
- :src="styleMap?.knobStyle?.imageSrc"
|
|
|
- :image-style="styleMap?.knobStyle?.imageStyle"
|
|
|
- />
|
|
|
+ <div class="absolute" :style="trackStyle">
|
|
|
+ <div class="absolute" :style="indicatorStyle">
|
|
|
+ <div class="absolute w-full h-full overflow-hidden">
|
|
|
+ <ImageBg
|
|
|
+ :src="styleMap?.indicatorStyle?.imageSrc"
|
|
|
+ :image-style="styleMap?.indicatorStyle?.imageStyle"
|
|
|
+ :style="indicatorImageStyle"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <!-- 左边值 -->
|
|
|
+ <div
|
|
|
+ v-if="mode === 'range'"
|
|
|
+ :style="otherStyle.startKnobStyle"
|
|
|
+ class="absolute aspect-square flex items-center justify-center"
|
|
|
+ >
|
|
|
+ <div :style="styleMap?.knobStyle" class="shrink-0">
|
|
|
+ <ImageBg
|
|
|
+ :src="styleMap?.knobStyle?.imageSrc"
|
|
|
+ :image-style="styleMap?.knobStyle?.imageStyle"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 右边值 -->
|
|
|
+ <div
|
|
|
+ :style="otherStyle.endKnobStyle"
|
|
|
+ class="absolute aspect-square flex items-center justify-center"
|
|
|
+ >
|
|
|
+ <div :style="styleMap?.knobStyle" class="shrink-0">
|
|
|
+ <ImageBg
|
|
|
+ :src="styleMap?.knobStyle?.imageSrc"
|
|
|
+ :image-style="styleMap?.knobStyle?.imageStyle"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -67,7 +64,6 @@ const styleMap = useWidgetStyle({
|
|
|
widget: 'lv_slider',
|
|
|
props
|
|
|
})
|
|
|
-
|
|
|
const isGradientBackground = (background: unknown) => {
|
|
|
return typeof background === 'string' && /(?:linear|radial|conic)-gradient\(/.test(background)
|
|
|
}
|
|
|
@@ -84,14 +80,65 @@ const getOffset = (value: string | number | undefined, total = 0) => {
|
|
|
return Number(value) || 0
|
|
|
}
|
|
|
|
|
|
+const parseCssNumber = (value: unknown) => {
|
|
|
+ const number = Number.parseFloat(String(value ?? 0))
|
|
|
+ return Number.isFinite(number) ? number : 0
|
|
|
+}
|
|
|
+
|
|
|
+const parsePadding = (padding: CSSProperties['padding']) => {
|
|
|
+ const values = String(padding ?? '0')
|
|
|
+ .trim()
|
|
|
+ .split(/\s+/)
|
|
|
+ .map(parseCssNumber)
|
|
|
+
|
|
|
+ const top = values[0] ?? 0
|
|
|
+ const right = values[1] ?? top
|
|
|
+ const bottom = values[2] ?? top
|
|
|
+ const left = values[3] ?? right
|
|
|
+
|
|
|
+ return { top, right, bottom, left }
|
|
|
+}
|
|
|
+
|
|
|
+const mainPadding = computed(() => parsePadding(styleMap.value?.mainStyle?.padding))
|
|
|
+
|
|
|
+const trackStyle = computed<CSSProperties>(() => {
|
|
|
+ const { top, right, bottom, left } = mainPadding.value
|
|
|
+
|
|
|
+ return {
|
|
|
+ top: `${top}px`,
|
|
|
+ right: `${right}px`,
|
|
|
+ bottom: `${bottom}px`,
|
|
|
+ left: `${left}px`
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+const indicatorOffset = computed(() => {
|
|
|
+ const width = Number(props.width || 0)
|
|
|
+ const height = Number(props.height || 0)
|
|
|
+ const { top, right, bottom, left } = mainPadding.value
|
|
|
+ const trackWidth = Math.max(width - left - right, 0)
|
|
|
+ const trackHeight = Math.max(height - top - bottom, 0)
|
|
|
+
|
|
|
+ return {
|
|
|
+ left: left + getOffset(otherStyle.value.barStyle.left, trackWidth),
|
|
|
+ top: top + getOffset(otherStyle.value.barStyle.top, trackHeight)
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+const indicatorImageStyle = computed<CSSProperties>(() => ({
|
|
|
+ width: `${props.width || 0}px`,
|
|
|
+ height: `${props.height || 0}px`,
|
|
|
+ left: `${-indicatorOffset.value.left}px`,
|
|
|
+ top: `${-indicatorOffset.value.top}px`
|
|
|
+}))
|
|
|
+
|
|
|
const indicatorGradientStyle = computed<CSSProperties>(() => {
|
|
|
const indicatorBackground = styleMap.value?.indicatorStyle?.background
|
|
|
if (!isGradientBackground(indicatorBackground)) return {}
|
|
|
|
|
|
const width = Number(props.width || 0)
|
|
|
const height = Number(props.height || 0)
|
|
|
- const left = getOffset(otherStyle.value.barStyle.left, width)
|
|
|
- const top = getOffset(otherStyle.value.barStyle.top, height)
|
|
|
+ const { left, top } = indicatorOffset.value
|
|
|
|
|
|
return {
|
|
|
backgroundSize: `${width}px ${height}px`,
|
|
|
@@ -215,37 +262,39 @@ const otherStyle = computed(() => {
|
|
|
direction,
|
|
|
endKnobStyle: isHorizontal
|
|
|
? {
|
|
|
- top: '-4px',
|
|
|
+ top: -mainPadding.value.top + 'px',
|
|
|
bottom: 'auto',
|
|
|
right: endHorizontalAnchor === 'right' ? '0' : 'auto',
|
|
|
left: endHorizontalAnchor === 'left' ? '0' : 'auto',
|
|
|
- height: 'calc(100% + 8px)',
|
|
|
+ height: height + 'px',
|
|
|
+ width: height + 'px',
|
|
|
transform: getHorizontalKnobTransform(endHorizontalAnchor)
|
|
|
}
|
|
|
: {
|
|
|
- left: '50%',
|
|
|
+ left: -mainPadding.value.left + 'px',
|
|
|
right: 'auto',
|
|
|
top: endVerticalAnchor === 'top' ? '0' : 'auto',
|
|
|
bottom: endVerticalAnchor === 'bottom' ? '0' : 'auto',
|
|
|
- width: 'calc(100% + 8px)',
|
|
|
- transform: `translateX(-50%) ${getVerticalKnobTransform(endVerticalAnchor)}`
|
|
|
+ width: width + 'px',
|
|
|
+ height: width + 'px'
|
|
|
},
|
|
|
startKnobStyle: isHorizontal
|
|
|
? {
|
|
|
- top: '-4px',
|
|
|
+ top: -mainPadding.value.top + 'px',
|
|
|
bottom: 'auto',
|
|
|
right: startHorizontalAnchor === 'right' ? '0' : 'auto',
|
|
|
left: startHorizontalAnchor === 'left' ? '0' : 'auto',
|
|
|
- height: 'calc(100% + 8px)',
|
|
|
+ height: height + 'px',
|
|
|
+ width: height + 'px',
|
|
|
transform: getHorizontalKnobTransform(startHorizontalAnchor)
|
|
|
}
|
|
|
: {
|
|
|
- left: '50%',
|
|
|
+ left: -mainPadding.value.left + 'px',
|
|
|
right: 'auto',
|
|
|
top: startVerticalAnchor === 'top' ? '0' : 'auto',
|
|
|
bottom: startVerticalAnchor === 'bottom' ? '0' : 'auto',
|
|
|
- width: 'calc(100% + 8px)',
|
|
|
- transform: `translateX(-50%) ${getVerticalKnobTransform(startVerticalAnchor)}`
|
|
|
+ width: width + 'px',
|
|
|
+ height: width + 'px'
|
|
|
}
|
|
|
}
|
|
|
})
|