slicing-slider.vue 3.88 KB
<template>
    <section class="slicing-slider">
        <el-slider
            v-model="value"
            vertical
            height="440px"
            range
            :step="0.1"
            :max="maximum"
            :min="minimum"
            placement="left"
            :format-tooltip="
                (value) => `${roundTo(value, 1).toFixed(2)} ${unit}
                  ${value > 0 ? (roundTo(value, 1) * 10).toFixed(2) : 0}`
            "
            tooltip-class="tooltipClass"
        />
        <div class="slider-part">
            <span style="color: transparent" v-text="0" />
            <span v-text="'&#188;'" />
            <span v-text="'&#189;'" />
            <span v-text="'&#190;'" />
            <span style="color: transparent" v-text="1" />
        </div>
    </section>
</template>

<script setup>
import { storeToRefs } from 'pinia';
import { useSlicingSliderStore } from '@/views/stores/useSlicingSliderStore';
import { watch, nextTick, onMounted } from 'vue';

const store = useSlicingSliderStore();
const { maximum, minimum, value, unit } = storeToRefs(store);

const roundTo = (number = 0.0, decimal = 2) => {
    const val = Math.round((number * Math.pow(10, decimal)).toPrecision(15)) / Math.pow(10, decimal);
    return val;
};

const setHandleDisabled = () => {
    const sliders = document.getElementsByClassName('el-slider__button-wrapper');
    let min = Infinity;
    let index = 0;
    for (let i = 0, len = sliders.length; i < len; i++) {
        const ariaValue = parseInt(sliders[i].getAttribute('aria-valuenow'), 10);
        if (ariaValue < min) {
            min = ariaValue;
            index = i;
        }
    }
    if (sliders.length > index) {
        for (let i = 0, len = sliders.length; i < len; i++) {
            let property = 'initial';
            if (index === i) {
                property = 'none';
                const elementStyle = sliders[i].firstElementChild.style;
                elementStyle.setProperty('border-color', 'transparent', 'important');
                elementStyle.setProperty('background-color', 'transparent', 'important');
            }
            sliders[i].style.setProperty('pointer-events', property, 'important');
        }
    }
};

onMounted(() => {
    setHandleDisabled();
});

watch(
    () => [maximum.value, minimum.value],
    () => {
        setHandleDisabled();
    }
);

watch(
    () => value.value,
    () => {
        nextTick(() => {
            const b = document.getElementsByClassName('el-slider__button-wrapper');
            const popperDom = document.getElementsByClassName('el-popper');
            if (popperDom) {
                const canvas = document.getElementById('viewer-editor');
                const rect = canvas.getBoundingClientRect();
                for (let i = 0; i < popperDom.length; i++) {
                    const element = b[i].getBoundingClientRect();
                    popperDom[i].style['transform'] = `translate(${
                        element.right - rect.width - element.width * 0.75 - 15
                    }px,${element.top - element.height * 0.25}px)`;
                }
            }
        });
    }
);
</script>
<style lang="less">
.slicing-slider {
    position: absolute;
    right: 270px;
    top: calc(50vh - 250px);
    display: flex;
    justify-content: space-between;
    // pointer-events: none;
    .slider-part {
        height: 440px;
        width: 60px;
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        font-size: x-large;
    }
}
.el-slider__button-wrapper {
    pointer-events: initial !important;
}
.el-popper {
    display: block !important;
    white-space: pre-line;
    text-align: center;
    font-size: 14px !important;
    z-index: 150 !important;
    // pointer-events: none;
}
.el-fade-in-linear-leave-active,
.el-fade-in-linear-leave-to {
    opacity: 1 !important;
}
.tooltipClass {
    z-index: 150 !important;
}
</style>