1
1
<template >
2
- <div class =" g-crop-image-principal" >
3
- <div class =" image-wrap" :style =" { width:width + 'px',height: height + 'px' }" >
4
- <img ref =" crop-image" :src =" src" :style =" { width:'100%',height: '100%', }" >
5
- </div >
6
- <div class =" image-mask" v-if =" !hideCrop" >
7
- <div class =" mask top" :style =" { top:0, height: cropCSS.top + 'px', left: 0, width: '100%'}" ></div >
8
- <div class =" mask bottom" :style =" { bottom:0, top: (cropCSS.top + cropCSS.height) + 'px', left: 0, width: '100%'}" ></div >
9
- <div class =" mask left" :style =" {top: cropCSS.top + 'px', height: cropCSS.height + 'px', left:0, width: cropCSS.left + 'px'}" ></div >
10
- <div class =" mask right" :style =" {top: cropCSS.top + 'px', height: cropCSS.height + 'px', left: (cropCSS.left + cropCSS.width) + 'px', right: 0}" ></div >
11
- </div >
12
- <div class =" crop-box" v-if =" !hideCrop" v-on:touchstart.self =" drag" v-on:mousedown.self =" drag" :style =" {top: cropCSS.top + 'px', left: cropCSS.left + 'px', height: cropCSS.height + 'px', width: cropCSS.width + 'px'}" >
13
- <div class =" reference-line v" ></div >
14
- <div class =" reference-line h" ></div >
15
- <a class =" g-resize" v-on:touchstart.self =" resize" v-on:mousedown.self =" resize" ></a >
2
+ <div class =" image-aside" >
3
+ <div class =" g-crop-image-box" >
4
+ <div class =" g-crop-image-principal" v-on:touchstart.capture =" drag" v-on:mousedown.capture =" drag" >
5
+ <div class =" image-wrap" :style =" { width: width + 'px',height: height + 'px', left: left+ 'px', top: top + 'px', backgroundImage: 'url(' + src + ')', cursor: isResize ? 'default' : 'move'}" >
6
+ <img ref =" crop-image" style =" width :0 ;height :0 ;" :src =" src" />
7
+ </div >
8
+ <div class =" image-mask" v-if =" !isResize" >
9
+ <div class =" mask top" :style =" { top:0, height: cropCSS.top + 'px', left: 0, width: '100%'}" ></div >
10
+ <div class =" mask bottom" :style =" { bottom:0, top: (cropCSS.top + cropCSS.height) + 'px', left: 0, width: '100%'}" ></div >
11
+ <div class =" mask left" :style =" {top: cropCSS.top + 'px', height: cropCSS.height + 'px', left:0, width: cropCSS.left + 'px'}" ></div >
12
+ <div class =" mask right" :style =" {top: cropCSS.top + 'px', height: cropCSS.height + 'px', left: (cropCSS.left + cropCSS.width) + 'px', right: 0}" ></div >
13
+ </div >
14
+ <div class =" crop-box" v-if =" !isResize" :style =" {top: cropCSS.top + 'px', left: cropCSS.left + 'px', height: cropCSS.height + 'px', width: cropCSS.width + 'px'}" >
15
+ <div class =" reference-line v" ></div >
16
+ <div class =" reference-line h" ></div >
17
+ <a class =" g-resize" v-on:touchstart.self =" resize" v-on:mousedown.self =" resize" ></a >
18
+ </div >
19
+
20
+ </div >
21
+ <resize-bar v-if =" resize" ref =" resizeBar" @resize =" resizeImage" ></resize-bar >
16
22
</div >
17
23
</div >
18
24
</template >
19
25
20
26
<style scoped>
27
+ .g-crop-image-principal {
28
+ overflow : hidden ;
29
+ background-color : #fff ;
30
+ background-image : -webkit-linear-gradient (bottom left , #efefef 25% , transparent 25% , transparent 75% , #efefef 75% , #efefef ),-webkit-linear-gradient (bottom left , #efefef 25% , transparent 25% , transparent 75% , #efefef 75% , #efefef );
31
+ background-image : -moz-linear-gradient (bottom left , #efefef 25% , transparent 25% , transparent 75% , #efefef 75% , #efefef ),-moz-linear-gradient (bottom left , #efefef 25% , transparent 25% , transparent 75% , #efefef 75% , #efefef );
32
+ background-image : -o-linear-gradient (bottom left , #efefef 25% , transparent 25% , transparent 75% , #efefef 75% , #efefef ),-o-linear-gradient (bottom left , #efefef 25% , transparent 25% , transparent 75% , #efefef 75% , #efefef );
33
+ background-image : linear-gradient (to top right , #efefef 25% , transparent 25% , transparent 75% , #efefef 75% , #efefef ),linear-gradient (to top right , #efefef 25% , transparent 25% , transparent 75% , #efefef 75% , #efefef );
34
+ background-position : 0 0 ,10px 10px ;
35
+ -webkit-background-size : 21px 21px ;
36
+ background-size : 21px 21px ;
37
+ }
38
+ .image-aside {
39
+ overflow : hidden ;
40
+ position : absolute ;
41
+ right : 30px ;
42
+ left :30px ;
43
+ top :70px ;
44
+ bottom :40px ;
45
+ text-align : center ;
46
+ }
47
+ .image-aside .image-wrap {
48
+ position : absolute ;
49
+ left : 0 ;
50
+ top : 0 ;
51
+ -webkit-touch-callout : none ;
52
+ -webkit-user-select : none ;
53
+ -khtml-user-select : none ;
54
+ -moz-user-select : none ;
55
+ -ms-user-select : none ;
56
+ user-select : none ;
57
+ box-shadow : 0 3px 5px -2px rgba (0 ,0 ,0 ,.25 );
58
+ background-size : cover ;
59
+ }
21
60
.image-mask {
22
61
position : absolute ;
23
62
left : 0 ;
30
69
background-color : rgba (255 ,255 ,255 ,.6 );
31
70
}
32
71
.crop-box {
72
+ z-index : 2000 ;
33
73
box-sizing : border-box ;
34
74
position : absolute ;
35
75
background : none ;
@@ -90,14 +130,17 @@ import drag from './lib/drag';
90
130
import resize from ' ./lib/resize' ;
91
131
import GIF_LOADING_SRC from ' ./lib/loading-gif' ;
92
132
import helper from ' ./lib/helper' ;
133
+ import ResizeBar from ' ./resize-bar.vue' ;
93
134
// set cropbox size in image
94
135
const CROPBOX_PERCENT = 75 ;
136
+ const isMobile = helper .isMobile ;
137
+ const areaWidth = window .innerWidth - 60 ;
138
+ const areaHeight = window .innerHeight - 110 ;
95
139
export default {
140
+ components: {
141
+ ResizeBar,
142
+ },
96
143
props: {
97
- formId: {
98
- type: String ,
99
- default: ' ' ,
100
- },
101
144
ratio: {
102
145
type: String ,
103
146
default: ' 1:1'
@@ -110,8 +153,8 @@ export default {
110
153
type: Number ,
111
154
default: 50 ,
112
155
},
113
- hideCrop : {
114
- type: [String , Boolean ],
156
+ isResize : {
157
+ type: [Boolean ],
115
158
default: false ,
116
159
}
117
160
},
@@ -121,6 +164,10 @@ export default {
121
164
src: GIF_LOADING_SRC ,
122
165
width: 24 ,
123
166
height: 24 ,
167
+ initWidth: 24 ,
168
+ initHeight: 24 ,
169
+ left: 0 ,
170
+ top: 0 ,
124
171
cropCSS: {
125
172
126
173
}
@@ -139,71 +186,103 @@ export default {
139
186
this .ratioH = 1 ;
140
187
this .ratioVal = this .ratio ;
141
188
}
142
- this .setLayout (w, h);
143
- this .setCropBox ();
144
189
this .natrualWidth = w;
145
190
this .natrualHeight = h;
191
+ this .setLayout (w, h);
192
+ const resizeBar = this .$refs .resizeBar ;
193
+ if (this .isResize ) {
194
+ resizeBar .setProgress (100 );
195
+ } else {
196
+ resizeBar .setProgress (0 );
197
+ }
146
198
return this .imgChangeRatio ;
147
199
},
148
-
149
200
resizeImage (progress ) {
150
- const w = this .natrualWidth * this .imgChangeRatio * progress;
151
- const h = this .natrualHeight * this .imgChangeRatio * progress;
201
+ let w,
202
+ h;
203
+ if (this .isResize ) {
204
+ w = this .natrualWidth * this .imgChangeRatio * progress;
205
+ h = this .natrualHeight * this .imgChangeRatio * progress;
206
+ } else {
207
+ w = this .initWidth + progress * (this .natrualWidth - this .initWidth );
208
+ h = this .initHeight + progress * (this .natrualHeight - this .initHeight );
209
+ }
152
210
if (w <= this .minWidth || h < this .minHeight ) {
153
211
return ;
154
212
}
155
- this ._setStyle (w, h, w/ h);
156
- this .setCropBox ();
213
+ this .left += (this .width - w) / 2 ;
214
+ this .top += (this .height - h) / 2 ;
215
+ this .width = w;
216
+ this .height = h;
217
+ this .imgChangeRatio = this .width / this .natrualWidth ;
157
218
},
158
219
159
220
setLayout (w , h ) {
160
- let H = window . innerHeight - 80 ,
161
- W = window . innerWidth - 60 ,
221
+ let H = areaHeight ,
222
+ W = areaWidth ,
162
223
width = w,
163
224
height = h,
164
- marginLeft = 0 ;
225
+ marginLeft = 0 ,
226
+ marginTop = 0 ;
165
227
166
228
// caculate the image ratio
167
229
let R = width / height;
168
230
let Rs = W / H ;
169
231
if (R > Rs) {
170
- width = W ;
171
- height = W / R ;
172
- marginLeft = ( H - W / R ) / 2 ;
232
+ height = H ;
233
+ width = H * R ;
234
+ marginLeft = ( W - H * R ) / 2 ;
173
235
} else {
174
236
width = H * R ,
175
237
height = H ;
176
238
marginLeft = (W - H * R ) / 2 ;
177
239
}
178
- this .marginLeft = marginLeft;
179
- this .marginTop = 0 ;
180
- this .imgChangeRatio = width / w;
181
- this ._setStyle (width, height, R , true );
240
+ this ._setStyle (width, height, marginLeft, marginTop, R , true );
182
241
},
183
242
184
- _setStyle (w , h , r , isInit ) {
185
- const $container = this .$el ;
243
+ _setStyle (w , h , ml , mt , r , isInit ) {
244
+ const $container = this .$el . querySelector ( ' .g-crop-image-principal ' ) ;
186
245
if (! isInit) {
187
246
this .marginLeft = this .marginLeft + (this .width - w) / 2 ;
188
247
this .marginTop = this .marginTop + (this .height - h) / 2 ;
189
248
}
190
249
$container .style .cssText = ' width:' + w + ' px;height:' + h + ' px;margin-left:'
191
- + this .marginLeft + ' px;' + ' margin-top:' + this .marginTop + ' px' ;
192
- this .width = w;
193
- this .height = h;
250
+ + ml + ' px;' + ' margin-top:' + mt + ' px' ;
251
+ this .setCropBox (w, h);
252
+ if (this .isResize ) {
253
+ this .width = w;
254
+ this .height = h;
255
+ } else {
256
+ if (r >= 1 ) {
257
+ this .height = this .cropCSS .height ;
258
+ this .width = this .height * r;
259
+ } else {
260
+ this .width = this .cropCSS .width ;
261
+ this .height = this .width / r;
262
+ }
263
+ this .initWidth = this .width ;
264
+ this .initHeight = this .height ;
265
+ this .left = (w - this .width ) / 2 ;
266
+ this .top = (h - this .height ) / 2 ;
267
+ }
268
+ this .imgChangeRatio = this .width / this .natrualWidth ;
194
269
},
195
270
196
- setCropBox () {
197
- if (this .hideCrop ) {
271
+ setCropBox (w , h , r ) {
272
+ if (this .isResize ) {
198
273
return ;
199
274
}
200
275
let $selectCropBox = this .__find (' .crop-box' );
201
276
let $wrap = this .$el ;
202
- let imageWidth = this . width ,
203
- imageHeight = this . height ;
204
- let ratioW = this .ratioW ,
277
+ let imageWidth = w ,
278
+ imageHeight = h,
279
+ ratioW = this .ratioW ,
205
280
ratioH = this .ratioH ;
206
- const baseCropWidth = (imageWidth / 100 ) * CROPBOX_PERCENT ;
281
+ let cropWidth = imageWidth;
282
+ if (areaWidth < w) {
283
+ cropWidth = areaWidth;
284
+ }
285
+ const baseCropWidth = (cropWidth / 100 ) * CROPBOX_PERCENT ;
207
286
const CSSObj = {
208
287
width: baseCropWidth,
209
288
height: (baseCropWidth / ratioW) * ratioH,
@@ -220,11 +299,12 @@ export default {
220
299
$selectCropBox .style .cssText = helper .setCssText (CSSObj);
221
300
};
222
301
this .cropCSS = CSSObj;
302
+
223
303
},
224
304
225
305
getCropData () {
226
306
// keep compatible with old api
227
- if (this .hideCrop ) {
307
+ if (this .isResize ) {
228
308
return {
229
309
imgChangeRatio: this .imgChangeRatio ,
230
310
toCropImgX: 0 ,
@@ -234,8 +314,8 @@ export default {
234
314
};
235
315
}
236
316
return {
237
- toCropImgX: this .cropCSS .left / this .imgChangeRatio ,
238
- toCropImgY: this .cropCSS .top / this .imgChangeRatio ,
317
+ toCropImgX: ( this .cropCSS .left - this . left ) / this .imgChangeRatio ,
318
+ toCropImgY: ( this .cropCSS .top - this . top ) / this .imgChangeRatio ,
239
319
toCropImgW: this .cropCSS .width / this .imgChangeRatio ,
240
320
toCropImgH: this .cropCSS .height / this .imgChangeRatio ,
241
321
};
@@ -246,12 +326,15 @@ export default {
246
326
},
247
327
248
328
__find (str ) {
249
- let dq = document . querySelector ( ' #vciu-modal- ' + this .formId ) ;
329
+ let dq = this .$el ;
250
330
return dq .querySelector (str);
251
331
},
252
332
// resize and drag move
253
333
resize (e ) {
254
334
e .stopPropagation ();
335
+ if (! this .ratio .indexOf (' :' )) {
336
+ return ;
337
+ }
255
338
let $el = e .target .parentElement ;
256
339
let $container = this .__find (' .g-crop-image-principal' );
257
340
if (this ._$container ) {
@@ -261,8 +344,8 @@ export default {
261
344
const coor = {
262
345
x: helper .isMobile ? e .touches [0 ].clientX : e .clientX ,
263
346
y: helper .isMobile ? e .touches [0 ].clientY : e .clientY ,
264
- w: parseInt ( window . getComputedStyle ( $el). width , 10 ) ,
265
- h: parseInt ( window . getComputedStyle ( $el). height , 10 )
347
+ w: $el . offsetWidth ,
348
+ h: $el . offsetHeight ,
266
349
};
267
350
this .el = $el;
268
351
this .container = $container;
@@ -283,7 +366,6 @@ export default {
283
366
document .removeEventListener (' mousemove' , move, false );
284
367
document .removeEventListener (' mouseup' , end, false );
285
368
};
286
-
287
369
if (helper .isMobile ) {
288
370
document .addEventListener (' touchmove' , move, false );
289
371
document .addEventListener (' touchend' , end, false );
@@ -294,25 +376,25 @@ export default {
294
376
295
377
drag (e ) {
296
378
e .preventDefault ();
297
- const $el = e . target ;
379
+ const $el = this . __find ( ' .image-wrap ' ) ;
298
380
this .el = $el;
299
- const $container = this .$el ;
300
- const $infoAside = document . getElementsByClassName ( ' image-aside ' )[ 0 ] ;
381
+ const $cropBox = this .__find ( ' .crop-box ' ) ;
382
+ const $container = e . currentTarget ;
301
383
const self = this ;
302
384
const isMobile = helper .isMobile ;
303
385
const coor = {
304
- x: (isMobile ? e .touches [0 ][' clientX' ] : e .clientX ) - $el .offsetLeft - $el . parentElement . offsetLeft - $infoAside . offsetLeft ,
305
- y: (isMobile ? e .touches [0 ][' clientY' ] : e .clientY ) - $el .offsetTop - $el . parentElement . offsetTop - $infoAside . offsetTop ,
306
- posX : isMobile ? e . touches [ 0 ][ ' clientX ' ] : e . clientX ,
307
- posy : isMobile ? e . touches [ 0 ][ ' clientY ' ] : e . clientY ,
308
- maxLeft : parseInt ( $container . style . width ) - parseInt ( $el .style . width ) ,
309
- maxTop : parseInt ( $container . style . height ) - parseInt ( $el .style . height ) ,
386
+ x: (isMobile ? e .touches [0 ][' clientX' ] : e .clientX ) - $el .offsetLeft ,
387
+ y: (isMobile ? e .touches [0 ][' clientY' ] : e .clientY ) - $el .offsetTop ,
388
+ maxLeft : $cropBox . offsetLeft ,
389
+ maxTop : $cropBox . offsetTop ,
390
+ minLeft : ( $cropBox . offsetWidth + $cropBox . offsetLeft ) - $el .offsetWidth ,
391
+ minTop : ( $cropBox . offsetHeight + $cropBox . offsetTop ) - $el .offsetHeight ,
310
392
};
311
393
const move = function (ev ) {
312
394
const newCropStyle = drag (ev, self .el , coor);
313
395
if (newCropStyle) {
314
- self .cropCSS . left = newCropStyle .left ;
315
- self .cropCSS . top = newCropStyle .top ;
396
+ self .left = newCropStyle .left ;
397
+ self .top = newCropStyle .top ;
316
398
}
317
399
};
318
400
const stopMove = function (ev ) {
0 commit comments