上一篇说了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 = 300 class SimpleImageCutter {
constructor(options) {
this.fileUpload = options.fileUpload
this.imgPreview = options.imgPreview
this.imgResult = options.imgResult
this.cutter = options.cutter this.percentage = this.imgResult.parentElement.clientWidth / this.cutter.clientWidth
this.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 = null
imgPreview.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 + cPBorderWidth
this.iTop = imgPreview.getBoundingClientRect().top + document.documentElement.scrollTop + cPBorderWidth
this.iRight = this.iLeft + imgPreview.clientWidth
this.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.offsetX
cOffsetY = 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 - cBorderWidth
cTop = ev.clientY - cOffsetY - cBorderWidth
cRight = cLeft + cutter.clientWidth + cBorderWidth
cBottom = cTop + cutter.clientHeight + cBorderWidth if (!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 / pw
phc > 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. File API文件操作之FileReader

    近来研究点对点的文件传输,想到一种方案FileReader+WebRtc. 当我看到FileReader的时候,哎呀,不错的东西啊,仔细一看属于File API,或者叫做Web API. File A ...

  2. JAVASE02-Unit06: 文件操作——File 、 文件操作—— RandomAccessFile

    Unit06: 文件操作--File . 文件操作-- RandomAccessFile java.io.FileFile的每一个实例是用来表示文件系统中的一个文件或目录 package day06; ...

  3. 【转】c#文件操作大全(二)

    61.文件夹移动到整合操作 FolderDialog aa = new FolderDialog();            aa.DisplayDialog();            if (aa ...

  4. [转]JavaScript文件操作(2)-FileReader

    在上篇文章中,我介绍了在JavaScript操作文件,重点讲了如何取得File对象. 这些对象包含的文件的元数据在上传或者拖放到浏览器中时可以获取到.有了文件当然接下来就是读取文件了. FileRea ...

  5. C使用FILE指针文件操作

    文件的基本概念 所谓“文件”是指一组相关数据的有序集合. 这个数据集有一个名称,叫做文件名.实际上在前面的各章中我们已经多次使用了文件,例如源程序文件.目标文件.可执行文件.库文件 (头文件)等.文件 ...

  6. 总结文件操作函数(二)-C语言

    格式化读写: #include <stdio.h> int printf(const char *format, ...);                   //相当于fprintf( ...

  7. 【File】文件操作(初识文件操作一)

    一,初识文件流 看到标题就知道接下来的所有操作对象都是面对文件进行的.那么问题来了.在java中目录是不是也属于文件呢?答案是yes.既然目录也属于文件,那么对于目录跟文件的区分就显现出来了.在接下来 ...

  8. win32 api 文件操作!

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

  9. Java中常用到的文件操作那些事(二)——使用POI解析Excel的两种常用方式对比

    最近生产环境有个老项目一直内存报警,不时的还出现内存泄漏,导致需要重启服务器,已经严重影响正常服务了.获取生成dump文件后,使用MAT工具进行分析,发现是其中有个Excel文件上传功能时,经常会导致 ...

随机推荐

  1. IntelliJ IDEA(四) :Settings【Appearance and Behavior】

    前言 IDEA是一个智能开发工具,每个开发者的使用习惯不同,如何个性化自己的IDEA?我们可以通过Settings功能来设置.Settings文件是IDEA的配置文件,通过他可以设置主题,项目,插件, ...

  2. 查看主机DNSserver

    一.Nslookup(name server lookup)( 域名查询):是一个用于查询 Internet 域名信息或诊断DNS server问题的工具.nslookup能够指定查询的类型,能够查到 ...

  3. 【NOI2010】海拔【平面图最小割】

    [问题描写叙述] YT市是一个规划良好的城市,城市被东西向和南北向的主干道划分为n×n个区域.简单起见.能够将YT市看作 一个正方形,每个区域也可看作一个正方形.从而.YT城市中包含(n+1)×(n+ ...

  4. myeclipse将java项目转换成web项目,导出war包

    1.项目右击属性,勾选以下两项,点击apply,关掉窗体,又一次打开 2.打开assembly,删掉webroot文件夹.把相应的webapp文件夹加入进来 watermark/2/text/aHR0 ...

  5. xml解析(4)

    本节要点: DOM解析方式 SAX解析方式 DOM4J对XML的解析 XML用于将数据组织起来,形成文档用于存储和传输: 更多时候我们需要的是将xml中的数据解析出来,甚至是在程序中动态生成xml. ...

  6. Selenium Python 安装指导

    最近无聊.又重新装了个selenium 果然时代变了.安装的时候的方法和以前不太一样了.因此觉得有必要单列出来加以说明 另外备注:测试小伙伴们.安装此类工具报错.尝试以下两个方案之一: 1.请转sta ...

  7. 浅析JavaScript的字符串查找函数:indexOf和search

    语法 ①indexOf:方法可返回某个指定的字符串值在长字符串中首次出现的位置.如果被查找字符串没有找到,返回-1. indexOf 说明:该方法将从头到尾地检索字符串 stringObject,看它 ...

  8. wait/notify 实现多线程交叉备份

    一.任务 创建20个线程,其中10个线程是将数据备份到 A 数据库中,另外10 个线程将数据备份到 B 数据库中,并且备份 A 数据库和 备份 B 数据库的是交叉运行的. 二.实现 1.实现备份 A ...

  9. Java并发编程之ThreadLocal源码分析

    ## 1 一句话概括ThreadLocal<font face="微软雅黑" size=4>  什么是ThreadLocal?顾名思义:线程本地变量,它为每个使用该对象 ...

  10. bzoj 2298: [HAOI2011]problem a

    Description 一次考试共有n个人参加,第i个人说:"有ai个人分数比我高,bi个人分数比我低."问最少有几个人没有说真话(可能有相同的分数) Input 第一行一个整数n ...