diff --git a/Readme.md b/Readme.md index 1e3bd61..a34375a 100644 --- a/Readme.md +++ b/Readme.md @@ -19,7 +19,7 @@ - [x] `wc-space`间隔组件 - [ ] `wc-avatar`头像组件 - [x] `wc-badge`徽标组件 -- [ ] `wc-drawer`抽屉组件 +- [x] `wc-drawer`抽屉组件 - [ ] `wc-collapse`折叠组件 - [ ] `wc-counter`倒计时组件 - [ ] `wc-drag`拖拽组件 diff --git a/package.json b/package.json index df00c48..618f3e3 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@bd/wcui", + "name": "@bd/ui", "version": "1.0.0", "description": "", "files": [ diff --git a/src/drag/core.js b/src/drag/core.js new file mode 100644 index 0000000..c0511bb --- /dev/null +++ b/src/drag/core.js @@ -0,0 +1,137 @@ +/** + * 拖拽插件的核心部分 + * @author yutent + * @date 2019/08/23 19:41:21 + */ + +import { $, bind, unbind, fire } from '@bd/core' + +const DEF_OPT = { + axis: '', // x | y | xy 拖拽方向 + limit: false, // false | window | parent 拖拽范围 + overflow: true // 是否可拖拽出可视区外 +} + +export default class Drag { + constructor(elem) { + this.$elem = elem + + this.#init() + } + + #init() { + this.$elem.style.transform = '' + var { x, y } = this.$elem.getBoundingClientRect() + // _x, _y是位移,用于数据修正 + this.pos = { x, y, _x: 0, _y: 0 } + } + + // drag by + by(node, opt = {}) { + this.$drag = node + this.opt = Object.assign(Object.create(null), DEF_OPT, opt) + + // + if (this.opt.limit !== false) { + this.opt.overflow = false + } + + // 鼠标状态图标 + node.style.cursor = 'move' + + this._handleResize = bind(window, 'resize', this.#init.bind(this)) + + // let + this._handleMousedown = bind(node, 'mousedown', ev => { + if (this.disabled) { + return + } + var bcr = this.$elem.getBoundingClientRect() + + /* 修正由于页面有滚动距离,导致拖拽位移计算不正确的情况 */ + if (bcr.x - this.pos._x !== this.pos.x) { + this.pos.x = bcr.x - this.pos._x + } + if (bcr.y - this.pos._y !== this.pos.y) { + this.pos.y = bcr.y - this.pos._y + } + + let mx = ev.pageX + let my = ev.pageY + + let ww = document.documentElement.clientWidth + let wh = document.documentElement.clientHeight + + let tw = bcr.width + let th = bcr.height + + //限制区域, 4个值依次是: 上, 右, 下, 左 + let limit = [0, ww - tw, wh - th, 0] + if (this.opt.limit === 'parent') { + let pbcr = this.$elem.parentNode.getBoundingClientRect() + limit = [pbcr.top, pbcr.right - tw, pbcr.bottom - th, pbcr.left] + } + + let handleMove = bind(document, 'mousemove', ev => { + // 防止拖动到边缘时导致页面滚动 + ev.preventDefault() + + let _x = ev.pageX - mx + (bcr.x - this.pos.x) + let _y = ev.pageY - my + (bcr.y - this.pos.y) + + // 将另外一个方向的值清零来实现单向拖拽 + if (this.opt.axis === 'x') { + _y = 0 + } + if (this.opt.axis === 'y') { + _x = 0 + } + + // 限制不可拖拽出指定区域(可视区或者父容器) + if (this.opt.overflow === false) { + if (_x < limit[3] - this.pos.x) { + _x = limit[3] - this.pos.x + } else if (_x > limit[1] - this.pos.x) { + _x = limit[1] - this.pos.x + } + + if (_y < limit[0] - this.pos.y) { + _y = limit[0] - this.pos.y + } else if (_y > limit[2] - this.pos.y) { + _y = limit[2] - this.pos.y + } + } + this.pos._x = _x + this.pos._y = _y + fire(this.$elem, 'dragging', { + offset: { + x: this.pos.x + _x, + y: this.pos.y + _y + }, + moved: { x: _x, y: _y } + }) + this.$elem.style.transform = `translate(${_x}px, ${_y}px)` + }) + + let handleUp = bind(document, 'mouseup', ev => { + fire(this.$elem, 'dragged', { + offset: { + x: this.pos.x + this.pos._x, + y: this.pos.y + this.pos._y + }, + moved: { x: this.pos._x, y: this.pos._y } + }) + + unbind(document, 'mousemove', handleMove) + unbind(document, 'mouseup', handleUp) + }) + }) + + return this + } + + destroy() { + unbind(window, 'resize', this._handleResize) + unbind(this.$drag, 'mousedown', this._handleMousedown) + } +} diff --git a/src/drawer/index.js b/src/drawer/index.js index fe90fd8..45f5b5c 100644 --- a/src/drawer/index.js +++ b/src/drawer/index.js @@ -4,37 +4,56 @@ * @date 2023/03/27 10:39:29 */ -import { - css, - html, - bind, - unbind, - Component, - outsideClick, - clearOutsideClick, - nextTick, - classMap, - styleMap -} from '@bd/core' +import { css, html, Component, nextTick, styleMap } from '@bd/core' -const DIRECTION = { - left: 'l2r-in', - right: 'r2l-in', - top: 't2b-in', - bottom: 'b2t-in' +const ANIMATION = { + left: { + custom: [ + { transform: ' translateX(-100%)' }, + { transform: ' translateX(0)' } + ] + }, + right: { + custom: [ + { transform: ' translateX(100%)' }, + { transform: ' translateX(0)' } + ] + }, + top: { + custom: [ + { transform: ' translateY(-100%)' }, + { transform: ' translateY(0)' } + ] + }, + bottom: { + custom: [ + { transform: ' translateY(100%)' }, + { transform: ' translateY(0)' } + ] + } } class Drawer extends Component { + static animation = {} static props = { - title: { type: String, default: '', attribute: false }, + title: '', from: 'right', - visible: false + visible: { + type: Boolean, + default: false, + observer(v) { + this.$anim.start(!v) + this.$refs.drawer.$anim.start(!v) + } + }, + width: '', + height: '', + 'mask-close': false } static styles = [ css` :host { - display: none; position: fixed; left: 0; top: 0; @@ -42,9 +61,8 @@ class Drawer extends Component { width: 100%; height: 100%; background: rgba(0, 0, 0, 0.3); - transition: opacity 0.3s linear; - opacity: 0; } + .drawer { display: flex; flex-direction: column; @@ -54,19 +72,6 @@ class Drawer extends Component { font-size: 14px; background: #fff; box-shadow: 0 0 24px rgba(0, 0, 0, 0.2); - - &.l2r-in { - animation: l2r-in 0.3s ease-in-out forwards; - } - &.r2l-in { - animation: r2l-in 0.3s ease-in-out forwards; - } - &.t2b-in { - animation: t2b-in 0.3s ease-in-out forwards; - } - &.b2t-in { - animation: b2t-in 0.3s ease-in-out forwards; - } } .header { @@ -90,11 +95,6 @@ class Drawer extends Component { flex: 1; padding: 16px; } - - :host([visible]) { - display: block; - opacity: 1; - } `, css` :host([from='left']), @@ -131,40 +131,6 @@ class Drawer extends Component { bottom: 0; transform: translateY(100%); } - `, - css` - @keyframes r2l-in { - from { - transform: translateX(100%); - } - to { - transform: translateX(0); - } - } - @keyframes l2r-in { - from { - transform: translateX(-100%); - } - to { - transform: translateX(0); - } - } - @keyframes b2t-in { - from { - transform: translateY(100%); - } - to { - transform: translateY(0); - } - } - @keyframes t2b-in { - from { - transform: translateY(-100%); - } - to { - transform: translateY(0); - } - } ` ] @@ -173,24 +139,35 @@ class Drawer extends Component { } mounted() { - console.log('mounted title: ', this.title) + this.$on('click', ev => { + let path = ev.composedPath() + + if (path[0] === ev.currentTarget && this['mask-close']) { + this.closeDrawer() + } + }) } render() { - let classes = classMap({ - drawer: true, - [DIRECTION[this.from]]: this.visible - }) + let style = {} + if ((this.from === 'left' || this.from === 'right') && this.width) { + style = { width: this.width } + } else if ((this.from === 'top' || this.from === 'bottom') && this.height) { + style = { height: this.height } + } return html` -
+
${this.title}
-
- -
+
` } diff --git a/src/form/checkbox.js b/src/form/checkbox.js index 5cc1012..ee505fd 100644 --- a/src/form/checkbox.js +++ b/src/form/checkbox.js @@ -79,7 +79,6 @@ class CheckboxItem extends Component { :host { display: inline-flex; align-items: center; - line-height: 1; font-size: 14px; cursor: pointer; diff --git a/src/form/radio.js b/src/form/radio.js index cbb7bf0..30a7839 100644 --- a/src/form/radio.js +++ b/src/form/radio.js @@ -76,7 +76,6 @@ class RadioItem extends Component { :host { display: inline-flex; align-items: center; - line-height: 1; font-size: 14px; cursor: pointer; diff --git a/src/form/switch.js b/src/form/switch.js index 1e2385d..1624ba2 100644 --- a/src/form/switch.js +++ b/src/form/switch.js @@ -13,7 +13,6 @@ class Switch extends Component { default: '', attribute: false }, - checked: false, disabled: false, readonly: false } @@ -23,7 +22,6 @@ class Switch extends Component { :host { display: inline-flex; align-items: center; - line-height: 1; font-size: 14px; cursor: pointer; @@ -46,26 +44,13 @@ class Switch extends Component { display: flex; justify-content: center; align-items: center; - width: 14px; - height: 14px; - margin-right: 4px; - border: 1px solid var(--color-dark-1); - border-radius: 4px; - background: #fff; + width: 36px; + height: 18px; + padding: 3px; + margin-right: 5px; + border-radius: 16px; + background: var(--color-dark-1); transition: box-shadow 0.15s linear; - - wc-icon { - display: block; - visibility: hidden; - width: 10px; - height: 10px; - transform: scale(0); - transition: transform 0.15s linear; - } - } - &:host([checked]) .dot wc-icon { - visibility: visible; - transform: scale(1); } } `, @@ -112,8 +97,8 @@ class Switch extends Component { font-size: map.get($v, 'f'); .dot { - width: #{map.get($v, 'f')}; - height: #{map.get($v, 'f')}; + width: #{map.get($v, 'f') * 2.5}; + height: #{map.get($v, 'f') * 1.25}; } } } @@ -133,15 +118,11 @@ class Switch extends Component { @loop $t, $c in $colors { :host([type='#{$t}']) { label { - color: var(--color-#{$c}-2); + color: var(--color-#{$c}-1); } .dot { - border-color: var(--color-#{$c}-2); - - &::after { - background: var(--color-#{$c}-2); - } + background: var(--color-#{$c}-1); } &:host(:focus-within) .dot { @@ -201,7 +182,7 @@ class Switch extends Component { @click=${this.handleClick} @keydown=${this.handleClick} > - + ` }