canvas像素点获取 —— 拾色器、放大器

栏目: Html5 · 发布时间: 7年前

内容简介:最近在学习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 属性中。

这个样子:

canvas像素点获取 —— 拾色器、放大器

先来一下demo,通过getImageData方法获取鼠标指针处的像素值。

demo1

canvas像素点获取 —— 拾色器、放大器

部分代码:

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像素点获取 —— 拾色器、放大器

但这里有两个问题:一个是本地图片预览,一个是跨域图片报错。

第一个问题之前有写过一篇文章,可以看这里,这里不赘述了。

注意 第二个问题源于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端淘宝页面产品预览的效果。这样:

canvas像素点获取 —— 拾色器、放大器

这个效果的实现相当简单,只是直接利用了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);
		}
	}
}
复制代码

另一篇: canvas像素点操作 —— 视频绿幕抠图

参考资料


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Creative Selection

Creative Selection

Ken Kocienda / St. Martin's Press / 2018-9-4 / USD 28.99

Hundreds of millions of people use Apple products every day; several thousand work on Apple's campus in Cupertino, California; but only a handful sit at the drawing board. Creative Selection recounts ......一起来看看 《Creative Selection》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

html转js在线工具
html转js在线工具

html转js在线工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具