百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

谈谈图片上传及canvas压缩的流程(canvas图片压缩变黑)

myzbx 2025-05-05 17:35 9 浏览

我们通常在做图片上传的时候都会遇上这样的情况,一是后端接口限制上传图片的大小,或者是即使后端没有限制大小,因为图片太大在前端渲染时太慢,造成页面加载体验较差。因此我们很有必要对上传的图片进行压缩。

本文在gitthub做了收录:github.com/Michael-lzg…

本文主要包括以下流程:

  • 用户通过 input 框选择图片
  • 使用 FileReader 进行图片预览
  • 将图片绘制到 canvas 画布上
  • 使用 canvas 画布的能力进行图片压缩
  • 将压缩后的 Base64(DataURL) 格式的数据转换成 Blob 对象进行上传

Input 标签来获取图片

通过设置 input 标签的 type 属性为 file,来让用户可以选择文件,设置 accept 限制选择的文件类型,绑定 onchange 事件,来获取确认选择后的文件

<input type="file" accept="image/*" onchange="loadFile(event)"

FileReader

FileReader 是什么,我们先来看看官方文档的介绍

FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。

FileReader 常用的两个方法如下:

  • FileReader.onload:处理 load 事件。即该钩子在读取操作完成时触发,通过该钩子函数可以完成例如读取完图片后进行预览的操作,或读取完图片后对图片内容进行二次处理等操作。
  • FileReader.readAsDataURL:读取方法,并且读取完成后,result 属性将返回 Data URL 格式(Base64 编码)的字符串,代表图片内容。

在图片上传中,我们可以通过 readAsDataURL() 方法进行了文件的读取,并且通过 result 属性拿到了图片的 Base64(DataURL) 格式的数据,然后通过该数据实现了图片预览的功能

<div class="container">
  <input type="file" accept="image/*" onchange="loadFile(event)" />
</div>
<script>
  const loadFile = function (event) {
    let file =  event.target.files[0]
    const reader = new FileReader()
    reader.onload = function () {
      console.log(reader.result)
      ...
    }
    reader.readAsDataURL(file)
  }
</script>

canvas 压缩图片

这是图片上传压缩的核心所在,我们先使用
CanvasRenderingContext2D.drawImage() 方法将上传的图片文件在画布上绘制出来,再使用 Canvas.toDataURL() 将画布上的图片信息转换成 base64(DataURL) 格式的数据。

drawImage()

drawImage() 方法在画布上绘制图像、画布或视频。drawImage() 方法也能够绘制图像的某些部分,以及/或者增加或减少图像的尺寸。参数如下

  • img 规定要使用的图像、画布或视频。
  • sx 可选。开始剪切的 x 坐标位置。
  • sy 可选。开始剪切的 y 坐标位置。
  • swidth 可选。被剪切图像的宽度。
  • sheight 可选。被剪切图像的高度。
  • x 在画布上放置图像的 x 坐标位置。
  • y 在画布上放置图像的 y 坐标位置。
  • width 可选。要使用的图像的宽度。(伸展或缩小图像)
  • height 可选。要使用的图像的高度。(伸展或缩小图像)
var cas = document.querySelector('canvas')
var ctx = cas.getContext('2d')
// 先创建图片对象
var img = new Image()
img.src = './images/1.jpg'

// 图片加载完之后
img.onload = function () {
  ctx.drawImage(img, 206, 111, 32, 38, 100, 100, 32, 38)
}

Canvas.toDataURl()

Canvas.toDataURl() 方法可以将 canvas 画布上的信息转换为 base64(DataURL) 格式的图像信息,纯字符的图片表示形式。该方法接收 2 个参数:

  • mimeType(可选): 表示需要转换的图像的 mimeType 类型。默认值是 image/png,还可以是 image/jpeg, image/webp 等。
  • quailty(可选):quality 表示转换的图片质量。范围是 0 到 1。图片的 mimeType 需要是 image/jpeg 或者 image/webp,其他 mimeType 值无效。默认压缩质量是 0.92。
var canvas = document.createElement('canvas')
canvas.toDataURL("image/jpeg" 0.8)

到这里,我们先来上 canvas 压缩图片的代码

function compress(base64, quality, mimeType) {
  let canvas = document.createElement('canvas')
  let img = document.createElement('img')
  img.crossOrigin = 'anonymous'
  return new Promise((resolve, reject) => {
    img.src = base64
    img.onload = () => {
      let targetWidth, targetHeight
      if (img.width > MAX_WIDTH) {
        targetWidth = MAX_WIDTH
        targetHeight = (img.height * MAX_WIDTH) / img.width
      } else {
        targetWidth = img.width
        targetHeight = img.height
      }
      canvas.width = targetWidth
      canvas.height = targetHeight
      let ctx = canvas.getContext('2d')
      ctx.clearRect(0, 0, targetWidth, targetHeight) // 清除画布
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
      let imageData = canvas.toDataURL(mimeType, quality / 100)
      resolve(imageData)
    }
  })
}

将 base64 转化为文件

  • 通过 window.atob 将 base-64 字符串解码为 binaryString(二进制文本);
  • 将 binaryString 构造为 multipart/form-data 格式;
  • 用 Uint8Array 将 multipart 格式的二进制文本转换为 ArrayBuffer。
function dataUrlToBlob(base64, mimeType) {
  let bytes = window.atob(base64.split(',')[1])
  let ab = new ArrayBuffer(bytes.length)
  let ia = new Uint8Array(ab)
  for (let i = 0; i < bytes.length; i++) {
    ia[i] = bytes.charCodeAt(i)
  }
  return new Blob([ab], { type: mimeType })
}

将图片上传到服务端

  • 创建一个 FormData,把 blob append 到 FormData 里面
  • 请求服务端接口,提交图片
function uploadFile(url, blob) {
  let formData = new FormData()
  let request = new XMLHttpRequest()
  formData.append('image', blob)
  request.open('POST', url, true)
  request.send(formData)
}

ps:在实际开发中,我们要不要把图片转化为 FormData 形式上传到服务端,这就看具体的业务需要了。我们可以上图片上传到腾讯云,直接返回一个'https.xxx.jgp'的图片 url 用于上传。

如何获取?

转发这篇文章,关注我,私信回复“资料”即可获取高清大纲,以上 spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构

如何私信?

关注我后,在手机,点进头像进我的主页,主页上方右上角有个私信,点击私信,如何回复关键字“资料”即可

相关推荐

Oculus虚拟控制器细节曝光:可实现游戏控制

最近,Oculus发布了OculusRift的开发者指南与Oculus的0.7版本SDK开发开发工具,从中我们看到了关于OculusTouch虚拟现实游戏控制器与虚拟现实头盔配合使用的更多细节。O...

58年游戏控制器进化史 1分钟视频科普醒脑

今日,油管频道SuperDeluxe发布了一段手柄发展史特制视频,从1958年电子游戏鼻祖《TENNISFORTWO》控制器开始,到随后较为知名的「Pong」与「FC」,很多产品是具有相似结构和...

真正用手玩游戏 对应Valve Index的SteamVR手套控制器预购

尽管不温不火,不过SteamVR游戏也有不少忠实玩家,日前一款支持ValveIndex的SteamVR手套控制器RealityXRGameGlove公开预购,一起来了解下。·RealityX...

499元起,八位堂全按键专业街机控制器“天刃星”发售

IT之家5月18日消息,八位堂昨日在国内发售了新款全按键专业街机控制器“天刃星”,可选复古版、Xbox版,定价分别为499元和599元。两款控制器均为电子竞技和街机游戏的职业玩家设计...

八位堂发布两款Fightingdeck控制器:专为格斗、射击类游戏打造

IT之家5月17日消息,八位堂日前宣布,将于2025年7月15日推出两款全新的Fightingdeck街机控制器:一款定价89.99美元(IT之家注:现汇率约合649元...

HORI《太鼓达人》游戏专用控制器11月6日首销,478元

IT之家11月1日消息,HORI索尼授权《太鼓达人》专用游戏控制器“太鼓”现已上架京东,将于11月6日开售,这款“太鼓”支持PS5/PS4/PC使用,相比Switch...

修改手机通知栏,居然能玩游戏!

在之前的内容中,技能君给大家分享过不少关于手机通知栏美化的小技巧,然而,这些胡里花俏的技能,全都是仅支持安卓手机的。所以,今天技能君就给iPhone的小伙伴们带来一款仅支持iPhone的通知栏美化小组...

用完支付宝、微博和淘宝的小组件,我发现我回不去了

iOS14的更新之后,最开心的就是我们这群被苹果封闭系统“禁欲”了很多年的苹果用户了。仿佛一瞬间所有人的iPhone都成为了一款“变装”游戏,各种花里胡哨的图标,好看的小组件一...

《使命召唤17:黑色行动冷战》追加3v3狙击战模式

《使命召唤17:黑色行动冷战》周二进行了更新中,追加了一个在《使命召唤16:现代战争》中首次普及的游戏模式——3V3狙击游戏。它通过限定玩家使用狙击步枪来改变常规的枪战模式。TreyarchStud...

Unity常用组件整理(一)

【1】变换Transform为物体提供最基本的位置、旋转、缩放等属性,而且“父子关系”也由它管理(每个物体有且只有一个)【2】光源Light为场景提供各种光源。大部分材质都需要有光源照射才能正...

HarmonyOS新增300多个开源组件,涉游戏、音视频等8大类

据“HarmonyOS开发者”微信公众号7月28日消息,自第一批HarmonyOS400+组件开源后,本次新增300多个开源组件,共涉及8大类(工具、网络、文件数据、UI、框架、动画图形、音视频、游...

《我的世界》狂欢节强势来袭 惊喜折扣福利送不停

亲爱的冒险家,双11即将到来,我们也迫不及待为大家带来了好消息~“MC狂欢节”强势来袭!方块世界有惊喜折扣等着你哦~11月6日到11月11日,《我的世界》将携手知名KOL与开发者在虎牙直播欢乐开播,...

游戏开发需要学什么

游戏开发可以说是当下最热门的专业了,不过这一行业虽然很火热,但也有一定的竞争压力。这个行业需要大量的人才,而且游戏开发这个行业目前还处于初级阶段,所以发展空间还是很大的。现在有很多人都想进入这个行业,...

昆仑万维开源Matrix-Game大模型 可据指令生成相应游戏世界视频

【太平洋科技快讯】5月13日,昆仑万维宣布,旗下Matrix系列的交互式世界生成方向正式落地,推出Matrix-Game大模型(17B),并开源其核心代码。Matrix-Game是工业界首个...

游戏帧数低硬件不背锅 如何完善游戏运行环境?

众所周知,在玩游戏的过程中,电脑配置对游戏的体验影响是巨大的,不同的硬件配置会对游戏的运行效果产生千差万别的效果。但是除了硬件条件以外,运行环境对游戏的运行效果也是有着千丝万缕的影响。想要获得一个完美...