自定义input上传图片组件,美化样式

前段时间因为项目需求,做过一个上传图片组件,这里分享下大致思路,希望对有需要的童鞋有所帮助~~~


功能需求:1.上传图片限制大小、分辨率、类型
2.上传图片支持自由裁剪
3.图片上传后支持预览和删除

效果图,只截取了一小部分,大致看下就ok啦,是不是感觉比原生的好看多了^_^

项目是基于react框架写的,话不多说,开始撸代码~~~

Step1:编写基础html结构

<div>
<input
type="file"
accept="image/jpeg, image/gif, image/png, image/bmp"
styleName="input-file"
/>
<label htmlFor="file" styleName="ant-upload">
{uploadButton}
</label>
</div> // uploadButton组件代码如下:
const uploadButton = (
<div styleName="upload-plus-text">
<Icon type="plus" />
<div className="ant-upload-text">上传照片</div>
</div>
);

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:添加事件处理

对上传图片的类型、大小和分辨率进行检测

<input
type="file"
id='file'
accept="image/jpeg, image/gif, image/png, image/bmp"
styleName="input-file"
onChange={e => {
this.onFileChange(e);
}}
/>
<label htmlFor="file" styleName="ant-upload">
{uploadButton}
</label>
</div> // 一些常量定义
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:裁剪功能

代码较多就不展示了= =,使用的是react-cropper

Step5:预览和删除功能

预览功能实现思路就是通过判断是否已经上传图片来展示不同的状态。未上传展示uploadButton组件,已上传就展示imagePreview组件。
通过判断是否已经上传图片来控制input标签的id属性值,未上传图id='file',已上传图片将id='',这样一来,再次去点击label的时候由于for属性找不到对应的id,就不会触发input上onChange事件

<div>
<input
type="file"
id={imageUrl ? '' : 'file'}
accept="image/jpeg, image/gif, image/png, image/bmp"
styleName="input-file"
onChange={e => {
this.onFileChange(e);
}}
/>
<label htmlFor="file" styleName="ant-upload">
{imageUrl ? imagePreview : uploadButton}
</label>
</div>
<Modal
visible={showPreviewModal}
title="图片预览"
footer={null}
width={700}
onCancel={this.handlePreviewCancel}>
<img alt="" style={{ width: '100%' }} src={imageUrl} />
</Modal>
// imagePreview组件代码如下
const imagePreview = (
<div
styleName="image-background-preview"
style={{ backgroundImage: `url(${imageUrl})` }}>
<div styleName="preview-image">
<span styleName="preview-image-btn">
<a title="预览图片" href="javascript:;">
<Icon
type="eye"
styleName="icon-btn"
onClick={this.handlePreview}
/>
</a>
<a title="删除图片" href="javascript:;">
<Icon
type="delete"
styleName="icon-btn"
onClick={this.swapImageFile}
/>
</a>
</span>
</div>
</div>
); // 预览图片
handlePreview() {
this.setState({
showPreviewModal: true
});
} // 删除图片
swapImageFile() {
this.setState({ imageUrl: '' });
}

写在最后:项目涉及代码较多,文章只展示了大部分代码,一些具体细节代码可能就没有展示了,还望见谅,第一次写文章,可能比较混乱,有问题还望大家指出~~~ ^_^

自定义input上传图片组件的更多相关文章

  1. Vue组件之自定义表单组件

    今天又看了一遍vue的文档,记得之前学习的时候,官方文档中有提过,v-model指令是一个语法糖,做两件事,一个是给表单控件元素绑定value,第二个是当输入时更新绑定的值,不过后来在"表单 ...

  2. 自定义Vue&Element组件,实现用户选择和显示

    在我们很多前端业务开发中,往往为了方便,都需要自定义一些用户组件,一个是减少单一页面的代码,提高维护效率:二个也是方便重用.本篇随笔介绍在任务管理操作中,使用自定义Vue&Element组件, ...

  3. svelte组件:Svelte3自定义Navbar+Tabbr组件|svelte自定义插件

    基于Svelte3自定义组件Navbar+Tabbar沉浸式导航条|底部凸起菜单栏 Svelte 一种全新的构建用户界面的框架.当下热门的 Vue 和 React 在浏览器中需要做大量的工作,而 Sv ...

  4. iOS开发之自定义表情键盘(组件封装与自动布局)

    下面的东西是编写自定义的表情键盘,话不多说,开门见山吧!下面主要用到的知识有MVC, iOS开发中的自动布局,自定义组件的封装与使用,Block回调,CoreData的使用.有的小伙伴可能会问写一个自 ...

  5. BizTalk动手实验(十一)自定义开发管道组件

    1 课程简介 通过本课程熟悉自定义开始管道组件的流程.各组件接口的功能作用以及自定义管道. 本场景为开发一个消息ZIP压缩的发送管道组件. 2 准备工作 1. 熟悉管道组件各阶段组成 2. 下载Ion ...

  6. 自定义input file样式

    自定义input file样式:一般都是通过隐藏input,通过定义label来实现.这种做法要注意的是label的for属性要指定input对应的id; <!DOCTYPE html> ...

  7. React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发

    React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发   2016/09/23 |  React Native技术文章 |  Sky丶清|  4 条评论 |  1 ...

  8. 自定义vue全局组件use使用、vuex的使用

    自定义vue全局组件use使用(解释vue.use()的原理)我们在前面学习到是用别人的组件:Vue.use(VueRouter).Vue.use(Mint)等等.其实使用的这些都是全剧组件,这里我们 ...

  9. 百度小程序自定义通用toast组件

    百度小程序Toast组件 author: @TiffanysBear 百度小程序自定义通用toast组件 BdToast百度小程序自定义通用组件-github地址 需求 手百小程序的toast仅支持在 ...

随机推荐

  1. redis 列表 数据类型

    列表 rpush dname  技术部  后勤部 售后部 lpush  dname   秘书部 lset dname 2  销售部     修改 lrange dname 0 -1   打印所有列表 ...

  2. Python 入门之 内置模块 -- random模块

    Python 入门之 内置模块 -- random模块 1.random模块 import random # random -- 随机数 (1)选择1-50之间随机的整数 print(random.r ...

  3. 解决IOS把数字渲染为电话号码,颜色为蓝色解决方案

    可将telephone=no,则手机号码不被显示为拨号链接<meta name="format-detection" content="telephone=no&q ...

  4. 实现 RSA 算法之改进和优化(第三章)(老物)

    第三章 如何改进和优化RSA算法 这章呢,我想谈谈在实际应用出现的问题和理解. 由于近期要开始各种忙了,所以写完这章后我短时间内也不打算出什么资料了=- =(反正平时就没有出资料的习惯.) 在讲第一章 ...

  5. python 实现屏幕录制

    用python实现屏幕录制 PIL 即pollow 的安装命令如下: pip install pillow 其中cv2的安装是下面这条命令 pip install opencv-python 代码实现 ...

  6. Scala Nothing 从官方DOC翻译

    Nothing is - together with scala.Null - at the bottom of Scala's type hierarchy. Scala中的Nothing和Null ...

  7. jquery-mobile pop

    一.弹框 代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...

  8. adb shell命令模拟按键/输入input使用keycode 列表详解

    在adb shell里有一个非常使用的命令,模拟按键输入,这里首先不要理解为是键盘的模拟按键,下面命令的使用和键值做一个详解. input命令格式 adb shell input keyevent & ...

  9. spring中spEL常用应用场景

    spEL表达式表示:#{} 一.基本类型值运算操作 {}可以放置数字,字符串,布尔型,表达式(运算,正则,逻辑).这个应用场景和EL表达式一样的,实际中用的也不多. 注意:在XML中表示==,> ...

  10. ArrayList与LinkedList的区别

    两者区别大致分为以下几点: 1.ArrayList采用的是采用的是数组形式保存数据,这种方式将对象放在连续的位置中(线性存储):LinkedList采用的将对象放在独立的空间中,每个空间还保留下一个节 ...