自定义input上传图片组件,美化样式
前段时间因为项目需求,做过一个上传图片组件,这里分享下大致思路,希望对有需要的童鞋有所帮助~~~
功能需求:1.上传图片限制大小、分辨率、类型 2.上传图片支持自由裁剪 3.图片上传后支持预览和删除
效果图,只截取了一小部分,大致看下就ok啦,是不是感觉比原生的好看多了^_^
项目是基于react
框架写的,话不多说,开始撸代码~~~
Step1:编写基础html结构
// uploadButton组件代码如下: const uploadButton = (); 上传照片
Step2:基础样式
input-file { width: 0.1px; height: 0.1px; opacity: 0; overflow: hidden; position: absolute; z-index: -1;}.ant-upload { @w: 100px; width: @w; height: @w; padding: 5px; background-color: #fafafa; border: 1px dashed #d9d9d9; border-radius: 4px; display: block; cursor: pointer; position: relative;}.upload-plus-text { width: 100%; text-align: center; position: absolute; left: 0; top: 50%; transform: translateY(-50%); i { font-size: 28px; color: #999; } .ant-upload-text { margin-top: 8px; font-size: 12px; color: #666; }}
Step3:添加事件处理
对上传图片的类型、大小和分辨率进行检测
{ this.onFileChange(e); }}/>// 一些常量定义const IMAGE_MIN_WIDTH = 1280; // 上传图片最小宽const IMAGE_MIN_HEIGHT = 800; // 上传图片最小高const IMAGE_MAX_SIZE = 1024 * 1024; // 上传图片最大大小// 处理上传文件 onFileChange(e) { const file = e.target.files[0]; e.target.value = ''; // 再次上传同一文件进行裁剪 if (this.handleBeforeUpload(file)) { const reader = new FileReader(); reader.onload = e => { const src = e.target.result; const image = new Image(); const _this = this; image.onload = () => { const width = image.width; const height = image.height; if (width >= IMAGE_MIN_WIDTH && height >= IMAGE_MIN_HEIGHT) { _this.setState({ initialImageUrl: src, showCropModal: true }); } else { message.error('照片分辨率小于1280*800'); } }; image.src = src; }; reader.readAsDataURL(file); } }// 检查照片格式、大小等信息 handleBeforeUpload(file) { if (file) { const sizeOk = file.size < IMAGE_MAX_SIZE; const typeReg = new RegExp(/^image\/bmp|gif|jpg|jpeg|png$/, 'i'); const typeOk = typeReg.test(file.type); if (!typeOk) { message.error('照片格式有误'); } else if (!sizeOk) { message.error('照片大小超过1M'); } return sizeOk && typeOk; } }
Step4:裁剪功能
代码较多就不展示了= =,使用的是
Step5:预览和删除功能
预览功能实现思路就是通过判断是否已经上传图片来展示不同的状态。未上传展示uploadButton组件,已上传就展示imagePreview组件。
通过判断是否已经上传图片来控制input标签的id属性值,未上传图id='file',已上传图片将id='',这样一来,再次去点击label的时候由于for属性找不到对应的id,就不会触发input上onChange事件{ this.onFileChange(e); }} />// imagePreview组件代码如下const imagePreview = ( ); // 预览图片handlePreview() { this.setState({ showPreviewModal: true });}// 删除图片swapImageFile() { this.setState({ imageUrl: '' });}
写在最后:项目涉及代码较多,文章只展示了大部分代码,一些具体细节代码可能就没有展示了,还望见谅,第一次写文章,可能比较混乱,有问题还望大家指出~~~ ^_^