Canvas基本图片操作与处理

更新日期: 2020-03-12阅读: 1.8k标签: canvas

前言

Canvas是H5中新增的技术,主要运用在图片的处理和动画的绘制上,随着Canvas的使用场景越来越多,了解Canvas对平时开发大有裨益,这篇文章将介绍Canvas基本图片操作与处理


图片上传与绘制

将图片上传并绘制到Canva中是最常见的Canvas的图片处理,这个上传与绘制的过程是怎么实现的呢?下面举个例子:

<canvas id="myCanvas"></canvas>
<input type="file" id="file">
let upload = document.getElementById('file')
upload.onchange = (event) => {
  let file = event.target.files[0]
  let fileReader = new FileReader()
  fileReader.onload = (e) => {
    let img = new Image()
    img.src = e.target.result
    img.onload = () => {
      let canvas = document.getElementById('myCanvas')
      canvas.width = img.width
      canvas.height = img.height
      let context = canvas.getContext('2d')
      context.drawImage(img, 0, 0)
    }
  }
  fileReader.readAsDataURL(file)
}

这个上传与绘制的过程可以总结为两步:

  • 通过FileReader对象将input上传的file对象转化为base64格式的图片
  • 创建Image对象,将对象绘制在canvas上

这里为什么要将base64格式的地址复制给Image对象,然后再将Image对象绘制到Canvas上而不是直接绘制呢?
这是因为Canvas上绘制时并不支持url作为图片源,Canvas只支持下面几种图片源:

  • Image()函数构造的或者任何<img>元素
  • <video>元素作为图片源,可以抓取当前帧作为图像
  • 另一个<canvas>元素作为源
  • 高性能位图作为图片源

Canvas在绘图时还有一个需要注意的点就是:Canvas在绘制不同域名下的图片会出现跨域的错误,如图:

被污染的Canvas,其实就是因为图片跨域的问题的,这时需要两步走:

  • 图片服务器响应头添加Access-Control-Allow-Origin为*或者指定域名
  • 设置Image的crossOrigin属性img.setAttribute("crossOrigin",'Anonymous')

简单示例代码

let img = new Image()
img.setAttribute("crossOrigin",'Anonymous')
img.src = './images/avatar.jpeg'
img.onload = () => {
  let canvas = document.getElementById('myCanvas')
  canvas.width = img.width
  canvas.height = img.height
  let context = canvas.getContext('2d')
  context.drawImage(img, 0, 0)
  console.log(canvas.toDataURL('image/png', 1.0))
} 

更多跨域相关内容可以看这里


图片变换

图片缩放

Canvas中图片缩放的实际上是通过画布的缩放来达到的,因此默认的缩放中心是在画布原点(0, 0),但是一般情况下我们做缩放时都希望图片中心是缩放中心,这里有两种办法能达到图片中心作为缩放中心的缩放效果,接下来分别来看这两种办法的示例:
第一种:

let canvas = document.getElementById('myCanvas')
canvas.width = img.width
canvas.height = img.height
let context = canvas.getContext('2d')
context.translate(img.width / 2, img.height / 2)
context.scale(0.5, 0.5)
context.translate(-img.width / 2, -img.height / 2)
context.drawImage(img, 0, 0, img.width, img.height)

第一种方法就是画布平移,先将画布原点移到图像中心,然后再做画布缩放,再将画布平移还原,最后绘制图片,此时绘制的图片就是以图片中心做的缩放

第二种:

let canvas = document.getElementById('myCanvas')
canvas.width = img.width
canvas.height = img.height
let context = canvas.getContext('2d')
let paintWidth = img.width / 2
let paintHight = img.height / 2
let originX = 0 // 原图片X坐标
let originY = 0 // 原图片Y坐标
let paintX = originX + (img.width - paintWidth) / 2 // 缩放后的图片X坐标
let paintY = originY + (img.height - paintHight) / 2 // 缩放后的图片Y坐标
context.drawImage(img, paintX, paintY, paintWidth, paintHight)

第二种就是最直接的计算当图片以左上角作为缩放中心,缩放后的图片位置产生的位置偏移,将位置偏移加上在进行图片绘制

图片旋转

Canvas的图片旋转和图片缩放一样,默认的旋转中心也是画布的原点(0, 0),此时也需要平移画布来实现图片的中心旋转,举个例子

let img = new Image()
img.setAttribute("crossOrigin",'Anonymous')
img.src = './images/avatar.jpeg'
img.onload = () => {
let canvas = document.getElementById('myCanvas')
  canvas.width = img.width
  canvas.height = img.height
  let context = canvas.getContext('2d')
  context.translate(img.width / 2, img.height / 2)
  context.rotate(30 * Math.PI / 180)
  context.translate(-img.width / 2, -img.height / 2)
  context.drawImage(img, 0, 0, img.width, img.height)
}

镜像变换

镜像变换可以以图片垂直中线为对称轴,左右镜像的变换叫水平镜像,或者水平中线为对称轴,上下镜像的变换叫垂直镜像,一般水平镜像用的比较多,这里就来看一个水平镜像的例子:

let img = new Image()
img.setAttribute("crossOrigin",'Anonymous')
img.src = './images/avatar.jpeg'
img.onload = () => {
  let canvas = document.getElementById('myCanvas')
  canvas.width = img.width
  canvas.height = img.height
  let context = canvas.getContext('2d')
  context.translate(img.width / 2, img.height / 2)
  context.scale(-1 , 1)
  context.translate(-img.width / 2, -img.height / 2)
  context.drawImage(img, 0, 0, img.width, img.height)
}

原图:

水平镜像:


镜像操作的原理其实很简单:就是将scale设置为负值,当x轴的缩放为负值时,就是水平镜像,当y轴的缩放为负值时就是垂直镜像

对称轴翻转

对称轴翻转指的是图片沿着左上角至右下角的对角线翻转,来看用代码Canvas是怎么实现的:

let img = new Image()
img.setAttribute("crossOrigin",'Anonymous')
img.src = './images/avatar.jpeg'
img.onload = () => {
  let canvas = document.getElementById('myCanvas')
  canvas.width = img.width
  canvas.height = img.height
  let context = canvas.getContext('2d')
  context.translate(img.width / 2, img.height / 2)
  context.scale(-1 , 1)
  context.rotate(90 * Math.PI / 180)
  context.translate(-img.width / 2, -img.height / 2)
  context.drawImage(img, 0, 0, img.width, img.height)
}

翻转图:


实现原理:先做水平镜像,然后顺时针旋转90度,由于先做的水平镜像,坐标轴会被水平翻转,顺时针旋转90度实际是逆时针旋转90度


图片灰度

图片的灰度效果是Canvas非常常见的一个图片处理效果,先来看实现灰度效果的代码:

let img = new Image()
img.setAttribute("crossOrigin",'Anonymous')
img.src = './images/avatar.jpeg'
img.onload = () => {
  let canvas = document.getElementById('myCanvas')
  canvas.width = img.width
  canvas.height = img.height
  let context = canvas.getContext('2d')
  context.drawImage(img, 0, 0, img.width, img.height)
  let imageData = context.getImageData(0, 0, img.width, img.height)
  let data = imageData.data
  for (let i = 0; i < data.length; i += 4) {
    let average = (data[i] + data[i + 1] + data[i + 2]) / 3
    data[i] = average
    data[i + 1] = average
    data[i + 2] = average
  }
  context.putImageData(imageData, 0, 0)
}

灰度效果图:


实现思路:

  • 先将图片绘制在canvas上
  • 利用getImageData方法获取每个像素点的rgb值
  • 求出每个像素点的rgb平均值,然后重新赋值
  • 利用putImageData将重新计算的imageData对象绘制到图片上

这里可能会有人对getImageData和putImageData这两个api不是很熟悉,想要了解这个两个api的可以点getImageDataputImageData


总结

Canva在图片的处理上凸显的作用越来越大,因此写了这篇文章对Canvas基本图片操作与处理做了简单的介绍,希望看了这篇文章对大家了解Canvas能有所帮助。如果有错误或不严谨的地方,欢迎批评指正,如果喜欢,欢迎点赞

原文:https://segmentfault.com/a/1190000022026418

链接: https://www.fly63.com/article/detial/8211

HTML5 Canvas绘图基本使用方法, H5使用Canvas绘图

Canvas 是H5的一部分,允许脚本语言动态渲染图像。Canvas 定义一个区域,可以由html属性定义该区域的宽高,javascript代码可以访问该区域,通过一整套完整的绘图功能(API),在网页上渲染动态效果图。

web图片前端裁剪功能实现_利用html5 canvas技术实现图片裁剪

上传截图很多做法是把图像发送到后端,把裁剪后的结果发送给浏览器,这种方式会增加处理时延。用canvas提供的API实现纯前端的剪切:这里头关键有三步:显示未经处理的图片,得到裁剪区域,显示裁剪后的区域。

原生js使用canvas实现图片格式webp/png/jpeg在线转换

javascript完成图片格式转换: 通过input上传图片,使用FileReader将文件读取到内存中。将图片转换为canvas,canvas.toDataURL()方法设置为我们需要的格式,最后将canvas转换为图片。

离屏Canvas — 使用Web Worker提高你的Canvas运行速度

现在因为有了离屏Canvas,你可以不用在你的主线程中绘制图像了!Canvas 是一个非常受欢迎的表现方式,同时也是WebGL的入口。它能绘制图形,图片,展示动画,甚至是处理视频内容

canvas高效绘制10万图形,你必须知道的高效绘制技巧

最近的一个客户项目中,简化的需求是绘制按照行列绘制很多个圆圈。需求看起来不难,上手就可以做,写两个for循环。,IT行业的知识更新越来越快,能够以不变应万变的人,就是拥有良好的学习力、创造力、判断力和思考力的人。这些能力会让你在变换万千的技术海洋中,屹立不倒,不被淹没。

利用canvas将网页元素生成图片并保存在本地

利用canvas将网页元素生成图片并保存在本地,首先引入三个文件,createElementNS() 方法可创建带有指定命名空间的元素节点。 createElementNS(ns,name) > createElementNS() 方法与 createElement() 方法相似

基于 HTML5 Canvas 的智能安防 SCADA 巡逻模块

随着大数据时代的来临,物联网的日益发展,原先的 SCADA 系统本身也在求新求变,从最开始的专业计算机和操作系统,到通用计算机和相关软件,再到现在基于 HTML5 Canvas 的新型组态开发,其应用的范围也从最初的电力

js用canvas实现简单的粒子运动

在写下合格粒子运动时要先清楚你的思路,不能一开始就盲目的开始写,首先先要确定思路然后在去一步步的实现,在写的过程要注意细节,要思考js有些知识是跟数学知识相关的要注意观察

Canvas 点线动画案例

canvas 画的圆不是圆,是椭圆。不要在style里指定 Canvas 的宽度,Canvas 画布的尺寸的大小和显示的大小是有很大的区别的,在 canvas 里面设置的是才是 Canvas 本身的大小。不要企图通过闭合现有路径来开始一条新路径

Canvas在移动端绘制模糊的原因与解决办法

由于一些移动端的兼容性原因,我们某个项目需要前端将pdf转换成在移动端页面可直接观看的界面。为了方便解决,我们采用了pdf.js这个插件,该插件可以将pdf转换成canvas绘制在页面上

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!