一.drawImage()函数
drawImage() 方法在画布上绘制图像、画布或视频。drawImage() 方法也能够绘制图像的某些部分,以及/或者增加或减少图像的尺寸。
三种用法
context.drawImage(img,x,y); 在画布上定位图像。
context.drawImage(img,x,y,width,height);在画布上定位图像,并规定图像的宽度和高度。
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
传9个参数时,这个函数的意思是从原图像的sx,sy的位置,剪取sw,sh大小的图像,放到canvas画布中dx,dy的位置,现图像的大小为dw宽,dh高。
注意点:我们直接调用drawImage()函数时,将使用图片的原有尺寸,从指定的位置开始,平铺在canvas画布中。当图片尺寸大于canvas画布时,超出的部分将自动隐藏。
二.中心缩放图片
方法一:在原图像的sx,sy位置,选取canvas.width,canvas.height的图像,放置于canvas画布中。
绿颜色的代表原图像,蓝颜色的代表canvas画布。
sx = imageWidth/2 - canvas.width/2;
sy = imageHidth/2 - canvas.height/2;
context.drawImage(image,sx,sy.canvas.width,canvas.height,0,0,canvas.width,canvas.height);
缺点:缩小的时候会出bug。
方法二:每一次都显示整个图像,只不过我们显示整个图像的时候,显示这个图像在左上角的坐标不一样。
绿色为canvas画布,蓝色为要显示的图像。
sx,sy为我们要显示的目的图像在左上角的坐标。
sx = canvas.width - imageWidth/2;
sy = canvas.height - imageHeight/2;
context.drawImage(image,dx,dy,imageWidth,iamgeHeight);
当scale>1时,sx,sy为负,从canvas外面进行显示,画布外面的部分自动隐藏达到放大的效果。
当scale<1时,sx,sy为正,从canvas里面进行显示。
源代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body style="background: black;">
<canvas id="canvas" style="border: 1px solid #000; display: block; margin:0 auto">
您的浏览器不支持canvas画布!
</canvas>
<input type="range" id="scale-range" min="0.5" max="3.0" step="0.01" value="1.0"
style="display: block; margin: 20px auto; width: 800px;">
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var slide = document.getElementById("scale-range");
var image = new Image();
window.onload = function () {
canvas.width = 1152;
canvas.height = 700;
var scale = slide.value;
image.src = "img/img-lg.jpg";
image.onload = function () {
//context.drawImage(image,0,0,canvas.width,canvas.height);
drawImageByScale(scale);
slide.onmousemove = function () {
scale = slide.value;
drawImageByScale(scale);
}
}
};
function drawImageByScale(scale) {
var imageWidth = 1152*scale;
var imageHeight = 700*scale;
x = canvas.width/2 - imageWidth/2;
y = canvas.height/2 - imageHeight/2;
context.clearRect(0,0,canvas.width,canvas.height);
context.drawImage(image,x,y,imageWidth,imageHeight);
}
</script>
</body>
</html>
三.离屏canvas(将第二个canvas中的内容加载到第一个canvas上)
1.给图片加水印
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<canvas id="canvas" style="border: 1px solid #000; display: block; margin: 50px auto">
您的浏览器不支持canvas画布!
</canvas>
<input type="range" id="scale-range" min="0.5" max="3.0" step="0.01" value="1.0"
style="display: block; margin: 20px auto; width:800px">
<canvas id="watermark-canvas" style="display: none; margin: 0 auto;border: 1px solid #aaa;">
您的浏览器不支持canvas画布!
</canvas>
<script>
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var slider = document.getElementById("scale-range");
var watermarkCanvas = document.getElementById("watermark-canvas");
var watermarkContext = watermarkCanvas.getContext("2d");
window.onload = function () {
canvas.width = 1152;
canvas.height = 768;
var image = new Image();
var scale = 1.0;
image.src = "img/img-lg.jpg";
image.onload = function () {
drawImage(image,scale);
slider.onmousemove = function () {
scale = slider.value;
drawImage(image,scale);
}
};
//setup watermark canvas
watermarkCanvas.width = 600;
watermarkCanvas.height = 100;
watermarkContext.font = "bold 50px Arial";
watermarkContext.lineWidth = 1;
watermarkContext.fillStyle = "rgba(255,255,255,0.5)";
watermarkContext.textBaseline = "middle";
watermarkContext.fillText("==AFeng521web.com==",20,50);
};
function drawImage(image,scale) {
imageWidth = 1152*scale;
imageHeight = 768*scale;
x = canvas.width/2 - imageWidth/2;
y = canvas.height/2 - imageHeight/2;
context.clearRect(0,0,canvas.width,canvas.height);
context.drawImage(image,x,y,imageWidth,imageHeight);
//将第二个画布加到第一个画布的右下角
context.drawImage(watermarkCanvas,canvas.width - watermarkCanvas.width,
canvas.height - watermarkCanvas.height)
}
</script>
</body>
</html>
效果图:
2.放大镜
关键点:获取鼠标在canvas中的位置
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body style="background: black">
<canvas id="canvas" style="display: block; margin: 0 auto; border: 1px solid #aaa;">
您的浏览器不支持canvas!
</canvas>
<canvas id="offCanvas" style="display: none;">
</canvas>
<script>
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var offCanvas = document.getElementById("offCanvas");
var offContext = offCanvas.getContext("2d");
var image = new Image();
var isMouseDown = false;
var scale;
window.onload = function () {
canvas.width = 1152;
canvas.height = 768;
image.src = "img/img-lg.jpg";
image.onload = function () {
offCanvas.width = image.width;
offCanvas.height = image.height;
scale = offCanvas.width / canvas.width;
context.drawImage(image,0,0,canvas.width,canvas.height);
offContext.drawImage(image,0,0);
}
};
function windowToCanvas(x,y) {
var bbox = canvas.getBoundingClientRect();
return {
x:x-bbox.left,
y:y-bbox.top
}
}
canvas.onmousedown = function (e) {
e.preventDefault();
isMouseDown = true;
point = windowToCanvas(e.clientX,e.clientY);
console.log(point.x,point.y);
drawCanvasWithMagnifier(true,point)
};
canvas.onmouseup = function(e){
e.preventDefault();
isMouseDown = false;
drawCanvasWithMagnifier( false );
};
canvas.onmouseout = function(e){
e.preventDefault();
isMouseDown = false;
drawCanvasWithMagnifier( false );
};
canvas.onmousemove = function(e){
e.preventDefault();
if( isMouseDown == true ){
point = windowToCanvas( e.clientX , e.clientY );
console.log( point.x , point.y );
drawCanvasWithMagnifier( true , point );
}
};
function drawCanvasWithMagnifier(isShowMagnifier,point) {
context.clearRect(0,0,canvas.width,canvas.height);
context.drawImage(image,0,0,canvas.width,canvas.height);
if(isShowMagnifier == true) {
drawMagnifier(point);
}
}
function drawMagnifier(point) {
var mr = 200;
var imageLG_cx = point.x *scale;
var imageLG_cy = point.y *scale;
var sx = imageLG_cx - mr;
var sy = imageLG_cy - mr;
var dx = point.x - mr;
var dy = point.y - mr;
context.save();
context.lineWidth = 10;
context.strokeStyle = "#069";
context.beginPath();
context.arc(point.x,point.y,mr,0,Math.PI*2,false);
context.stroke();
context.clip();
context.drawImage(offCanvas,sx,sy,2*mr,2*mr,dx,dy,2*mr,2*mr);
context.restore();
}
</script>
</body>
</html>
效果图:
三.滤镜
1.getImageData(x,y,w,h);
x 开始复制的左上角位置的 x 坐标。
y 开始复制的左上角位置的 y 坐标。
width 将要复制的矩形区域的宽度。
height 将要复制的矩形区域的高度。
ImageData = context.getImageData(x,y,w,h);
返回ImageData对象,该对象拷贝了画布指定矩形区域的像素数据,width和height。
data属性返回一个 Uint8ClampedArray,它可以被使用作为查看初始像素数据。每个像素用4个1bytes值(按照红,绿,蓝和透明值的顺序; 这就是”RGBA”格式) 来代表。每个颜色值部份用0至255来代表。每个部份被分配到一个在数组内连续的索引,左上角像素的红色部份在数组的索引0位置。像素从左到右被处理,然后往下,遍历整个数组。
Uint8ClampedArray 包含高度 × 宽度 × 4 bytes数据,索引值从0到(高度×宽度×4)-1。
2.putImageData()方法去对场景进行像素数据的写入。
context.putImageData(imageData,dx,dy,dirtyX,dirtyY,dirtyW,dirtyH);
注意点:离整个canvas的左端为dx+dirtyX;离整个canvas的上端为dy+dirtyY;
3.滤镜制作思想:将原图像中的像素数据通过getImageData(x,y,w,h)得到,然后再通过图像算法进行修改,最后将修改的像素信息通过putImageData()添加进canvas画布中。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div style="margin: 20px auto; width:1700px">
<canvas id="canvasa" width="800" height="560" style="display: block; float: left; border: 1px solid #aaa;">
</canvas>
<canvas id="canvasb" width="800" height="560" style="display: block; float: right; border: 1px solid #aaa;">
</canvas>
</div>
<div style="clear: both;"></div>
<div style="text-align: center; margin-top: 50px; font-size: 20px">
<a href="javascript:greyEffect()">Grey Effect</a>
<a href="javascript:blackEffect()">Black and White Effect</a>
<a href="javascript:reverseEffect()">Reverse Effect</a>
<a href="javascript:blurEffect()">Blur Effect</a>
<a href="javascript:mosaicEffect()">Mosaic Effect</a>
</div>
<script>
var canvasa = document.getElementById("canvasa");
var contexta = canvasa.getContext("2d");
var canvasb = document.getElementById("canvasb");
var contextb = canvasb.getContext("2d");
var image = new Image();
window.onload = function () {
image.src = "img/autumn.jpg";
image.onload = function () {
contexta.drawImage(image,0,0,canvasa.width,canvasa.height);
}
};
function greyEffect() {
var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);
var pixeldata = imageData.data;
for(var i=0; i<canvasb.width*canvasb.height; i++) {
var r = pixeldata[i*4+0];
var g = pixeldata[i*4+1];
var b = pixeldata[i*4+2];
var grey = r*0.3+g*0.59+b*0.11;
pixeldata[i*4+0] = grey;
pixeldata[i*4+1] = grey;
pixeldata[i*4+2] = grey;
}
contextb.putImageData(imageData,0,0,0,0,canvasb.width,canvasb.height);
//context.putImageData();
}
function blackEffect() {
var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);
var pixelData = imageData.data;
for(var i=0; i<canvasb.width*canvasb.height; i++) {
var r = pixelData[i*4+0];
var g = pixelData[i*4+1];
var b = pixelData[i*4+2];
var grey = r*0.3+g*0.59+b*0.11;
if(grey > 125) {
pv = 255;
}
else {
pv = 0;
}
pixelData[i*4+0] = pv;
pixelData[i*4+1] = pv;
pixelData[i*4+2] = pv;
}
contextb.putImageData(imageData,0,0,0,0,canvasa.width,canvasa.height);
}
function reverseEffect() {
var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);
var pixelData = imageData.data;
for(var i=0; i<canvasb.width*canvasb.height; i++) {
var r = pixelData[i*4+0];
var g = pixelData[i*4+1];
var b = pixelData[i*4+2];
pixelData[i*4+0] = 255-r;
pixelData[i*4+1] = 255-g;
pixelData[i*4+2] = 255-b;
}
contextb.putImageData(imageData,0,0,0,0,canvasb.width,canvasb.height);
}
function blurEffect() {
var tempImageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);
var tempPixelData = tempImageData.data;
var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);
var pixelData = imageData.data;
var blurR = 3;
var totalnum = (2*blurR+1)*(2*blurR+1);
for(var i=blurR; i<canvasb.height-blurR; i++) {
for(var j=blurR; j<canvasb.width-blurR; j++) {
var totalr = 0, totalg = 0, totalb = 0;
for(var dx = -blurR; dx <= blurR; dx++) {
for(var dy = -blurR; dy<=blurR; dy++) {
var x = i + dx;
var y = j + dy;
var p = x*canvasb.width + y;
totalr += tempPixelData[p*4+0];
totalg += tempPixelData[p*4+1];
totalb += tempPixelData[p*4+2];
}
}
var p = i*canvasb.width + j;
pixelData[p*4+0] = totalr/totalnum;
pixelData[p*4+1] = totalg/totalnum;
pixelData[p*4+2] = totalb/totalnum;
}
}
contextb.putImageData(imageData,0,0,0,0,canvasb.width,canvasb.height)
}
function mosaicEffect(){
var tmpImageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
var tmpPixelData = tmpImageData.data
var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
var pixelData = imageData.data
var size = 16
var totalnum = size*size
for( var i = 0 ; i < canvasb.height ; i += size )
for( var j = 0 ; j < canvasb.width ; j += size ){
var totalr = 0 , totalg = 0 , totalb = 0
for( var dx = 0 ; dx < size ; dx ++ )
for( var dy = 0 ; dy < size ; dy ++ ){
var x = i + dx
var y = j + dy
var p = x*canvasb.width + y
totalr += tmpPixelData[p*4+0]
totalg += tmpPixelData[p*4+1]
totalb += tmpPixelData[p*4+2]
}
var p = i*canvasb.width+j
var resr = totalr / totalnum
var resg = totalg / totalnum
var resb = totalb / totalnum
for( var dx = 0 ; dx < size ; dx ++ )
for( var dy = 0 ; dy < size ; dy ++ ){
var x = i + dx
var y = j + dy
var p = x*canvasb.width + y
pixelData[p*4+0] = resr
pixelData[p*4+1] = resg
pixelData[p*4+2] = resb
}
}
contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width, canvasb.height )
}
</script>
</body>
</html>