/** * {} * @author yutent * @date 2023/03/21 16:14:10 */ import { nextTick, css, bind, unbind, html, Component } from '@bd/core' class Slider extends Component { static props = { value: { type: Number, default: 0, observer() {} }, max: 100, min: 0, step: 1, disabled: false, readonly: false, vertical: false, 'show-tooltip': true } static styles = css` :host { display: block; width: 100%; height: 38px; } .slider { position: relative; display: flex; align-items: center; height: 100%; } .runway { flex: 1; position: relative; height: 6px; background: #e4e7ed; border-radius: 99rem; cursor: pointer; .bar { flex: 1; pointer-events: none; position: absolute; height: 100%; width: 0%; border-radius: 99rem; background: #409eff; } } .dot-wrapper { position: absolute; display: flex; justify-content: center; align-items: center; height: 36px; width: 36px; top: 50%; left: 0%; cursor: grab; transform: translate(-50%, -50%); .dot { height: 20px; width: 20px; border-radius: 50%; border: 2px solid #409eff; background: #fff; transition: transform 0.2s ease-in-out; &:hover { transform: scale(1.2); } } } .tips { user-select: none; position: absolute; top: -100%; border-radius: 4px; padding: 10px; z-index: 2000; font-size: 12px; line-height: 1.2; min-width: 10px; word-wrap: break-word; color: #fff; background: #303133; transform: translateX(-50%); &:after { position: absolute; border: 6px solid transparent; bottom: -12px; left: 50%; transform: translateX(-50%); content: ''; border-top-color: #303133; } } .cursor-default { cursor: grabbing !important; } ` progress = 0 mounted() { console.log('slider mounted') console.log(this.$refs, 'refs') this.$bar = this.$refs.bar this.$dotWrap = this.$refs.dotWrap this.$runway = this.$refs.runway this.$tips = this.$refs.tips } onMousedown(e) { document.documentElement.classList.toggle('cursor-default') const start = e.clientX let { value: preValue, step, max, min, progress } = this preValue = preValue || min const onMousemove = bind(document, 'mousemove', e => { const distance = e.clientX - start const scale = distance / this.$runway.clientWidth const diff = Math.round(scale * (max - min)) let newValue = Math.floor(preValue + diff) // console.log({ diff, preValue }) let newProgress = progress + Math.floor(scale * 100) if (newValue < min) { newValue = min } if (newValue > max) { newValue = max } if (newValue % step) { return } // console.warn(newValue) this.value = newValue this.setProgress(newProgress) }) const onMouseup = bind(document, 'mouseup', () => { unbind(document, 'mousemove', onMousemove) unbind(document, 'mouseup', onMouseup) }) } onClick(e) { if (e.target !== this.$refs.runway) { return } const { max, min, step } = this const { clientWidth } = e.target const { offsetX } = e const range = max - min const scale = offsetX / clientWidth // console.log( // { // scale, // range // }, // scale * range + min // ) let newValue = Math.floor(scale * range + min) const mod = newValue % step if (mod) { const half = step / 2 if (mod > half) { newValue += step - mod } else { newValue -= mod } } this.value = newValue console.log(scale * 100) //const progress = Math.floor(scale * 100) const progress = Math.floor(((newValue - min) / range) * 100) // console.log({ progress }) this.setProgress(progress) } setProgress(val) { val = Math.floor(val) val = val > 100 ? 100 : val val = val < 0 ? 0 : val this.$bar.style.width = `${val}%` this.$dotWrap.style.left = `${val}%` this.$tips.style.left = `${val}%` this.progress = val } render() { return html`
${this.value}
` } } Slider.reg('slider')