先看一下这张图
这张图来自某掘金人的...忘记叫啥了。感谢!
算了,开始结合MDN看这张图里面的内容吧。
基础api
blob
Blob表示一个不可变的、原始数据的类文件对象。可以按二进制或者文本的方式读取。
也可以转化成流文件。
使用blob()创建一个blob数据。
/**
*
* @array {bolb、ArrayBuffer,DOMstring...}
* @options 数组内容的MIME类型。
*/
var blob = new Blob(array,options);
实例的属性
- size
- type
实例的方法
- blob.arrayBuffer()
- 返回promise对象 其中包含 arrayBuffer的二进制数据。
// 使用 let bufferPromise = blob.arrayBuffer(); let buffer = await blob.arrayBuffer();
- 返回promise对象 其中包含 arrayBuffer的二进制数据。
- blob.slice()
- 可将blob切割成小型的blob。类似数组。
let Ablob = blob.splice(0,2,'') // 返回剪切的部分
- 可将blob切割成小型的blob。类似数组。
- blob.stream()
- 方法返回一个ReadableStream对象,读取它将返回包含在Blob中的数据。
let ReadableStream = blob.stream(); - blob.text()
- 方法返回一个 Promise 对象,包含 blob 中的内容,使用 UTF-8 格式编码。
var textPromise = blob.text(); var text = await blob.text();
- 方法返回一个 Promise 对象,包含 blob 中的内容,使用 UTF-8 格式编码。
file
file是blob的一个继承。
file提供了文件信息的读取。
[file].type
[file].size
[file].name
file文件来自用户通过input选择的fileList。
或者拖动生成的xx对象(我才拖动上传就是这个api),这个之后在去了解。
file处理的和blob相同。
我们可以使用 FileReader 和 URL.createObjectURL()、
XMLHttpRequest.send()对file和blob进行处理。
继承方法
file.splice(start,end,'')
FileReader
file对象允许web应用异步读取原始数据缓冲区的内容, 使用file和blob对象指定要读取的文件或者数据。
读取blob、file等
let reader = new FileReader()
reader.onload = (e)=>{
console.log(e.target.result)
}
reader.readAsDataURL( new Blob() )
上面的代码演示了创建一个 FileReader。 通过readAsDataURL读取指定的内容, 在onload(读取完成后)即可以在target.result中返回base64的内容。
除此之外,它还有一下几种方法。
reader.readAsText()
在result中返回字符串形式的内容
reader.readAsArrayBuffer()
在result中返回ArrayBuffer数据对象
reader.readAsBinaryString()
在result中返回二进制数据
URL.createObjectURL
这个方法来自 URL
它允许浏览器用它指定一个 file 或者 blob 并将其其转化为DOMString。
他和DOM息息相关,因此我们在不在使用他转换完成的这个DOMString之后,我们需要使用
window.URL.revokeObjectURL(url)将其释放,得到最佳的性能效果。
基础应用
文件下载
链接类型的文件下载我们分为以下几个步骤
- 资源文件转为blob类型
- 当我们下载一个文件的资源链接时,我们可以使用ajax对这个文件资源的
responseType设置为blob。 这样我们得到了一个blob类型的文件。这个文件存在浏览器缓冲区中。
- 当我们下载一个文件的资源链接时,我们可以使用ajax对这个文件资源的
- 获取到缓冲区的文件地址,配合a标签实现下载。
- 浏览器提供了URL.createObjectURL()方法,可以将链接地址转化为blob的前端url链接。a标签下载 a标签实现下载的过程,不在本次研究范围内。
- 当已经实现下载之后我们需要对这个缓冲区中的文件进行释放。
- window.URL.revokeObjectURL(url)
见如下代码:
<DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件下载demo</title>
<script src="../ajax/index.js"></script>
</head>
<body>
<div onclick="downloadFiel()">下载</div>
<script>
let fileUrl = 'https://bloggers-1304641141.cos.ap-beijing.myqcloud.com/img/1636095726424.jpg';
const downloadFiel = function (url){
ajax({
type:"get",
reqireUrl: url || fileUrl,
responseType:"blob",
success:function (res){
let a = document.createElement('a');
//将通过ajax处理返回的blob对像,转化为blob类型的url(DOMString);
let url = window.URL.createObjectURL(res)
a.href = url;
// 裁剪最后一个类型编辑,编辑下载名称
a.download = '测试.'+fileUrl.split('.').reverse()[0]
// 触发a标签
a.click()
// 释放blob DOMString
window.URL.revokeObjectURL(url)
}
})
}
</script>
</body>
</html>
canvas图片处理。
canvas图片处理思路
1、这里我们选择文件,将文件使用URL.createObjectURL()将文件转为blob类型的url进行渲染。
2、我们可以通过new Image()加载这个图片,并且使用canvas对图片进行处理。
3、最后使用canvas.toBlob()将处理后的图片转换为blob文件。
4、将这个blob文件使用URL.createObjectURL()得到blob类型的url下载保存下来。
处理过程
额,逻辑算比较简单的,然后就直接写上全部代码啦,可以赋值以下代码直接看。 有点简陋。你可以优化以下,(●ˇ∀ˇ●)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvas图片处理</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.img {
margin-top: 15px;
text-align: center;
}
.btn{
display: inline-block;
width: 100px;
height: 35px;
line-height: 35px;
background-color: #42b983;
border-radius: 20px;
text-align: center;
color: #fff;
transition: 0.4s;
}
.btn:hover{
cursor: pointer;
opacity: 0.8;
transition: 0.4s;
}
</style>
</head>
<body>
<div class="img">
<canvas id="image"></canvas>
</div>
<div class="file">
<input accept="image/*" id="file" type="file"> <div class="btn" id="save">保 存</div>
</div>
<script>
window.URL = window.URL || window.webkitURL ;
let file = document.getElementById('file');
let canvas = document.getElementById('image');
let btn = document.getElementById('save')
let ctx = canvas.getContext('2d');
canvas.width = 270;
canvas.height = 270;
let img = new Image();
// 定义国旗星星数组
let stars = []
file.onchange = function (e) {
// 使用createObjectURL 找到对应缓存中的地址字符传
let url = window.URL.createObjectURL(e.target.files[0])
img.onload = function () {
handleDraw();
}
img.src = url;
}
btn.onclick = function (){
if(file.files.length<1){
alert('请选择图片')
return
}
canvas.toBlob(function (e){
let saveUrl = window.URL.createObjectURL(e)
let a = document.createElement('a')
console.log(saveUrl)
a.href=saveUrl
a.download = 'save.png'
console.log(a)
a.click()
window.URL.revokeObjectURL(saveUrl)
})
}
// 利用crc设置圆角
const handleBorderRect = (ctx, x, y, w, h, r, color) => {
ctx.beginPath();
// 左上角
ctx.arc(x + r, y + r, r, Math.PI, 1.5 * Math.PI);
ctx.moveTo(x + r, y);
ctx.lineTo(x + w - r, y);
ctx.lineTo(x + w, y + r);
// 右上角
ctx.arc(x + w - r, y + r, r, 1.5 * Math.PI, 2 * Math.PI);
ctx.lineTo(x + w, y + h - r);
ctx.lineTo(x + w - r, y + h);
// 右下角
ctx.arc(x + w - r, y + h - r, r, 0, 0.5 * Math.PI);
ctx.lineTo(x + r, y + h);
ctx.lineTo(x, y + h - r);
// 左下角
ctx.arc(x + r, y + h - r, r, 0.5 * Math.PI, Math.PI);
ctx.lineTo(x, y + r);
ctx.lineTo(x + r, y);
ctx.fillStyle = color;
ctx.fill();
ctx.closePath();
};
class Star {
constructor(ctx, x, y, size) {
this.ctx = ctx
this.ponits = []
this.color = 'yellow'
for (let i = 1; i <= 5; i++) {
let temp = {
x: Math.cos((18 + i * 72) / 180 * Math.PI) * size + size + x,
y: -Math.sin((18 + i * 72) / 180 * Math.PI) * size + size + y,
sx: Math.cos((54 + i * 72) / 180 * Math.PI) * 0.4 * size + size + x,
sy: -Math.sin((54 + i * 72) / 180 * Math.PI) * 0.4 * size + size + y,
}
this.ponits.push(temp);
}
stars.push(this)
}
draw() {
let list = this.ponits
this.ctx.beginPath()
for (let i = 0; i < list.length; i++) {
let temp = list[i]
ctx.lineTo(temp.x, temp.y)
ctx.lineTo(temp.sx, temp.sy)
}
this.ctx.fillStyle = this.color
this.ctx.fill()
this.ctx.closePath()
}
}
// 添加五角星
const drawStart = (ctx) => {
// 计算圆上点的坐标
function getXyByRound(h, r) {
return {
y: Math.sin(Math.PI * 2 / 360 * h) * r,
x: Math.cos(Math.PI * 2 / 360 * h) * r
}
}
new Star(ctx, 20, 40, 25)
let index = 0
while (index < 4) {
let temp = getXyByRound(index*27, 60)
index++
new Star(ctx, temp.x+20, temp.y+40, 10)
}
stars.forEach(star => star.draw())
}
// 添加渐变色蒙层
const drawReact = (ctx, x, y, w, h) => {
let gradient = ctx.createLinearGradient(x, y, w, h)
ctx.beginPath()
gradient.addColorStop(0, 'rgba(255,0,0,.9)')
gradient.addColorStop(1, 'rgba(255,0,0,0)')
ctx.fillStyle = gradient
ctx.fillRect(0, 0, w, h)
ctx.closePath();
}
const handleDraw = () => {
// 剪裁圆角
handleBorderRect(ctx, 10, 10, 250, 250, 14, 'orange');
ctx.clip();
// 绘制图片
ctx.drawImage(img, 10, 10, 250, 250);
// 添加渐变色
drawReact(ctx, 10, 10, 270, 270);
// 添加五角星整列
drawStart(ctx);
};
</script>
</body>
</html>
测试/排除
经过测试,在手机端微信浏览器中下载图片不可行,在手机内置浏览器中是可以的。
因此在遇到在微信内下载图片的需求时,
可以引导至外部浏览器中进行,或者将图片用a标签包裹,打开此图长按下载。