上一篇说了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二相关推荐

  1. 基于html5 File API文件操作

    文章来源:小青年原创  发布时间:2016-08-16  关键词:blob,File,FileReader,DataURI,URL  转载需标注本文原始地址: http://zhaomenghuan. ...

  2. C++的File类文件操作(转)

    C++的File类文件操作 语言文件系统称为流文件(Stream),正文流(正文文件),二进制流(二进制文件) 缓冲与非缓冲文件 顺序操作文件与随机操作文件 顺序文件:读/写第K个数据块之前必须读/写 ...

  3. C语言使用FILE指针文件操作

    C语言使用FILE指针文件操作 文件的基本概念 所谓"文件"是指一组相关数据的有序集合.这个数据集有一个名称,叫做文件名.实际上我们已经多次使用了文件,例如源程序文件.目标文件.可 ...

  4. C++的File类文件操作

    C++的File类文件操作 语言文件系统称为流文件(Stream),正文流(正文文件),二进制流(二进制文件) 缓冲与非缓冲文件 顺序操作文件与随机操作文件 顺序文件:读/写第K个数据块之前必须读/写 ...

  5. python 入门第二课2 file的文件操作

    务必注意读/写方式和指针位置 1.文件操作总结 模式'r'或者'r+'或者'rb+'指针初始位置在文件开头 模式'w'或者'w+'或者'wb+'指针初始位置在文件末尾 模式'a'或者'a+'或者'ab ...

  6. win32 api 文件操作!

    CreateFile 打开文件 要对文件进行读写等操作,首先必须获得文件句柄,通过该函数可以获得文件句柄,该函数是通向文件世界的大门. ReadFile 从文件中读取字节信息. 在打开文件获得了文件句 ...

  7. php复制xml文件,PHP_php xml文件操作实现代码(二),复制代码 代码如下:?php //创 - phpStudy...

    php xml文件操作实现代码(二) 复制代码 代码如下: //创建一个新的DOM文档 $dom = new DomDocument(); //在根节点创建departs标签 $departs = $ ...

  8. 【Android 文件管理】分区存储 ( MediaStore 文件操作 )

    文章目录 一.动态权限申请 二.MediaStore 操作文件 三.完整代码示例 1.MainActivity 核心代码 2.build.gradle 构建脚本 3.清单文件 五.相关文档资料 特别注 ...

  9. 兼容input 文件选择_「HTML5」FileAPI 文件操作实战

    本文来自<FileAPI 文件操作实战> 其他系列放在了Github,欢迎交流和Star 介绍 HTML5 为我们提供了 File API 相关规范.主要涉及 File 接口 和 File ...

  10. Linux内核文件操作

    Linux内核文件操作 前言 一.文件操作结构体 二.VFS之file_operations对象 1.文件打开filp_open 2.文件关闭filp_close 3.文件读取vfs_read 4.文 ...

最新文章

  1. 突然想起99年的那次离别
  2. 【mathematical statistics】4 hypothesis testing
  3. php网站开发期末大作业,大学生期末网页大作业
  4. 深入解读:获Forrester大数据能力高评价的阿里云DataWorks思路与能力
  5. android 手机号码显示加空格,Android实现输入手机号时自动添加空格
  6. python怎么做图表_python 制作表格
  7. Python机器学习方向企业面试题(三)
  8. CCF201403-1 相反数(解法二)(100分)(废除!!!)
  9. android ResideMenu使用
  10. SPSS 有调节的中介与有中介的调节【SPSS 042期】
  11. Android微信页面缓存清理,安卓用户如何彻底清理微信大量缓存?4招让你彻底解决内存烦恼...
  12. ipa在线安装搭建_最新!超级签名系统源码以及搭建过程
  13. html 免备案,域名没有备案使用cdn(免备案cdn推荐)
  14. 冷数据、温数据、热数据,难道数据也是有温度的?
  15. 【计算机图形学】实验报告1用OpenGL画线命令绘制一个多边构成图形或场景
  16. 总结深度优先与广度优先的区别
  17. 成都市2021年高考三诊成绩查询,2020年成都各校高三“三诊”成绩一览表
  18. 用c#编写一个vb 工程源码分析工具(带源码工程下载)
  19. 卸载计算机应用程序的步骤,win7系统下卸载应用程序的步骤
  20. 防火墙工作原理(工作方式)

热门文章

  1. 动态规划:01背包问题、多段图问题
  2. 李宏毅机器学习笔记day3
  3. mul ab 的执行结果是_实战总结:为xxljob定制化的 php 执行器
  4. docker 内部ping不通宿主机_修改docker网段
  5. pre和code的区别
  6. 第一课:安卓开发工具Android Studio最新版本的安装
  7. 部分关键字--this/extends/super/static/final/abstract/访问权限总结
  8. Ubuntu上安装ns2-2.34
  9. 【转】程序员:如何写出杀手级简历
  10. struts2拦截器interceptor的三种配置方法