内容简介:最近在学习canvas,然后照葫芦画瓢简单实现了几个小demo,跟大家一块学习一下。用法:用法:
最近在学习canvas,然后照葫芦画瓢简单实现了几个小demo,跟大家一块学习一下。
主要内容
- 两个方法:drawImage、getImageData
- 前端图片预览、跨域图片问题
两个方法:drawImage、getImageData
drawImage
用法:
context.drawImage(img[, sx, sy, swidth, sheight], x, y[, width, height]); 复制代码
参数 | 描述 |
---|---|
img | 可以是图片、视频、画布 |
sx | 可选。开始剪切的 x 坐标位置。 |
sy | 可选。开始剪切的 y 坐标位置。 |
swidth | 可选。被剪切图像的宽度。 |
sheight | 可选。被剪切图像的高度。 |
x | 在画布上放置图像的 x 坐标位置。 |
y | 在画布上放置图像的 y 坐标位置。 |
width | 可选。要使用的图像的宽度。(伸展或缩小图像) |
height | 可选。要使用的图像的高度。(伸展或缩小图像) |
getImageData
用法:
context.getImageData(x, y, width, height); 复制代码
参数 | 描述 |
---|---|
x | 开始复制的左上角位置的 x 坐标。 |
y | 开始复制的左上角位置的 y 坐标。 |
width | 将要复制的矩形区域的宽度。 |
height | 将要复制的矩形区域的高度。 |
方法返回 ImageData 对象,该对象拷贝了画布指定矩形的像素数据。 是Uint8ClampedArray类型的一维数组,包含着RGBA格式的整型数据。 对于 ImageData 对象中的每个像素,都存在着四方面的信息,即RGBA值:
- R - 红色 (0-255)
- G - 绿色 (0-255)
- B - 蓝色 (0-255)
- A - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)
color/alpha 以数组形式存在,并存储于 ImageData 对象的 data 属性中。
这个样子:
先来一下demo,通过getImageData方法获取鼠标指针处的像素值。
demo1
部分代码:
methods: { import imgUrl from './component/sample.jpg'; export default { data () { return { canvas: null, ctx: null, color: null } }, methods: { pick (e, ctx) { let x = e.layerX, y = e.layerY, pixel = ctx.getImageData(x, y, 1, 1), data = pixel.data, rgba = 'rgba(' + data[0] + ',' + data[1] + ',' + data[2] + ',' + ((data[3] / 255).toFixed(2)) + ')'; this.color.style.background = rgba; this.color.textContent = rgba; } }, mounted () { this.canvas = this.$refs['canvas']; this.ctx = this.canvas.getContext('2d'); this.color = this.$refs['color']; let img = new Image(); img.src = imgUrl; img.onload = () => { this.ctx.drawImage(img, 0, 0, this.canvas.width, this.canvas.height); }; this.canvas.onmousemove = () => { this.pick(event, this.ctx); } } } 复制代码
前端图片预览、跨域图片问题
还可以取本地或者远程跨域的图片,像这样
demo2
但这里有两个问题:一个是本地图片预览,一个是跨域图片报错。
第一个问题之前有写过一篇文章,可以看这里,这里不赘述了。
注意 第二个问题源于canvas无法对 没有权限的跨域图片 进行操作,如出现跨域,对图片的操作(如getImageData、canvas.toDataURL)会报错: Uncaught DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. 即canvas已经被跨域的数据污染了。
要解决这个问题,就需要图片所在的服务器允许跨域访问(设置消息头 Access-Control-Allow-Origin="*"或者你的网站域名 ),且本地也需要开启跨域权限( img.crossOrigin = "anonymous" )。
由于一般的服务器都是允许跨域的,所以前端只要设置img.crossOrigin = "anonymous"就可以了。
当然,如果服务器设置了图片防盗链的话,我们本地开启了跨域权限也是没有用的。
部分代码:
data () { return { canvas: null, ctx: null, color: null, exterbalUrl: 'http://p8rbt50i2.bkt.clouddn.com/blog/else/miaoWechatIMG241526366731_.pic.jpg' } }, methods: { pick (e, ctx) { let x = e.layerX, y = e.layerY, pixel = ctx.getImageData(x, y, 1, 1), data = pixel.data, rgba = 'rgba(' + data[0] + ',' + data[1] + ',' + data[2] + ',' + (data[3] / 255).toFixed(2) + ')'; this.color.style.background = rgba; this.color.textContent = rgba; }, onFileChange (e) { let file = e.target.files[0], blob = new Blob([file]), // 文件转化成二进制文件 url = URL.createObjectURL(blob); //转化成url let img = new Image(); img.src = url; img.onload = () => { this.draw(img); URL.revokeObjectURL(url); }; }, draw (img) { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height) this.ctx.drawImage(img, 0, 0, this.canvas.width, this.canvas.height); }, onConfirmUrl () { let img = new Image(); //解决跨域问题 img.crossOrigin = 'anonymous'; img.src = this.exterbalUrl; img.onload = () => { this.draw(img); }; } }, mounted () { this.canvas = this.$refs['canvas']; this.ctx = this.canvas.getContext('2d'); this.color = this.$refs['color']; this.onConfirmUrl(); this.canvas.onmousemove = () => { this.pick(event, this.ctx); } } 复制代码
demo3
下面是一个放大镜效果,类似PC端淘宝页面产品预览的效果。这样:
这个效果的实现相当简单,只是直接利用了drawImage的“截取”功能,把左侧截取的50 * 50的画布放大后,重新画在了新的画布上。
部分代码:
const SAMPLE_WIDTH = 50, CANVAS_WIDHT = 300; export default { data () { return { exterbalUrl: 'http://p8rbt50i2.bkt.clouddn.com/blog/else/miaoWechatIMG241526366731_.pic.jpg' } }, methods: { pick (e, ctx) { let x = e.layerX, y = e.layerY; if(x < SAMPLE_WIDTH / 2) { x = SAMPLE_WIDTH / 2; } if(x > CANVAS_WIDHT - SAMPLE_WIDTH / 2) { x = CANVAS_WIDHT - SAMPLE_WIDTH / 2; } if(y < SAMPLE_WIDTH / 2) { y = SAMPLE_WIDTH / 2; } if(y > CANVAS_WIDHT - SAMPLE_WIDTH / 2) { y = CANVAS_WIDHT - SAMPLE_WIDTH / 2; } let x1 = x - SAMPLE_WIDTH / 2, y1 = y - SAMPLE_WIDTH / 2; this.drawCanvas(this.img); this.showMagnifier(x1, y1); this.drawSampleFrame(x1, y1); }, drawSampleFrame (x1, y1) { this.ctx.fillRect(x1, y1, 50, 50); this.ctx.strokeRect(x1, y1, 50, 50); }, onFileChange (e) { let file = e.target.files[0], blob = new Blob([file]), // 文件转化成二进制文件 url = URL.createObjectURL(blob); //转化成url let img = new Image(); img.src = url; img.onload = () => { this.img = img; this.drawCanvas(img); URL.revokeObjectURL(url); }; }, drawCanvas (img) { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); this.ctx.drawImage(img, 0, 0, this.canvas.width, this.canvas.height); }, onConfirmUrl () { let img = new Image(); //解决跨域问题 img.crossOrigin = 'anonymous'; img.src = this.exterbalUrl; img.onload = () => { this.img = img; this.drawCanvas(img); }; }, showMagnifier (x, y) { //重点所在 this.magnifierCtx.drawImage(this.canvas, x, y, SAMPLE_WIDTH, SAMPLE_WIDTH, 0, 0, this.magnifier.width, this.magnifier.height); } }, mounted () { this.canvas = this.$refs['canvas']; this.magnifier = this.$refs['magnifier']; this.ctx = this.canvas.getContext('2d'); this.magnifierCtx = this.magnifier.getContext('2d'); this.ctx.fillStyle = 'rgba(30, 144, 255, .5)'; this.ctx.strokeStyle = '#000'; this.onConfirmUrl(); this.canvas.onmousemove = () => { this.pick(event, this.ctx); } this.canvas.onmouseout = () => { this.magnifierCtx.clearRect(0, 0, this.magnifier.width, this.magnifier.height); this.drawCanvas(this.img); } } } 复制代码
参考资料
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 创业是格局与思维的放大器
- 掌握web开发基础系列--物理像素、逻辑像素、css像素
- 【译】只用 CSS 就能做到的像素画/像素动画
- 透明度叠加算法:如何计算半透明像素叠加到另一个像素上的实际可见像素值(附 WPF 和 HLSL 的实现)
- 开源人工智能算法一种新颖的超像素采样,网络深层特征估计超像素
- WPF 像素着色器入门:使用 Shazzam Shader Editor 编写 HLSL 像素着色器代码
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。