自定义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. mysql(中)

    mysql(中) 一.数据库配置 1.登录mysql 2.在mysql安装目录下:创建my.ini(my.cnf) 3.设置配置信息并保存 ''' [mysqld] character-set-ser ...

  2. oracle三种表连接方式

    1. 排序合并连接(Sort Merge Join) 排序合并连接的执行过程如下所示: * 将每个行源的行按连接谓词列排序 * 然后合并两个已排序的行源,并返回生成的行源 例如: select * f ...

  3. java中常见的异常种类

    Java常见的异常种类 ------------------------------------------------------------------------------- java Exc ...

  4. js,el表达式,<c:if>

    <c:if>中只能有一个判断语句,但是可以在一个el表达式中写多个判断条件 例: <c:if test="${fn:length(item.work_detail.note ...

  5. JS 的 Document对象

    Document 对象是是window对象的一个属性,因此可以将document对象作为一个全局对象来访问. 当浏览器载入 HTML 文档, 它就会成为 Document 对象. Document对象 ...

  6. 【总结】Android 应用测试总结

    前提 所有的功能分支已完成 启动: 1. 启动入口:桌面正常启动,最近运行启动,所有程序列表中启动,锁屏快捷启动2. 其他入口:从其他程序开启应用,从外部以文件形式打开应用(如果有)3. 退回:从其他 ...

  7. [转载]Ethernet,Half-Duplex/Full-Duplex,CSMA

    原文地址:Ethernet,Half-Duplex/Full-Duplex,CSMA/CD,Auto-Negotiation作者:心田麦浪 CSMA/CD(Carrier Sense Multiple ...

  8. 安装Python包报错——ReadTimeoutError

    一.问题:安装python包的时候报错ReadTimeoutError——Read time out. 二.解决办法三种方法,一是切换下载源:二是下载相应平台的安装包后安装:三是下载源码编译安装:  ...

  9. owncloud 安装

    假定lamp已安装完成. 1 安装owncloud 使用curl命令下载其发行版密钥(key),并使用add命令将其与apt-key实用程序一起导入: curl https://download.ow ...

  10. java基本类型和包装类型的区别

    Java的类型分为两部分,一个是基本类型(primitive),如int.double等八种基本数据类型: 另一个是引用类型(reference type),如String.List等.而每一个基本类 ...