From 32f89ab889e8179b02c8bd3530f8765406a30ec7 Mon Sep 17 00:00:00 2001 From: chenjiajian <770230504@qq.com> Date: Thu, 23 Mar 2023 11:41:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0slider=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/form/select.js | 113 ++++++++++++++++++++++++++++++ src/slider/index.js | 165 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 278 insertions(+) create mode 100644 src/form/select.js create mode 100644 src/slider/index.js diff --git a/src/form/select.js b/src/form/select.js new file mode 100644 index 0000000..0a3c80c --- /dev/null +++ b/src/form/select.js @@ -0,0 +1,113 @@ +/** + * {} + * @author yutent + * @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` +
+ + + + + + +
+ ` + } +} + +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`
${this.value}
` + } +} + +Select.reg('select') +Option.reg('option') diff --git a/src/slider/index.js b/src/slider/index.js new file mode 100644 index 0000000..59b8f06 --- /dev/null +++ b/src/slider/index.js @@ -0,0 +1,165 @@ +/** + * {} + * @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: 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`
+
+
+
+
+
+
+
${this.value}
+
` + } +} + +Slider.reg('slider')