Merge branch 'master' of github.com:9th-js/wcui

master
yutent 2023-03-24 17:04:36 +08:00
commit ae48529d72
1 changed files with 232 additions and 118 deletions

View File

@ -4,161 +4,246 @@
* @date 2023/03/21 16:14:10 * @date 2023/03/21 16:14:10
*/ */
import { nextTick, css, bind, unbind, html, Component } from '@bd/core' import { css, bind, unbind, html, Component } from '@bd/core'
class Slider extends Component { class Slider extends Component {
static props = { static props = {
value: { value: {
type: Number, type: Number,
default: 0, default: 0,
observer() {} observer(val) {
this.$bar && this.initValue(val)
}
}, },
type: 'info',
max: 100, max: 100,
min: 0, min: 0,
step: 1, step: 1,
disabled: false, disabled: false,
readonly: false, readonly: false,
vertical: false, vertical: false
'show-tooltip': true
} }
static styles = css` static styles = [
:host { css`
display: block; :host {
width: 100%; display: block;
height: 38px; 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;
} }
} .slider {
.dot-wrapper { position: relative;
position: absolute; display: flex;
display: flex; align-items: center;
justify-content: center; height: 100%;
align-items: center; }
height: 36px; .runway {
width: 36px; flex: 1;
top: 50%; position: relative;
left: 0%; height: 6px;
cursor: grab; // width: 100%;
transform: translate(-50%, -50%); background: #e4e7ed;
.dot { border-radius: 99rem;
height: 20px; cursor: pointer;
width: 20px; .bar {
border-radius: 50%; flex: 1;
border: 2px solid #409eff; pointer-events: none;
background: #fff; position: absolute;
transition: transform 0.2s ease-in-out; height: 100%;
&:hover { width: 0%;
transform: scale(1.2); border-radius: 99rem;
background: var(--color-blue-2, #409eff);
} }
} }
} .dot-wrapper {
.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; position: absolute;
border: 6px solid transparent; display: flex;
bottom: -12px; justify-content: center;
left: 50%; align-items: center;
transform: translateX(-50%); height: 36px;
content: ''; width: 36px;
border-top-color: #303133; top: 50%;
left: 0%;
cursor: grab;
transform: translate(-50%, -50%);
.dot {
height: 20px;
width: 20px;
border-radius: 50%;
border: 2px solid var(--color-blue-2, #409eff);
background: #fff;
transition: transform 0.2s ease-in-out;
&:hover {
transform: scale(1.2);
}
}
} }
} .tips {
.cursor-default { opacity: 0;
cursor: grabbing !important; pointer-events: none;
} 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%);
transition: opacity 0.2s ease-in-out;
&.show {
opacity: 1;
}
&:after {
position: absolute;
border: 6px solid transparent;
bottom: -12px;
left: 50%;
transform: translateX(-50%);
content: '';
border-top-color: #303133;
}
}
`,
//状态
css`
:host([vertical]) {
display: inline-block;
width: 38px;
height: 250px;
.slider {
justify-content: center;
.runway {
flex: 0 0 auto;
display: flex;
flex-direction: column-reverse;
width: 6px;
height: 100%;
cursor: pointer;
.bar {
height: 0%;
width: 100%;
}
.dot-wrapper {
left: 50%;
top: 100%;
transform: translate(-50%, -50%);
}
}
}
.tips {
top: 100%;
left: 50%;
transform: translate(-50%, -180%);
}
}
:host([loading]),
:host([disabled]) {
pointer-events: none;
cursor: not-allowed;
opacity: 0.6;
}
`,
//配色
css`
$colors: (
primary: 'teal',
info: 'blue',
success: 'green',
warning: 'orange',
danger: 'red',
secondary: 'dark',
help: 'grey'
);
@loop $t, $c in $colors {
:host([type='#{$t}']) {
.bar {
background-color: var(--color-#{$c}-2);
}
.dot {
border-color: var(--color-#{$c}-2);
}
}
}
`
]
progress = 0 progress = 0
mounted() { mounted() {
console.log('slider mounted')
console.log(this.$refs, 'refs')
this.$bar = this.$refs.bar this.$bar = this.$refs.bar
this.$dotWrap = this.$refs.dotWrap this.$dotWrap = this.$refs.dotWrap
this.$runway = this.$refs.runway this.$runway = this.$refs.runway
this.$tips = this.$refs.tips this.$tips = this.$refs.tips
this.initValue(this.value)
} }
onMousedown(e) { onMousedown(e) {
document.documentElement.classList.toggle('cursor-default') let {
const start = e.clientX value: preValue,
let { value: preValue, step, max, min, progress } = this step,
max,
min,
progress,
vertical,
disabled,
readOnly
} = this
if (disabled || readOnly) {
return
}
this.$tips.classList.toggle('show')
preValue = preValue || min preValue = preValue || min
const start = vertical ? e.clientY : e.clientX
const onMousemove = bind(document, 'mousemove', e => { const onMousemove = bind(document, 'mousemove', e => {
const distance = e.clientX - start e.preventDefault()
const scale = distance / this.$runway.clientWidth const distance = (vertical ? e.clientY : e.clientX) - start
const scale =
(distance /
(vertical ? this.$runway.clientHeight : this.$runway.clientWidth)) *
(vertical ? -1 : 1)
const diff = Math.round(scale * (max - min)) const diff = Math.round(scale * (max - min))
let newValue = Math.floor(preValue + diff)
// console.log({ diff, preValue })
let newProgress = progress + Math.floor(scale * 100) let newProgress = progress + Math.floor(scale * 100)
if (newValue < min) { let newValue = Math.floor(preValue + diff)
newValue = min newValue = Math.max(newValue, min)
} newValue = Math.min(newValue, max)
if (newValue > max) {
newValue = max
}
if (newValue % step) { if (newValue % step) {
return return
} }
// console.warn(newValue)
this.value = newValue this.value = newValue
this.setProgress(newProgress) requestAnimationFrame(() => {
this.setProgress(vertical ? 100 - newProgress : newProgress)
})
this.$emit('input')
}) })
const onMouseup = bind(document, 'mouseup', () => { const onMouseup = bind(document, 'mouseup', () => {
unbind(document, 'mousemove', onMousemove) unbind(document, 'mousemove', onMousemove)
unbind(document, 'mouseup', onMouseup) unbind(document, 'mouseup', onMouseup)
this.$tips.classList.toggle('show')
this.$emit('change')
}) })
} }
onClick(e) { onClick(e) {
if (e.target !== this.$refs.runway) { if (e.target !== this.$refs.runway) {
return return
} }
const { max, min, step } = this const { max, min, step, vertical, disabled, readOnly } = this
const { clientWidth } = e.target if (disabled || readOnly) {
const { offsetX } = e return
}
const { clientWidth, clientHeight } = e.target
const { offsetX, offsetY } = e
const range = max - min const range = max - min
const scale = offsetX / clientWidth const scale =
// console.log( (vertical ? offsetY : offsetX) / (vertical ? clientHeight : clientWidth)
// {
// scale,
// range
// },
// scale * range + min
// )
let newValue = Math.floor(scale * range + min) let newValue = Math.floor(scale * range + min)
const mod = newValue % step const mod = newValue % step
if (mod) { if (mod) {
@ -169,21 +254,50 @@ class Slider extends Component {
newValue -= mod newValue -= mod
} }
} }
this.value = newValue this.value = vertical ? range - newValue : newValue
console.log(scale * 100)
//const progress = Math.floor(scale * 100)
const progress = Math.floor(((newValue - min) / range) * 100) const progress = Math.floor(((newValue - min) / range) * 100)
// console.log({ progress }) this.setProgress(progress)
this.$emit('change')
if (!this.timeout) {
this.$tips.classList.toggle('show')
} else {
clearTimeout(this.timeout)
this.timeout = null
}
this.timeout = setTimeout(() => {
this.$tips.classList.toggle('show')
this.timeout = null
}, 1000)
}
initValue(val) {
const { max, min, vertical, disabled, readOnly } = this
if (disabled || readOnly) {
return
}
const range = max - min
val = Math.max(val, min)
val = Math.min(val, max)
this.value = val
let progress = Math.floor(((val - min) / range) * 100)
progress = vertical ? 100 - progress : progress
this.setProgress(progress) this.setProgress(progress)
} }
setProgress(val) { setProgress(val) {
const { vertical } = this
val = Math.floor(val) val = Math.floor(val)
val = val > 100 ? 100 : val val = Math.min(val, 100)
val = val < 0 ? 0 : val val = Math.max(val, 0)
this.$bar.style.width = `${val}%` if (vertical) {
this.$dotWrap.style.left = `${val}%` this.$bar.style.height = `${100 - val}%`
this.$tips.style.left = `${val}%` this.$dotWrap.style.top = `${val}%`
this.progress = val this.$tips.style.top = `${val}%`
this.progress = 100 - val
} else {
this.$bar.style.width = `${val}%`
this.$dotWrap.style.left = `${val}%`
this.$tips.style.left = `${val}%`
this.progress = val
}
} }
render() { render() {
return html`<div class="slider" ref="slider"> return html`<div class="slider" ref="slider">