File API文件操作之FileReader二
上一篇说了FileAPI中FileReader的readAsText,这里继续上文,说说另外一个API readAsDataURL。
这个接口是将File或者Blob读成base64格式的字符串,然后直接挂在HTML5的元素上,例如img就可以直接使用。
实际用途可以是图片预览和图片剪裁,这里我将用来实现图片剪裁。
思路:
1. file api的FileReader实现本地图片预览
2. 用web api的拖拽功能来实现剪裁
效果:
那么话不多说:
html代码:
<html><head><title>FileReader 之 readAsDataURL</title> </head><body style="margin: 2em 4em" draggable="false"><div>图片剪裁</div><input type="file" id="fileImageCut" value="选择图片"><br/><div draggable="false" id="imgWrapper" id="container1" style="display: inline-block;width: 500px"><div style="width: 404px;height: 404px;border:1px solid cornflowerblue;position: relative"><img draggable="false" style="position: absolute;left:-1px;bottom:-1px; border:1px solid greenyellow " id="imgPreview" /><div draggable="true" id="cutter" style="position: absolute;cursor:crosshair;left:-px;bottom:-2px; width:300px; height: 300px; border: 2px dotted sienna"></div></div></div><div style="display: inline-block;width: 200px;height:200px;vertical-align:buttom;border: 1px solid cadetblue;overflow: hidden;position:relative"><img draggable="false" style="width:266.7px;height:266.7px;position: absolute;left: 0;bottom: 0" id="imgResult"></div><!--<div draggable="true" id="cutter" style="position: absolute;cursor:crosshair;left:62px;top:274px; width:200px; height: 200px; border: 2px dotted sienna"></div> --> </body> <script src="./js/readAsDataURL.js"></script></html>
js代码:
const IMAGE_MAX_SIZE = 2 const CUTTER_WIDTH = CUTTER_HEIGHT = 300class SimpleImageCutter {constructor(options) {this.fileUpload = options.fileUploadthis.imgPreview = options.imgPreviewthis.imgResult = options.imgResultthis.cutter = options.cutterthis.percentage = this.imgResult.parentElement.clientWidth / this.cutter.clientWidththis.iLeft = this.iRight = this.iTop = this.iBottom = null}init() {this.resgiterEvents()}resgiterEvents() {let cLeft, cRight, cTop, cBottom, cOffsetX, cOffsetY,cutter = this.cutter, imgPreview = this.imgPreview, cBorderWidth = Number.parseInt(cutter.style.borderWidth.replace('px', '')),cPBorderWidth = Number.parseInt(imgPreview.style.borderWidth.replace('px', ''))this.fileUpload.addEventListener('change', (ev) => {let files = ev.target.files, file;//检查图片类型if (files.length && (file = files[0])) {if (!this.checkFile(file)) {return}//重置高宽imgPreview.removeAttribute('height')imgPreview.removeAttribute('width')imgPreview.style.width = imgPreview.style.height = nullimgPreview.style.visibility = 'hidden'let fr = new FileReader()fr.onload = () => {imgPreview.onload = () => {this.resizeImage()imgPreview.style.visibility = 'visible'this.resizeCutter()this.refreshPercentage()this.resizeResult()//计算图片相对浏览器的限值this.iLeft = imgPreview.getBoundingClientRect().left + document.documentElement.scrollLeft + cPBorderWidththis.iTop = imgPreview.getBoundingClientRect().top + document.documentElement.scrollTop + cPBorderWidththis.iRight = this.iLeft + imgPreview.clientWidththis.iBottom = this.iTop + imgPreview.clientHeight}this.imgResult.src = imgPreview.src = fr.result}//如果错误,抛出异常fr.onerror = ev => alert(ev.target.error) fr.readAsDataURL(file)}}, false)cutter.addEventListener('dragstart', ev => {cOffsetX = ev.offsetXcOffsetY = ev.offsetY/*let dragIcon = document.createElement("img") dragIcon.src = 'image/drag.jpg'dragIcon.width = cutter.width document.body.appendChild(dragIcon) ev.dataTransfer.setDragImage(dragIcon, 0, 0); *///cutter.style.border = "2px red solid" console.log('dragstart')return false}, false)cutter.addEventListener('dragover', ev => {//ev.stopPropagation()//ev.preventDefault()console.log('dragover')return false}, false)cutter.addEventListener('dragleave', ev => {//ev.stopPropagation()//ev.preventDefault()console.log('dragleave')return false}, false)cutter.addEventListener('drop', ev => {console.log('drop')}, false)cutter.addEventListener('dragend', ev => {cLeft = ev.clientX - cOffsetX - cBorderWidthcTop = ev.clientY - cOffsetY - cBorderWidthcRight = cLeft + cutter.clientWidth + cBorderWidthcBottom = cTop + cutter.clientHeight + cBorderWidthif (!this.iTop || cTop < this.iTop || cLeft < this.iLeft || cRight > this.iRight || cBottom > this.iBottom) {ev.stopPropagation()ev.preventDefault()} else {cutter.style.left = (cLeft - this.iLeft) + 'px'cutter.style.top = (cTop - this.iTop) + 'px'imgResult.style.left = -((cLeft - this.iLeft) * this.percentage).toFixed(2) + 'px'imgResult.style.top = -((cTop - this.iTop) * this.percentage).toFixed(2) + 'px'}}, false)}checkFile(file) {if (!file.type.startsWith("image")) {alert('不是有效的图片')return false}if (file.size > IMAGE_MAX_SIZE * 1024 * 1024) {alert(`上传的图片不允许大于${IMAGE_MAX_SIZE}M`)return false}return true}resizeImage() {let img = this.imgPreview, h = img.height, w = img.width,ph = img.parentElement.clientHeight, pw = img.parentElement.clientWidth,phc = h / ph, pwc = w / pwphc > pwc ? img.height = ph : img.width = pw}resizeCutter() {let minValue = Math.min(Math.min(imgPreview.clientHeight, CUTTER_HEIGHT), Math.min(imgPreview.clientWidth, CUTTER_WIDTH))cutter.style.height = cutter.style.width = minValue + 'px'cutter.style.top = cutter.style.left = null}resizeResult() {imgResult.style.width = (imgPreview.clientWidth * this.percentage).toFixed(2) + 'px'imgResult.style.height = (imgPreview.clientHeight * this.percentage).toFixed(2) + 'px'imgResult.style.top = imgResult.style.left = null}refreshPercentage() {this.percentage = this.imgResult.parentElement.clientWidth / this.cutter.clientWidth} }(new SimpleImageCutter({fileUpload: fileImageCut,imgPreview: imgPreview,imgResult: imgResult,cutter: cutter })).init()
这种简单实现存在的问题(下一种思路 html5 canvas):
1. 拖动效果体验比较差
2. 剪裁后的图片保存问题
源码路径:https://github.com/xiangwenhu/BlogCodes
File API文件操作之FileReader二相关推荐
- 基于html5 File API文件操作
文章来源:小青年原创 发布时间:2016-08-16 关键词:blob,File,FileReader,DataURI,URL 转载需标注本文原始地址: http://zhaomenghuan. ...
- C++的File类文件操作(转)
C++的File类文件操作 语言文件系统称为流文件(Stream),正文流(正文文件),二进制流(二进制文件) 缓冲与非缓冲文件 顺序操作文件与随机操作文件 顺序文件:读/写第K个数据块之前必须读/写 ...
- C语言使用FILE指针文件操作
C语言使用FILE指针文件操作 文件的基本概念 所谓"文件"是指一组相关数据的有序集合.这个数据集有一个名称,叫做文件名.实际上我们已经多次使用了文件,例如源程序文件.目标文件.可 ...
- C++的File类文件操作
C++的File类文件操作 语言文件系统称为流文件(Stream),正文流(正文文件),二进制流(二进制文件) 缓冲与非缓冲文件 顺序操作文件与随机操作文件 顺序文件:读/写第K个数据块之前必须读/写 ...
- python 入门第二课2 file的文件操作
务必注意读/写方式和指针位置 1.文件操作总结 模式'r'或者'r+'或者'rb+'指针初始位置在文件开头 模式'w'或者'w+'或者'wb+'指针初始位置在文件末尾 模式'a'或者'a+'或者'ab ...
- win32 api 文件操作!
CreateFile 打开文件 要对文件进行读写等操作,首先必须获得文件句柄,通过该函数可以获得文件句柄,该函数是通向文件世界的大门. ReadFile 从文件中读取字节信息. 在打开文件获得了文件句 ...
- php复制xml文件,PHP_php xml文件操作实现代码(二),复制代码 代码如下:?php //创 - phpStudy...
php xml文件操作实现代码(二) 复制代码 代码如下: //创建一个新的DOM文档 $dom = new DomDocument(); //在根节点创建departs标签 $departs = $ ...
- 【Android 文件管理】分区存储 ( MediaStore 文件操作 )
文章目录 一.动态权限申请 二.MediaStore 操作文件 三.完整代码示例 1.MainActivity 核心代码 2.build.gradle 构建脚本 3.清单文件 五.相关文档资料 特别注 ...
- 兼容input 文件选择_「HTML5」FileAPI 文件操作实战
本文来自<FileAPI 文件操作实战> 其他系列放在了Github,欢迎交流和Star 介绍 HTML5 为我们提供了 File API 相关规范.主要涉及 File 接口 和 File ...
- Linux内核文件操作
Linux内核文件操作 前言 一.文件操作结构体 二.VFS之file_operations对象 1.文件打开filp_open 2.文件关闭filp_close 3.文件读取vfs_read 4.文 ...
最新文章
- 突然想起99年的那次离别
- 【mathematical statistics】4 hypothesis testing
- php网站开发期末大作业,大学生期末网页大作业
- 深入解读:获Forrester大数据能力高评价的阿里云DataWorks思路与能力
- android 手机号码显示加空格,Android实现输入手机号时自动添加空格
- python怎么做图表_python 制作表格
- Python机器学习方向企业面试题(三)
- CCF201403-1 相反数(解法二)(100分)(废除!!!)
- android ResideMenu使用
- SPSS 有调节的中介与有中介的调节【SPSS 042期】
- Android微信页面缓存清理,安卓用户如何彻底清理微信大量缓存?4招让你彻底解决内存烦恼...
- ipa在线安装搭建_最新!超级签名系统源码以及搭建过程
- html 免备案,域名没有备案使用cdn(免备案cdn推荐)
- 冷数据、温数据、热数据,难道数据也是有温度的?
- 【计算机图形学】实验报告1用OpenGL画线命令绘制一个多边构成图形或场景
- 总结深度优先与广度优先的区别
- 成都市2021年高考三诊成绩查询,2020年成都各校高三“三诊”成绩一览表
- 用c#编写一个vb 工程源码分析工具(带源码工程下载)
- 卸载计算机应用程序的步骤,win7系统下卸载应用程序的步骤
- 防火墙工作原理(工作方式)
热门文章
- 动态规划:01背包问题、多段图问题
- 李宏毅机器学习笔记day3
- mul ab 的执行结果是_实战总结:为xxljob定制化的 php 执行器
- docker 内部ping不通宿主机_修改docker网段
- pre和code的区别
- 第一课:安卓开发工具Android Studio最新版本的安装
- 部分关键字--this/extends/super/static/final/abstract/访问权限总结
- Ubuntu上安装ns2-2.34
- 【转】程序员:如何写出杀手级简历
- struts2拦截器interceptor的三种配置方法