自定义input上传图片组件
自定义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上传图片组件的更多相关文章
- Vue组件之自定义表单组件
今天又看了一遍vue的文档,记得之前学习的时候,官方文档中有提过,v-model指令是一个语法糖,做两件事,一个是给表单控件元素绑定value,第二个是当输入时更新绑定的值,不过后来在"表单 ...
- 自定义Vue&Element组件,实现用户选择和显示
在我们很多前端业务开发中,往往为了方便,都需要自定义一些用户组件,一个是减少单一页面的代码,提高维护效率:二个也是方便重用.本篇随笔介绍在任务管理操作中,使用自定义Vue&Element组件, ...
- svelte组件:Svelte3自定义Navbar+Tabbr组件|svelte自定义插件
基于Svelte3自定义组件Navbar+Tabbar沉浸式导航条|底部凸起菜单栏 Svelte 一种全新的构建用户界面的框架.当下热门的 Vue 和 React 在浏览器中需要做大量的工作,而 Sv ...
- iOS开发之自定义表情键盘(组件封装与自动布局)
下面的东西是编写自定义的表情键盘,话不多说,开门见山吧!下面主要用到的知识有MVC, iOS开发中的自动布局,自定义组件的封装与使用,Block回调,CoreData的使用.有的小伙伴可能会问写一个自 ...
- BizTalk动手实验(十一)自定义开发管道组件
1 课程简介 通过本课程熟悉自定义开始管道组件的流程.各组件接口的功能作用以及自定义管道. 本场景为开发一个消息ZIP压缩的发送管道组件. 2 准备工作 1. 熟悉管道组件各阶段组成 2. 下载Ion ...
- 自定义input file样式
自定义input file样式:一般都是通过隐藏input,通过定义label来实现.这种做法要注意的是label的for属性要指定input对应的id; <!DOCTYPE html> ...
- React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发
React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发 2016/09/23 | React Native技术文章 | Sky丶清| 4 条评论 | 1 ...
- 自定义vue全局组件use使用、vuex的使用
自定义vue全局组件use使用(解释vue.use()的原理)我们在前面学习到是用别人的组件:Vue.use(VueRouter).Vue.use(Mint)等等.其实使用的这些都是全剧组件,这里我们 ...
- 百度小程序自定义通用toast组件
百度小程序Toast组件 author: @TiffanysBear 百度小程序自定义通用toast组件 BdToast百度小程序自定义通用组件-github地址 需求 手百小程序的toast仅支持在 ...
随机推荐
- Typora---markdown
一级标题 空格 编写内容 有序内容 +Tab 无序内容 -+Tab 代码块 print('hello world!') typora快捷键 标题1==ctrl +1 图片 表格 Ctrl + T 姓名 ...
- css实现两个div并排等高(一个div高度随另一个高度变化而变化)
方法一.两个div都设置 display: table-cell; 方法二.父级div设置 display: -webkit-box;
- MyCAT与MySQL导入、导出文件
1. MySQL批量导入-LOAD DATA使用本地客户端连接MySQL数据库,批量导入数据,出现报错:2017-06-07 09:30:45,936 MySqlWrapper::ImportCSVt ...
- Haproxy学习总结
一.Haproxy介绍 1.实现了一种事件驱动,单一进程模型,支持数万计的并发连接,用于为tcp和http应用程序提供高可用,负载均衡和代理服务的解决方案,尤其适用于高负载且需要持久连接或7层处理机制 ...
- 常用插件html
1.上传模板,插件 https://github.com/kartik-v/bootstrap-fileinput 2.
- 学习-Pytest(三)setup/teardown
1. 用例运行级别 模块级(setup_module/teardown_module)开始于模块始末,全局的 函数级(setup_function/teardown_function)只对函数用例生效 ...
- Linux Shell交互式自动化运维程序
Expect是Linux操作系统下的一个用来处理交互操作,系统默认是没有安装expect库,所以执行expect会提示找不到命令,需要手动安装,其它安装也比较简单,可以通过二进制源码包编译配置进行安装 ...
- Linux使用fsck修复文件系统
1.fsck---file system check fsck 扫描文件系统时一定要在单用户模式.修复模式或把设备umount后进行.如果扫描运行中的系统,会造成系统文件损坏. RHEL6中fsc ...
- 【HDU3308】LCIS
题目大意:维护一个长度为 N 的序列,支持单点修改,区间查询最长连续上升子序列的长度. 题解: 线段树维护一段区间左端点开始的 LCIS 长度,右端点开始的 LCIS 长度以及区间最优解.考虑进行合并 ...
- python修炼之路---面向对象
面向对象编程 面向对象编程:使用类和对象实现一类功能. 类与对象 类:类就是一个模板,模板里可以包含多个函数,函数里实现一些功能. 对象:是根据模板创建的实例,通过实例对象可以执行类中的函数. 面向对 ...