增加slider组件
parent
cc99526b36
commit
32f89ab889
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* {}
|
||||
* @author yutent<yutent.io@gmail.com>
|
||||
* @date 2023/03/21 16:14:10
|
||||
*/
|
||||
|
||||
import { nextTick, css, html, Component } from '@bd/core'
|
||||
import '../icon/index.js'
|
||||
import '../form/input.js'
|
||||
import '../scroll/index.js'
|
||||
class Select extends Component {
|
||||
static props = {
|
||||
value: {
|
||||
type: Array,
|
||||
default: [],
|
||||
attribute: false,
|
||||
observer() {
|
||||
// this.#updateChildrenStat()
|
||||
}
|
||||
},
|
||||
disabled: false,
|
||||
readonly: false
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
.icon {
|
||||
margin-right: 10px;
|
||||
--size: 14px;
|
||||
line-height: 100%;
|
||||
transform: rotate(90deg);
|
||||
transition: transform 0.2s ease-in-out;
|
||||
}
|
||||
.input {
|
||||
width: 200px;
|
||||
}
|
||||
.select {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
.select:focus-within {
|
||||
.icon {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
.option-list {
|
||||
height: 150px;
|
||||
border: 1px solid #e4e7ed;
|
||||
}
|
||||
}
|
||||
.option-list {
|
||||
position: absolute;
|
||||
margin: 5px 0;
|
||||
top: 110%;
|
||||
height: 150px;
|
||||
width: 100%;
|
||||
z-index: 1001;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
transition: height 0.2s ease-in-out;
|
||||
&:after {
|
||||
// content: '';
|
||||
// position: absolute;
|
||||
// left: 20%;
|
||||
// top: -16px;
|
||||
// border: 8px solid #fff;
|
||||
// border-top-color: transparent;
|
||||
// border-right-color: transparent;
|
||||
// border-left-color: transparent;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
mounted() {
|
||||
console.log('select mounted')
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="select">
|
||||
<wc-input readonly class="input">
|
||||
<wc-icon slot="append" class="icon" name="right" / >
|
||||
</wc-input>
|
||||
<wc-scroll class="option-list">
|
||||
<slot />
|
||||
</wc-scroll>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
class Option extends Component {
|
||||
static props = {
|
||||
value: '2'
|
||||
}
|
||||
|
||||
static styles = [css``]
|
||||
|
||||
mounted() {
|
||||
// console.log(this.value)
|
||||
// console.log(this.$refs)
|
||||
// console.log(this.root.innerHTML)
|
||||
console.log('option mounted')
|
||||
}
|
||||
onclick() {
|
||||
console.log(11)
|
||||
}
|
||||
render() {
|
||||
return html` <div ref="li">${this.value}</div> `
|
||||
}
|
||||
}
|
||||
|
||||
Select.reg('select')
|
||||
Option.reg('option')
|
|
@ -0,0 +1,165 @@
|
|||
/**
|
||||
* {}
|
||||
* @author yutent<yutent.io@gmail.com>
|
||||
* @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: null,
|
||||
min: null,
|
||||
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 {
|
||||
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: default;
|
||||
}
|
||||
`
|
||||
|
||||
mounted() {
|
||||
console.log('slider mounted')
|
||||
console.log(this.$refs, 'refs')
|
||||
|
||||
this.$bar = this.root.querySelector('.bar')
|
||||
this.$dotWrap = this.root.querySelector('.dot-wrapper')
|
||||
this.$runway = this.root.querySelector('.runway')
|
||||
this.$tips = this.root.querySelector('.tips')
|
||||
}
|
||||
onMousedown(e) {
|
||||
console.log(e)
|
||||
document.documentElement.classList.toggle('cursor-default')
|
||||
const start = e.clientX
|
||||
const preValue = this.value
|
||||
const onMousemove = bind(document, 'mousemove', e => {
|
||||
const distance = e.clientX - start
|
||||
const diff = Math.round((distance / this.$runway.clientWidth) * 100)
|
||||
let newValue = preValue + diff
|
||||
newValue = Math.floor(newValue)
|
||||
if (newValue < 0) {
|
||||
newValue = 0
|
||||
}
|
||||
if (newValue > 100) {
|
||||
newValue = 100
|
||||
}
|
||||
this.$bar.style.width = newValue + '%'
|
||||
this.$dotWrap.style.left = newValue + '%'
|
||||
this.$tips.style.left = newValue + '%'
|
||||
this.value = newValue
|
||||
})
|
||||
|
||||
bind(document, 'mouseup', e => {
|
||||
unbind(document, 'mousemove', onMousemove)
|
||||
document.documentElement.classList.toggle('cursor-default')
|
||||
})
|
||||
}
|
||||
onClick(e) {
|
||||
console.log(e)
|
||||
const { clientWidth } = e.target
|
||||
const { offsetX } = e
|
||||
this.value = Math.floor((offsetX / clientWidth) * 100)
|
||||
const barWidth = `${this.value}%`
|
||||
|
||||
this.$bar.style.width = barWidth
|
||||
this.$dotWrap.style.left = barWidth
|
||||
this.$tips.style.left = barWidth
|
||||
}
|
||||
render() {
|
||||
return html`<div class="slider" ref="slider">
|
||||
<div class="runway" @click=${this.onClick}>
|
||||
<div class="bar"></div>
|
||||
<div class="dot-wrapper" @mousedown=${this.onMousedown}>
|
||||
<div class="dot" ref="dot"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tips">${this.value}</div>
|
||||
</div>`
|
||||
}
|
||||
}
|
||||
|
||||
Slider.reg('slider')
|
Loading…
Reference in New Issue