Commit a17511c3979856a280703ff7d13c21079799ae41

Authored by 梁灏
1 parent 4616d882

Drawer add draggable prop

examples/routers/drawer.vue
... ... @@ -5,69 +5,68 @@
5 5 <Button @click="visible3 = true">show3</Button>
6 6  
7 7 <div style="width: 500px;height:500px;background: green;position: relative;">
8   -
  8 + <Drawer v-model="visible" placement="left" draggable inner :transfer="false" width="50" @on-resize-width="hrw" title="抽屉标题" :styles="styles" @on-close="handleClose">
  9 + <p>一些内容</p>
  10 + <p>一些内容</p>
  11 + <p>一些内容</p>
  12 + <Button @click="visible2 = true">show2</Button>
  13 + <p>一些内容</p>
  14 + <p>一些内容</p>
  15 + <p>一些内容</p>
  16 + <p>一些内容</p>
  17 + <p>一些内容</p>
  18 + <p>一些内容</p>
  19 + <p>一些内容</p>
  20 + <p>一些内容</p>
  21 + <p>一些内容</p>
  22 + <p>一些内容</p>
  23 + <p>一些内容</p>
  24 + <p>一些内容</p>
  25 + <p>一些内容</p>
  26 + <p>一些内容</p>
  27 + <p>一些内容</p>
  28 + <p>一些内容</p>
  29 + <p>一些内容</p>
  30 + <p>一些内容</p>
  31 + <p>一些内容</p>
  32 + <p>一些内容</p>
  33 + <p>一些内容</p>
  34 + <p>一些内容</p>
  35 + <p>一些内容</p>
  36 + <p>一些内容</p>
  37 + <p>一些内容</p>
  38 + <p>一些内容</p>
  39 + <p>一些内容</p>
  40 + <p>一些内容</p>
  41 + <p>一些内容</p>
  42 + <p>一些内容</p>
  43 + <p>一些内容</p>
  44 + <p>一些内容</p>
  45 + <p>一些内容</p>
  46 + <p>一些内容</p>
  47 + <p>一些内容</p>
  48 + <p>一些内容</p>
  49 + <p>一些内容</p>
  50 + <p>一些内容</p>
  51 + <p>一些内容</p>
  52 + <p>一些内容</p>
  53 + <p>一些内容</p>
  54 + <p>一些内容</p>
  55 + <p>一些内容</p>
  56 + <p>一些内容</p>
  57 + <p>一些内容</p>
  58 + <p>一些内容</p>
  59 + <p>一些内容</p>
  60 + <p>一些内容</p>
  61 + <p>一些内容</p>
  62 + <p>一些内容</p>
  63 + <p>一些内容</p>
  64 + </Drawer>
9 65 </div>
10 66  
11   - <Drawer v-model="visible" width="70" inner title="抽屉标题" :styles="styles" @on-close="handleClose">
12   - <p>一些内容</p>
13   - <p>一些内容</p>
14   - <p>一些内容</p>
15   - <Button @click="visible2 = true">show2</Button>
16   - <p>一些内容</p>
17   - <p>一些内容</p>
18   - <p>一些内容</p>
19   - <p>一些内容</p>
20   - <p>一些内容</p>
21   - <p>一些内容</p>
22   - <p>一些内容</p>
23   - <p>一些内容</p>
24   - <p>一些内容</p>
25   - <p>一些内容</p>
26   - <p>一些内容</p>
27   - <p>一些内容</p>
28   - <p>一些内容</p>
29   - <p>一些内容</p>
30   - <p>一些内容</p>
31   - <p>一些内容</p>
32   - <p>一些内容</p>
33   - <p>一些内容</p>
34   - <p>一些内容</p>
35   - <p>一些内容</p>
36   - <p>一些内容</p>
37   - <p>一些内容</p>
38   - <p>一些内容</p>
39   - <p>一些内容</p>
40   - <p>一些内容</p>
41   - <p>一些内容</p>
42   - <p>一些内容</p>
43   - <p>一些内容</p>
44   - <p>一些内容</p>
45   - <p>一些内容</p>
46   - <p>一些内容</p>
47   - <p>一些内容</p>
48   - <p>一些内容</p>
49   - <p>一些内容</p>
50   - <p>一些内容</p>
51   - <p>一些内容</p>
52   - <p>一些内容</p>
53   - <p>一些内容</p>
54   - <p>一些内容</p>
55   - <p>一些内容</p>
56   - <p>一些内容</p>
57   - <p>一些内容</p>
58   - <p>一些内容</p>
59   - <p>一些内容</p>
60   - <p>一些内容</p>
61   - <p>一些内容</p>
62   - <p>一些内容</p>
63   - <p>一些内容</p>
64   - <p>一些内容</p>
65   - <p>一些内容</p>
66   - <p>一些内容</p>
67   - </Drawer>
68 67  
69 68  
70   - <Drawer v-model="visible2" title="抽屉标题" placement="right">
  69 + <Drawer v-model="visible2" draggable title="抽屉标题" placement="right">
71 70 <p>一些内容</p>
72 71 <p>一些内容</p>
73 72 <p>一些内容</p>
... ... @@ -126,7 +125,7 @@
126 125 <p>一些内容</p>
127 126 <p>一些内容22</p>
128 127 </Drawer>
129   - <Drawer v-model="visible3" placement="left">
  128 + <Drawer v-model="visible3" draggable placement="left">
130 129 <p>一些内容</p>
131 130 <p>一些内容</p>
132 131 <p>一些内容</p>
... ... @@ -207,6 +206,9 @@
207 206 methods: {
208 207 handleClose () {
209 208 this.$Message.info('关闭了');
  209 + },
  210 + hrw (w) {
  211 + console.log(w);
210 212 }
211 213 }
212 214 };
... ...
src/components/drawer/drawer.vue
... ... @@ -15,6 +15,15 @@
15 15 <div :class="[prefixCls + '-header']" v-if="showHead"><slot name="header"><div :class="[prefixCls + '-header-inner']">{{ title }}</div></slot></div>
16 16 <div :class="[prefixCls + '-body']" :style="styles"><slot></slot></div>
17 17 </div>
  18 + <div class="ivu-drawer-drag" :class="{ 'ivu-drawer-drag-left': placement === 'left' }" v-if="draggable" @mousedown="handleTriggerMousedown">
  19 + <slot name="trigger">
  20 + <div class="ivu-drawer-drag-move-trigger">
  21 + <div class="ivu-drawer-drag-move-trigger-point">
  22 + <i></i><i></i><i></i><i></i><i></i>
  23 + </div>
  24 + </div>
  25 + </slot>
  26 + </div>
18 27 </div>
19 28 </transition>
20 29 </div>
... ... @@ -27,6 +36,8 @@
27 36 import Emitter from '../../mixins/emitter';
28 37 import ScrollbarMixins from '../modal/mixins-scrollbar';
29 38  
  39 + import { on, off } from '../../utils/dom';
  40 +
30 41 const prefixCls = 'ivu-drawer';
31 42  
32 43 export default {
... ... @@ -90,6 +101,11 @@
90 101 inner: {
91 102 type: Boolean,
92 103 default: false
  104 + },
  105 + // Whether drag and drop is allowed to adjust width
  106 + draggable: {
  107 + type: Boolean,
  108 + default: false
93 109 }
94 110 },
95 111 data () {
... ... @@ -98,6 +114,11 @@
98 114 visible: this.value,
99 115 wrapShow: false,
100 116 showHead: true,
  117 + canMove: false,
  118 + dragWidth: this.width,
  119 + wrapperWidth: this.width,
  120 + wrapperLeft: 0,
  121 + minWidth: 256
101 122 };
102 123 },
103 124 computed: {
... ... @@ -108,14 +129,15 @@
108 129 [`${prefixCls}-hidden`]: !this.wrapShow,
109 130 [`${this.className}`]: !!this.className,
110 131 [`${prefixCls}-no-mask`]: !this.mask,
111   - [`${prefixCls}-wrap-inner`]: this.inner
  132 + [`${prefixCls}-wrap-inner`]: this.inner,
  133 + [`${prefixCls}-wrap-dragging`]: this.canMove
112 134 }
113 135 ];
114 136 },
115 137 mainStyles () {
116 138 let style = {};
117 139  
118   - const width = parseInt(this.width);
  140 + const width = parseInt(this.dragWidth);
119 141  
120 142 const styleWidth = {
121 143 width: width <= 100 ? `${width}%` : `${width}px`
... ... @@ -168,6 +190,38 @@
168 190 const className = event.target.getAttribute('class');
169 191 if (className && className.indexOf(`${prefixCls}-wrap`) > -1) this.handleMask();
170 192 },
  193 + handleMousemove (event) {
  194 + if (!this.canMove || !this.draggable) return;
  195 + // 更新容器宽度和距离左侧页面距离,如果是window则距左侧距离为0
  196 + this.handleSetWrapperWidth();
  197 + const left = event.pageX - this.wrapperLeft;
  198 + // 如果抽屉方向为右边,宽度计算需用容器宽度减去left
  199 + let width = this.placement === 'right' ? this.wrapperWidth - left : left;
  200 + // 限定最小宽度
  201 + width = Math.max(width, parseFloat(this.minWidth));
  202 + event.atMin = width === parseFloat(this.minWidth);
  203 + // 如果当前width不大于100,视为百分比
  204 + if (width <= 100) width = (width / this.wrapperWidth) * 100;
  205 + this.dragWidth = width;
  206 + this.$emit('on-resize-width', parseInt(this.dragWidth));
  207 + },
  208 + handleSetWrapperWidth () {
  209 + const {
  210 + width,
  211 + left
  212 + } = this.$el.getBoundingClientRect();
  213 + this.wrapperWidth = width;
  214 + this.wrapperLeft = left;
  215 + },
  216 + handleMouseup () {
  217 + if (!this.draggable) return;
  218 + this.canMove = false;
  219 + },
  220 + handleTriggerMousedown () {
  221 + this.canMove = true;
  222 + // 防止鼠标选中抽屉中文字,造成拖动trigger触发浏览器原生拖动行为
  223 + window.getSelection().removeAllRanges();
  224 + },
171 225 },
172 226 mounted () {
173 227 if (this.visible) {
... ... @@ -181,8 +235,14 @@
181 235 }
182 236  
183 237 this.showHead = showHead;
  238 +
  239 + on(document, 'mousemove', this.handleMousemove);
  240 + on(document, 'mouseup', this.handleMouseup);
  241 + this.handleSetWrapperWidth();
184 242 },
185 243 beforeDestroy () {
  244 + off(document, 'mousemove', this.handleMousemove);
  245 + off(document, 'mouseup', this.handleMouseup);
186 246 this.removeScrollEffect();
187 247 },
188 248 watch: {
... ...
src/styles/components/drawer.less
... ... @@ -36,6 +36,10 @@
36 36 position: absolute;
37 37 overflow: hidden;
38 38 }
  39 +
  40 + &-dragging{
  41 + user-select: none;
  42 + }
39 43 }
40 44  
41 45 &-wrap * {
... ... @@ -93,4 +97,36 @@
93 97 &-no-mask{
94 98 pointer-events: none;
95 99 }
  100 +
  101 + &-drag{
  102 + top: 0;
  103 + height: 100%;
  104 + width: 0;
  105 + position: absolute;
  106 + &-left{
  107 + right: 0;
  108 + }
  109 + &-move-trigger{
  110 + width: 8px;
  111 + height: 100px;
  112 + line-height: 100px;
  113 + position: absolute;
  114 + top: 50%;
  115 + background: rgb(243, 243, 243);
  116 + transform: translate(-50%, -50%);
  117 + border-radius: ~"4px / 6px";
  118 + box-shadow: 0 0 1px 1px rgba(0, 0, 0, .2);
  119 + cursor: col-resize;
  120 + &-point{
  121 + display: inline-block;
  122 + width: 50%;
  123 + transform: translateX(50%);
  124 + i{
  125 + display: block;
  126 + border-bottom: 1px solid rgb(192, 192, 192);
  127 + padding-bottom: 2px;
  128 + }
  129 + }
  130 + }
  131 + }
96 132 }
97 133 \ No newline at end of file
... ...