1
vue封装原生的可预览裁剪上传图片插件H5,PC端都可以使用 - ZihangChu
source link: https://www.cnblogs.com/SadicZhou/p/16460609.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
vue封装原生的可预览裁剪上传图片插件H5,PC端都可以使用 - ZihangChu - 博客园
cut(index) { this.selIndex = index; this.pre = `< img src="${this.fileList[index]}" alt="" class='cutImg' />`; this.cutProp = true; console.log(this.$refs); this.$nextTick(function () { console.log(this.$refs.preimg.firstChild); //使用nextTick,dom更新完成后才能获取到子节点 this.myCropper = new Cropper(this.$refs.preimg.firstChild, { aspectRatio: 1 / 1, dragMode: "move", outputType: "png", //防止图片背景变黑 crop(event) { console.log(event.detail.x); console.log(event.detail.y); console.log(event.detail.width); console.log(event.detail.height); console.log(event.detail.rotate); console.log(event.detail.scaleX); console.log(event.detail.scaleY); }, }); }); }, qdcut() { let cropBox = this.myCropper.getCropBoxData(); console.log(this.myCropper.getCropBoxData()); //打印裁剪数据 let cropCanvas = this.myCropper.getCroppedCanvas({ width: cropBox.width, height: cropBox.height, }); //使用画布画出裁剪后的图片 let imgData = cropCanvas.toDataURL(); //导出裁剪后图片的数据 console.log(imgData); this.fileList.splice(this.selIndex, 1, imgData); console.log(this.fileList); this.cutProp = false; }, //确定裁剪 cancel() { this.cutProp = false; }, //取消裁剪 |
因为本次封装的是预览时裁剪的功能,所以裁剪的是点击预览列表中的文件触发的,cut方法将选择的图片的index存储selIndex变量中,然后通过v-html指令在剪裁弹窗中加载出对应的图片来进行裁剪,裁剪使用cropper.js来进行的,注意使用时要在this.$nextTick方法的回调中来进行剪裁函数的初始化,这样才能获取到通过v-html指令插入的图片。
选择合适的裁剪尺寸后点击确认才加调用qdcut方法,通过cropper.js的内置方法getCropBoxData()获取剪裁的数据,通过getCroppedCanvas()传入对应的数据然后导出剪裁后的图片,将fileList中对应的元素替换即可完成
6.下面附上整个代码,可以直接拿去使用:
1 <template> 2 <div> 3 <!-- 裁剪蒙层 --> 4 <div 5 class="prop center" 6 v-if="cutProp" 7 :style="{ 8 height: this.windowHeight + 'px', 9 width: this.windowWidth + 'px', 10 }" 11 > 12 <div v-html="pre" ref="preimg" class="imgContent"></div> 13 <div class="cutHandler"> 14 <button class="btn green" @click="cancel()">取消</button> 15 <button class="btn blue" @click="qdcut()">剪裁</button> 16 </div> 17 </div> 18 <!-- 删除弹窗 --> 19 <div 20 class="prop" 21 :style="{ 22 height: this.windowHeight + 'px', 23 width: this.windowWidth + 'px', 24 }" 25 v-if="show" 26 > 27 <div class="text"> 28 <img 29 src="../assets/remove.png" 30 alt="" 31 class="close" 32 @click="removePropClose()" 33 /> 34 <div>要删除这张照片吗</div> 35 <div class="action"> 36 <button class="btn green" @click="removePropClose()">取消</button> 37 <button class="btn blue" @click="remove()">确定</button> 38 </div> 39 </div> 40 </div> 41 <!-- 上传区域 --> 42 <div class="upContent"> 43 <!-- 预览区域 --> 44 <div 45 class="preView" 46 v-for="(i, index) in fileList" 47 :key="index" 48 ref="preList" 49 > 50 <div class="fileList" v-if="upLodaOk"> 51 <img 52 src="../assets/remove.png" 53 alt="" 54 class="remove" 55 @click="removeProp(index)" 56 /> 57 <img 58 :src="fileList[index]" 59 alt="" 60 class="img" 61 @click="cut(index)" 62 ref="imgitem" 63 /> 64 </div> 65 </div> 66 <!-- 上传区 --> 67 <label for="fileUp"> 68 <div class="upBorder"> 69 <img src="../assets/add.png" alt="" /> 70 <input 71 ref="fileUp" 72 type="file" 73 id="fileUp" 74 accept="image" 75 style="display: none" 76 @change="upload()" 77 /> 78 </div> 79 </label> 80 </div> 81 </div> 82 </template> 83 <script> 84 import Cropper from "cropperjs"; 85 import "cropperjs/dist/cropper.css"; 86 export default { 87 name: "upload", 88 data() { 89 return { 90 cutProp: false, 91 pre: "", //准备剪裁的图片 92 selIndex: "", //选择照片的索引 93 removeIndex: "", //准备删除的照片的索引 94 show: false, //删除弹出层 95 myCropper: null, 96 afterImg: "", 97 ingData: null, 98 upLodaOk: false, //是否展示预览列表 99 fileList: [], //已经上传图片的列表 100 }; 101 }, 102 methods: { 103 upload() { 104 let that = this; 105 console.log(this.$refs.fileUp.files); 106 if (this.$refs.fileUp.files.length != 0) { 107 const reader = new FileReader(); 108 reader.readAsDataURL(this.$refs.fileUp.files[0]); 109 reader.onload = function () { 110 const img = new Image(); 111 img.src = reader.result; 112 that.fileList.push(reader.result); 113 that.$refs.fileUp.value = null; //上传后重置上传input的value,这样才能同时上传相同的图片 114 console.log(reader.result); 115 }; 116 this.upLodaOk = true; 117 } 118 }, 119 removeProp(index) { 120 //v-for循环中的ref是个数组,根据index来取每一个对应的dom元素 121 this.removeIndex = index; 122 this.show = true; 123 }, 124 removePropClose() { 125 this.show = false; 126 }, 127 remove() { 128 this.fileList.splice(this.removeIndex, 1); 129 this.$refs.fileUp.value = null; //删除后重置上传input的value,这样才能同时上传相同的图片 130 console.log(this.$refs.fileUp.value); 131 this.show = false; 132 }, 133 cut(index) { 134 this.selIndex = index; 135 this.pre = `<img 136 src="${this.fileList[index]}" 137 alt="" 138 class='cutImg' 139 />`; 140 this.cutProp = true; 141 console.log(this.$refs); 142 this.$nextTick(function () { 143 console.log(this.$refs.preimg.firstChild); //使用nextTick,dom更新完成后才能获取到子节点 144 this.myCropper = new Cropper(this.$refs.preimg.firstChild, { 145 aspectRatio: 1 / 1, 146 dragMode: "move", 147 outputType: "png", //防止图片背景变黑 148 crop(event) { 149 console.log(event.detail.x); 150 console.log(event.detail.y); 151 console.log(event.detail.width); 152 console.log(event.detail.height); 153 console.log(event.detail.rotate); 154 console.log(event.detail.scaleX); 155 console.log(event.detail.scaleY); 156 }, 157 }); 158 }); 159 }, 160 qdcut() { 161 let cropBox = this.myCropper.getCropBoxData(); 162 console.log(this.myCropper.getCropBoxData()); //打印裁剪数据 163 let cropCanvas = this.myCropper.getCroppedCanvas({ 164 width: cropBox.width, 165 height: cropBox.height, 166 }); //使用画布画出裁剪后的图片 167 let imgData = cropCanvas.toDataURL(); //导出裁剪后图片的数据 168 console.log(imgData); 169 this.fileList.splice(this.selIndex, 1, imgData); 170 console.log(this.fileList); 171 this.cutProp = false; 172 }, //确定裁剪 173 cancel() { 174 this.cutProp = false; 175 }, //取消裁剪 176 }, 177 mounted() {}, 178 computed: { 179 windowWidth() { 180 return document.documentElement.clientWidth; 181 }, 182 windowHeight() { 183 return document.documentElement.clientHeight; 184 }, 185 }, //监听屏幕的宽度和高度 186 }; 187 </script> 188 <style> 189 .upBorder { 190 width: 8rem; 191 height: 8rem; 192 border: 1px silver dashed; 193 display: flex; 194 justify-content: center; 195 align-items: center; 196 } 197 .upContent { 198 display: flex; 199 justify-content: center; 200 align-items: center; 201 } 202 .img { 203 width: 8rem; 204 height: 8rem; 205 } 206 207 .fileList { 208 position: relative; 209 display: flex; 210 flex-direction: column; 211 justify-content: center; 212 align-items: center; 213 } 214 .remove { 215 position: absolute; 216 width: 1rem; 217 height: 1rem; 218 top: 0rem; 219 right: 0rem; 220 cursor: pointer; 221 } 222 .prop { 223 vertical-align: middle; 224 position: fixed; 225 top: 0; 226 left: 0; 227 z-index: 999; 228 background-color: rgba(0, 0, 0, 0.7); 229 } 230 .text { 231 border-radius: 0.2rem; 232 top: 50%; 233 left: 50%; 234 -webkit-transform: translate3d(-50%, -50%, 0); 235 transform: translate3d(-50%, -50%, 0); 236 position: fixed; 237 z-index: 1000; 238 color: black; 239 text-align: center; 240 background-color: #fff; 241 padding: 2rem 4rem; 242 white-space: nowrap; 243 } 244 .close { 245 position: absolute; 246 top: 0.3rem; 247 right: 0.3rem; 248 width: 1rem; 249 height: 1rem; 250 } 251 .action { 252 display: flex; 253 justify-content: space-between; 254 align-items: center; 255 margin-top: 1rem; 256 } 257 .btn { 258 font-size: 0.12rem; 259 color: #fff; 260 padding: 0.2rem 0.8rem; 261 } 262 .blue { 263 background-color: #1989fa; 264 border: 1px solid #1989fa; 265 } 266 .green { 267 background-color: #07c160; 268 border: 1px solid #07c160; 269 } 270 .cropper-point.point-se { 271 width: 5px; 272 height: 5px; 273 } 274 .cropper { 275 position: fixed; 276 top: 0; 277 z-index: 999; 278 } 279 280 /* .cropper-container{ 281 top: 50%; 282 left: 50%; 283 -webkit-transform: translate3d(-50%, -50%, 0); 284 transform: translate3d(-50%, -50%, 0); 285 } */ 286 .imgContent { 287 width: 16rem; 288 height: 16rem; 289 display: inline-block; 290 /* top: 50%; 291 left: 50%; 292 -webkit-transform: translate3d(-50%, -50%, 0); 293 transform: translate3d(-50%, -50%, 0); */ 294 } 295 .cutImg { 296 display: block; 297 max-width: 100%; 298 } 299 .center { 300 display: flex; 301 flex-direction: column; 302 justify-content: center; 303 align-items: center; 304 } 305 .cropper-bg { 306 background: none; 307 } 308 .cutHandler { 309 margin-top: 2rem; 310 width: 16rem; 311 text-align: center; 312 display: flex; 313 justify-content: space-between; 314 align-items: center; 315 } 316 .cropper-modal { 317 background: rgba(0, 0, 0, 0); 318 } 319 </style>
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK