0
# Event Handling
1
2
Comprehensive event system for responding to image loading, cropping interactions, and real-time preview updates in VueCropper.
3
4
## Capabilities
5
6
### Image Loading Events
7
8
Events fired during image loading and processing phases.
9
10
```javascript { .api }
11
/**
12
* Image load completion event
13
* @param status - "success" for successful load, "error" for failures, or Error object
14
*/
15
@img-load: (status: 'success' | 'error' | Error) => void;
16
17
/**
18
* Detailed error information when image loading fails
19
* @param error - Error object with failure details
20
*/
21
@img-load-error: (error: Error) => void;
22
```
23
24
**Usage Examples:**
25
26
```vue
27
<template>
28
<VueCropper
29
:img="imageUrl"
30
@img-load="handleImageLoad"
31
@img-load-error="handleImageError"
32
/>
33
</template>
34
35
<script>
36
export default {
37
methods: {
38
handleImageLoad(status) {
39
if (status === 'success') {
40
console.log('Image loaded successfully');
41
this.imageReady = true;
42
} else if (status === 'error') {
43
console.error('Failed to load image');
44
this.showErrorMessage = true;
45
} else if (status instanceof Error) {
46
console.error('Image load error:', status.message);
47
}
48
},
49
50
handleImageError(error) {
51
console.error('Detailed error:', error);
52
this.errorDetails = error.message;
53
this.showRetryOption = true;
54
}
55
}
56
};
57
</script>
58
```
59
60
### Movement and Interaction Events
61
62
Events fired during user interactions with the image and crop box.
63
64
```javascript { .api }
65
/**
66
* Image movement/dragging events
67
* @param data - Movement data with position information
68
*/
69
@img-moving: (data: MovingData) => void;
70
71
/**
72
* Crop box movement/dragging events
73
* @param data - Movement data with crop box position
74
*/
75
@crop-moving: (data: MovingData) => void;
76
77
/**
78
* Crop box size change events (modern name)
79
* @param data - Size change data with dimensions
80
*/
81
@change-crop-size: (data: CropSizeData) => void;
82
83
/**
84
* Legacy camelCase events (for compatibility)
85
*/
86
@imgLoad: (status: 'success' | 'error' | Error) => void;
87
@imgMoving: (data: MovingData) => void;
88
@realTime: (data: PreviewData) => void;
89
@changeCropSize: (data: CropSizeData) => void;
90
@cropMoving: (data: MovingData) => void;
91
92
interface MovingData {
93
moving: boolean;
94
axis: {
95
x1: number; // top-left x coordinate
96
x2: number; // top-right x coordinate
97
y1: number; // top-left y coordinate
98
y2: number; // bottom-right y coordinate
99
};
100
}
101
102
interface CropSizeData {
103
width: number; // crop box width
104
height: number; // crop box height
105
}
106
```
107
108
**Usage Examples:**
109
110
```vue
111
<template>
112
<VueCropper
113
:img="imageUrl"
114
@img-moving="handleImageMove"
115
@crop-moving="handleCropMove"
116
@change-crop-size="handleCropSizeChange"
117
/>
118
119
<div class="status-panel">
120
<p>Image Moving: {{ imageMoving ? 'Yes' : 'No' }}</p>
121
<p>Crop Position: {{ cropPosition.x }}, {{ cropPosition.y }}</p>
122
<p>Crop Size: {{ cropSize.width }} × {{ cropSize.height }}</p>
123
</div>
124
</template>
125
126
<script>
127
export default {
128
data() {
129
return {
130
imageMoving: false,
131
cropPosition: { x: 0, y: 0 },
132
cropSize: { width: 0, height: 0 }
133
};
134
},
135
methods: {
136
handleImageMove(data) {
137
this.imageMoving = data.moving;
138
if (data.moving) {
139
console.log('Image being dragged to:', data.axis);
140
// Update UI to show drag state
141
this.showDragIndicator = true;
142
} else {
143
this.showDragIndicator = false;
144
}
145
},
146
147
handleCropMove(data) {
148
if (data.moving) {
149
this.cropPosition = {
150
x: data.axis.x1,
151
y: data.axis.y1
152
};
153
// Sync with external preview or coordinates display
154
this.updateExternalPreview(data.axis);
155
}
156
},
157
158
handleCropSizeChange(data) {
159
this.cropSize = {
160
width: data.width,
161
height: data.height
162
};
163
// Validate minimum/maximum sizes
164
if (data.width < 50 || data.height < 50) {
165
this.showSizeWarning = true;
166
}
167
}
168
}
169
};
170
</script>
171
```
172
173
### Real-time Preview Events
174
175
Core event for implementing live preview functionality.
176
177
```javascript { .api }
178
/**
179
* Real-time preview updates during cropping operations
180
* @param data - Complete preview data for rendering external previews
181
*/
182
@real-time: (data: PreviewData) => void;
183
184
interface PreviewData {
185
url: string; // preview image URL/base64
186
img: string; // CSS transform styles for image element
187
div: string; // CSS transform styles for container element
188
w: number; // preview width in pixels
189
h: number; // preview height in pixels
190
}
191
```
192
193
**Usage Examples:**
194
195
```vue
196
<template>
197
<div class="cropper-layout">
198
<div class="main-cropper">
199
<VueCropper
200
:img="imageUrl"
201
@real-time="handleRealTimePreview"
202
/>
203
</div>
204
205
<div class="preview-panels">
206
<!-- Large Preview -->
207
<div class="preview-large">
208
<h3>Large Preview</h3>
209
<div
210
class="preview-container"
211
:style="{ width: previews.w + 'px', height: previews.h + 'px' }"
212
>
213
<div :style="previews.div">
214
<img :src="previews.url" :style="previews.img">
215
</div>
216
</div>
217
</div>
218
219
<!-- Small Preview -->
220
<div class="preview-small">
221
<h3>Small Preview (50%)</h3>
222
<div
223
class="preview-container"
224
:style="{
225
width: (previews.w * 0.5) + 'px',
226
height: (previews.h * 0.5) + 'px',
227
overflow: 'hidden'
228
}"
229
>
230
<div :style="{
231
...parseCSSTransform(previews.div),
232
zoom: 0.5
233
}">
234
<img :src="previews.url" :style="previews.img">
235
</div>
236
</div>
237
</div>
238
239
<!-- Fixed Size Preview -->
240
<div class="preview-fixed">
241
<h3>Avatar Preview (100x100)</h3>
242
<div
243
class="preview-container avatar-preview"
244
:style="{
245
width: '100px',
246
height: '100px',
247
overflow: 'hidden',
248
borderRadius: '50%'
249
}"
250
>
251
<div :style="{
252
...parseCSSTransform(previews.div),
253
zoom: 100 / previews.w
254
}">
255
<img :src="previews.url" :style="previews.img">
256
</div>
257
</div>
258
</div>
259
</div>
260
</div>
261
</template>
262
263
<script>
264
export default {
265
data() {
266
return {
267
imageUrl: '/path/to/image.jpg',
268
previews: {
269
url: '',
270
img: '',
271
div: '',
272
w: 0,
273
h: 0
274
}
275
};
276
},
277
methods: {
278
handleRealTimePreview(data) {
279
this.previews = data;
280
281
// Optional: emit to parent component
282
this.$emit('preview-updated', data);
283
284
// Optional: store for later use
285
this.lastPreviewData = data;
286
},
287
288
parseCSSTransform(cssString) {
289
// Helper to parse CSS transform string into object
290
// Implementation depends on your specific needs
291
return {
292
transform: cssString
293
};
294
}
295
}
296
};
297
</script>
298
299
<style scoped>
300
.cropper-layout {
301
display: flex;
302
gap: 20px;
303
}
304
305
.main-cropper {
306
flex: 1;
307
height: 400px;
308
}
309
310
.preview-panels {
311
width: 300px;
312
display: flex;
313
flex-direction: column;
314
gap: 15px;
315
}
316
317
.preview-container {
318
border: 1px solid #ddd;
319
margin: 5px;
320
position: relative;
321
}
322
323
.avatar-preview {
324
border: 2px solid #007bff;
325
}
326
</style>
327
```