Commit a17511c3979856a280703ff7d13c21079799ae41

Authored by 梁灏
1 parent 4616d882

Drawer add draggable prop

examples/routers/drawer.vue
@@ -5,69 +5,68 @@ @@ -5,69 +5,68 @@
5 <Button @click="visible3 = true">show3</Button> 5 <Button @click="visible3 = true">show3</Button>
6 6
7 <div style="width: 500px;height:500px;background: green;position: relative;"> 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 </div> 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 <p>一些内容</p> 70 <p>一些内容</p>
72 <p>一些内容</p> 71 <p>一些内容</p>
73 <p>一些内容</p> 72 <p>一些内容</p>
@@ -126,7 +125,7 @@ @@ -126,7 +125,7 @@
126 <p>一些内容</p> 125 <p>一些内容</p>
127 <p>一些内容22</p> 126 <p>一些内容22</p>
128 </Drawer> 127 </Drawer>
129 - <Drawer v-model="visible3" placement="left"> 128 + <Drawer v-model="visible3" draggable placement="left">
130 <p>一些内容</p> 129 <p>一些内容</p>
131 <p>一些内容</p> 130 <p>一些内容</p>
132 <p>一些内容</p> 131 <p>一些内容</p>
@@ -207,6 +206,9 @@ @@ -207,6 +206,9 @@
207 methods: { 206 methods: {
208 handleClose () { 207 handleClose () {
209 this.$Message.info('关闭了'); 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,6 +15,15 @@
15 <div :class="[prefixCls + '-header']" v-if="showHead"><slot name="header"><div :class="[prefixCls + '-header-inner']">{{ title }}</div></slot></div> 15 <div :class="[prefixCls + '-header']" v-if="showHead"><slot name="header"><div :class="[prefixCls + '-header-inner']">{{ title }}</div></slot></div>
16 <div :class="[prefixCls + '-body']" :style="styles"><slot></slot></div> 16 <div :class="[prefixCls + '-body']" :style="styles"><slot></slot></div>
17 </div> 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 </div> 27 </div>
19 </transition> 28 </transition>
20 </div> 29 </div>
@@ -27,6 +36,8 @@ @@ -27,6 +36,8 @@
27 import Emitter from '../../mixins/emitter'; 36 import Emitter from '../../mixins/emitter';
28 import ScrollbarMixins from '../modal/mixins-scrollbar'; 37 import ScrollbarMixins from '../modal/mixins-scrollbar';
29 38
  39 + import { on, off } from '../../utils/dom';
  40 +
30 const prefixCls = 'ivu-drawer'; 41 const prefixCls = 'ivu-drawer';
31 42
32 export default { 43 export default {
@@ -90,6 +101,11 @@ @@ -90,6 +101,11 @@
90 inner: { 101 inner: {
91 type: Boolean, 102 type: Boolean,
92 default: false 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 data () { 111 data () {
@@ -98,6 +114,11 @@ @@ -98,6 +114,11 @@
98 visible: this.value, 114 visible: this.value,
99 wrapShow: false, 115 wrapShow: false,
100 showHead: true, 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 computed: { 124 computed: {
@@ -108,14 +129,15 @@ @@ -108,14 +129,15 @@
108 [`${prefixCls}-hidden`]: !this.wrapShow, 129 [`${prefixCls}-hidden`]: !this.wrapShow,
109 [`${this.className}`]: !!this.className, 130 [`${this.className}`]: !!this.className,
110 [`${prefixCls}-no-mask`]: !this.mask, 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 mainStyles () { 137 mainStyles () {
116 let style = {}; 138 let style = {};
117 139
118 - const width = parseInt(this.width); 140 + const width = parseInt(this.dragWidth);
119 141
120 const styleWidth = { 142 const styleWidth = {
121 width: width <= 100 ? `${width}%` : `${width}px` 143 width: width <= 100 ? `${width}%` : `${width}px`
@@ -168,6 +190,38 @@ @@ -168,6 +190,38 @@
168 const className = event.target.getAttribute('class'); 190 const className = event.target.getAttribute('class');
169 if (className && className.indexOf(`${prefixCls}-wrap`) > -1) this.handleMask(); 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 mounted () { 226 mounted () {
173 if (this.visible) { 227 if (this.visible) {
@@ -181,8 +235,14 @@ @@ -181,8 +235,14 @@
181 } 235 }
182 236
183 this.showHead = showHead; 237 this.showHead = showHead;
  238 +
  239 + on(document, 'mousemove', this.handleMousemove);
  240 + on(document, 'mouseup', this.handleMouseup);
  241 + this.handleSetWrapperWidth();
184 }, 242 },
185 beforeDestroy () { 243 beforeDestroy () {
  244 + off(document, 'mousemove', this.handleMousemove);
  245 + off(document, 'mouseup', this.handleMouseup);
186 this.removeScrollEffect(); 246 this.removeScrollEffect();
187 }, 247 },
188 watch: { 248 watch: {
src/styles/components/drawer.less
@@ -36,6 +36,10 @@ @@ -36,6 +36,10 @@
36 position: absolute; 36 position: absolute;
37 overflow: hidden; 37 overflow: hidden;
38 } 38 }
  39 +
  40 + &-dragging{
  41 + user-select: none;
  42 + }
39 } 43 }
40 44
41 &-wrap * { 45 &-wrap * {
@@ -93,4 +97,36 @@ @@ -93,4 +97,36 @@
93 &-no-mask{ 97 &-no-mask{
94 pointer-events: none; 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 \ No newline at end of file 133 \ No newline at end of file