canvas图片裁剪并base64转化

一.需求

在canvas画布上,假设我们绘制了一张图片,现在需要将该图片进行裁剪,并将裁剪的区域提取成图像,并将该图像转化为base64格式返回,要求编写这样一个脚本。

二.知识储备

HTML5画布中,Canvas的以下几个接口可能是我们所需要的:

1. clip:

该接口用于对当前的画布设置裁剪区域,在之后的绘制过程中,只有裁剪区域中的绘制能够生效,即能够呈现。

该方法需要先绘制一个封闭的路径,比如一个圆(arc),抑或是一个矩形(rect),接着在通过clip进行裁剪:

例:

cxt.rect(0, 0, 100, 100);
cxt.clip();

裁剪之后只能在裁剪区呈现绘制,如果想要去除clip的影响,则需要在clip裁剪动作之前先将画布的状态保存起来,比如:cxt.save(),当我们需要重新绘制时,便可以通过cxt.restore()恢复至clip之前的状态,我们就可以在clip之前的状态下进行绘制。不过需要提醒的是:虽然恢复了状态,但是在restore之前和clip之后受到影响的绘制仍会保持原样,具体可以自己测试以下。

2. drawImage:

该接口用于在canvas画布中的特定位置将图像、画布或者视频绘制在其上,其有三种语法:

语法1:通过设置图像的左上角在画布的位置(x, y)将图像按图像原本大小进行绘制

context.drawImage(img, x, y);

语法2:相较于语法1,此语法设置图片在画布上的宽高(图像的拉伸缩小)

context.drawImage(img, x, y, width, height)

语法3:相比于语法2,添加了四个参数,sx、sy设置对图像进行裁剪的区域左上角相对于图像的位置,swidth、sheight设置裁剪宽高

context.drawImage(img, sx, sy, swidth, sheight, x, y, width, height)

这里要注意的是,语法三中width和height是设定呈现于画布中的裁剪区的宽高。

3. getImageData:

该接口复制画布上指定矩形的像素数据,返回一个ImageData对象,该对象拷贝了画布指定矩形的像素数据。

语法:

var imgData = context.getImageData(x, y, width, height);

x、y是指开始复制的区域的左上角x坐标和y坐标;

width、height是指将要复制的矩形区域的宽高;

4. putImageData:

该接口将图像数据(从指定的ImageData对象)放回画布上。

语法:

context.putImageData(imgData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight);//后面四个参数是可选的

imgData: 要放回画布的ImageData对象;

x、y: ImageData对象左上角的x、y坐标;

dirtyWidth, dirtyHeight:相当于裁剪宽度和高度;

dirtyX、 dirtyY:相对于裁剪区的偏移位置;

5. toDataURL:

该接口用于将整个canvas画布图像转化为dataURL(base64)。

语法:

canvas.toDataURL(type, encoderOptions)

两个参数均为可选,第一个参数指定图片格式,第二个参数指定图片的质量,返回值为包含data URI的DOMString。

三.思路

根据上面的知识储备,我们设计一下脚本逻辑:

  1. 首先设置裁剪区;

  2. 将图片绘制在画布的左上角;

  3. 通过getImageData获取裁剪区的像素;

  4. 创建一个和裁剪区一样大小的canvas;

  5. 通过putImageData将裁剪区像素复制到新创建的canvas画布中;

  6. 通过新的canvas调用toDataURL获取base64格式图像;

四.编码


//获取canvas画布相应区域的图像信息,并返回其base64格式的图像

  function getBase64Image(context, x1, y1, x2, y2) {

    var dataImg = context.getImageData(x1, y1, x2, y2);

    var canvas2 = document.createElement("canvas");

    var context2 = canvas2.getContext("2d");

    var width = Math.abs(x1 - x2);

    var height = Math.abs(y1 - y2);

    canvas2.width = width;

    canvas2.height = height;

    context2.putImageData(dataImg, 0, 0, 0, 0, width, height);

    var res = canvas2.toDataURL('image/jpeg');

    return res;

  }

五.发现问题

我们在本地进行测试的时候,会报错:

在这里插入图片描述

为什么会报错呢?

为了阻止欺骗,浏览器会追踪 image data。当你把一个“跟canvas的域不同的”图片放到canvas上,这个canvas就成为 “tainted”(被污染的,脏的),浏览器就不让你操作该canvas 的任何像素。这对于阻止多种类型的XSS/CSRF攻击(两种典型的跨站攻击)是非常有用的。

因为本地没有服务器环境仍然会报错,没有域的概念,浏览器会将图片判定为跨域,从而报错。

那我们就将测试demo放到服务器中就行了吧,运行一下,果然是可以了,如下截图所示:(注意图片必须是位于同一服务器环境)

在这里插入图片描述

看见没有,裁剪的图我们通过base64格式将其展示在左下角。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值