第一个对象可以使image,canvas,video等其他对象
drawImage的第一个参数不一定就是image,也可以是一个canvas
也就是说我们可以给一个canvas中放图片或者绘图,然后再用drawImage将它画出来
dx,dy表示绘制图片的起始坐标
加入dw,dy的时候,会自动帮我们进行图片缩放,也就是将图片以dw,dy的大小进行显示
这里跟上两个的区别就是,上两个是对目标画布进行绘制图像,而这种方式是讲原图像的某一块会知道目标画布的某一块
即将image/canvas原图像,从sx,sy开始截取sw,sh的大小到context所代表的画布的dx,dy位置,显示为dw,dh的大小
demo01–drawImage实现图片在canvas中心缩放
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body style="">
<canvas id='canvas' style="border:1px solid #aaa;margin:50px auto;display:block;">
您的浏览器尚不支持canvas,请更换浏览器尝试
</canvas>
<!--滑动杆-->
<input type="range" id='scaleRange' name="" min='0.5' max='3' step='0.01' value='1.0' style="display:block;margin:20px auto;width:800px;">
<script type="text/javascript"> var canvas = document.getElementById('canvas'); canvas.width = 1050; canvas.height = 800; var context = canvas.getContext('2d'); </script>
<script type="text/javascript"> var image = new Image(); var imageWidth_origin,imageHeight_origin; var slider = document.getElementById('scaleRange'); var scale = slider.value; window.onload = function(){ image.src = '../../images/detail-img.png'; image.onload = function(){ //context.drawImage(image,0,0,canvas.width,canvas.height); imageWidth_origin = image.width; imageHeight_origin = image.height; console.log(imageWidth_origin+"----"+imageHeight_origin) drawImageByScale(scale); slider.onmousemove = function(){ scale = slider.value; drawImageByScale(scale); }; }; }; //绘制图像 /** * 原理: * * 图片可以放大,可以缩小,所以我们使用drawImage的第二种方法context.drawImage(image,dx,dy,dw,dh) * * 这里dx,dy可以是负值,也可以是正数, * 1.图片是被放大的,那么图片比画布大,我们可以让dx,dy为负数,dw,dy为放大后image的宽和高、 * 这样从画布的外面进行绘制,那么在画布区域的地方就是我们需要放大的地方 * 2.图片是被缩小的,那么图片比画布小,dx,dy为正数,就是从画布的里面绘制,dw,dy为缩小后图片的宽和高, * 这样在画布里面显示的就是缩小的图片 */ function drawImageByScale(scale){ context.clearRect(0,0,canvas.width,canvas.height); var imageWidth = imageWidth_origin * scale, imageHeight = imageHeight_origin * scale; var dx = canvas.width / 2 - imageWidth / 2; var dy = canvas.height / 2 - imageHeight / 2; context.drawImage(image,dx,dy,imageWidth,imageHeight); } </script>
</body>
</html>
demo02–离屏技术:给图片添加水印
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body style="background-color:black;">
<canvas id='canvas' style="border:1px solid #aaa;margin:50px auto;display:block;">
您的浏览器尚不支持canvas,请更换浏览器尝试
</canvas>
<!--滑动杆-->
<input type="range" id='scaleRange' name="" min='0.5' max='3' step='0.01' value='1.0' style="display:block;margin:20px auto;width:800px;">
<!--添加水印的canvas画布-->
<canvas id='webmarket_canvas' style="border:1px solid #aaa;margin:50px auto;display:none;">
您的浏览器尚不支持canvas,请更换浏览器尝试
</canvas>
<script type="text/javascript"> var canvas = document.getElementById('canvas'); canvas.width = 1200; canvas.height = 800; var context = canvas.getContext('2d'); //水印画布 var webmarket_canvas = document.getElementById('webmarket_canvas'); webmarket_canvas.width = 400; webmarket_canvas.height = 100; var webmarket_context = webmarket_canvas.getContext('2d'); webmarket_context.font='bold 50px Arial'; webmarket_context.fillStyle = 'rgba(255,255,255,0.5)'; webmarket_context.textBaseLine = 'middle'; webmarket_context.fillText('== heyan ==',20,50); </script>
<script type="text/javascript"> var image = new Image(); var imageWidth_origin,imageHeight_origin; var slider = document.getElementById('scaleRange'); var scale = slider.value; window.onload = function(){ image.src = '../../images/banner_cogobuy_750_444.png'; image.onload = function(){ //context.drawImage(image,0,0,canvas.width,canvas.height); imageWidth_origin = image.width; imageHeight_origin = image.height; drawImageByScale(scale); slider.onmousemove = function(){ scale = slider.value; drawImageByScale(scale); }; }; }; //绘制图像 /** * 原理: * * 图片可以放大,可以缩小,所以我们使用drawImage的第二种方法context.drawImage(image,dx,dy,dw,dh) * * 这里dx,dy可以是负值,也可以是正数, * 1.图片是被放大的,那么图片比画布大,我们可以让dx,dy为负数,dw,dy为放大后image的宽和高、 * 这样从画布的外面进行绘制,那么在画布区域的地方就是我们需要放大的地方 * 2.图片是被缩小的,那么图片比画布小,dx,dy为正数,就是从画布的里面绘制,dw,dy为缩小后图片的宽和高, * 这样在画布里面显示的就是缩小的图片 */ function drawImageByScale(scale){ context.clearRect(0,0,canvas.width,canvas.height); var imageWidth = imageWidth_origin * scale, imageHeight = imageHeight_origin * scale; var dx = canvas.width / 2 - imageWidth / 2; var dy = canvas.height / 2 - imageHeight / 2; context.drawImage(image,dx,dy,imageWidth,imageHeight); /** * 绘制图片完成之后,把自定义的水印画布绘制上去 * * 而且此时在图片放大缩小时,水印一直保持在原来的位置 */ context.drawImage(webmarket_canvas,canvas.width - webmarket_canvas.width, canvas.height - webmarket_canvas.height); } </script>
</body>
</html>
var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);//获取canvasa中的所有元素
//获取图像中所有的像素信息,实现修改像素信息,滤镜效果
var pexelData = imageData.data;
/** * 1.在像素信息中,如果以一维数组来说图片像素的话 * 那么在canvas画布中就有canvas.width * canvas.height个像素 * 以4个位一组,分别代表r,g,b,a四个通道 * 第i个像素 * r--pexelData[4*i+0] * g--pexelData[4*i+1] * b--pexelData[4*i+2] * a--pexelData[4*i+3] * * 2.在像素信息中,以二位数组来说该图片的像素的话 * * 以4个位一组,分别代表r,g,b,a四个通道 * * 比如:第x行第y列的像素的四个通道的值反别是 * i = x * width + y * r--pexelData[4*i+0] * g--pexelData[4*i+1] * b--pexelData[4*i+2] * a--pexelData[4*i+3] */
下面是一个滤镜效果的demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvas drawImage绘图</title>
</head>
<body>
<div>
<canvas id='canvasa' style="border:1px solid #aaa;">
您的浏览器尚不支持canvas,请更换浏览器尝试
</canvas>
<canvas id='canvasb' style="border:1px solid #aaa; margin-left:100px;">
您的浏览器尚不支持canvas,请更换浏览器尝试
</canvas>
</div>
<div style="text-align:center;margin-top:50px;font-size:20px">
<a href="javascript:void(0)" onclick="filter()">测试</a>
<a href="javascript:void(0)" onclick="greyEffect()">灰度滤镜</a>
<a href="javascript:void(0)" onclick="blackEffect()">黑白滤镜</a>
<a href="javascript:void(0)" onclick="reverseEffect()">反色滤镜</a>
<a href="javascript:void(0)" onclick="blurEffect()">模糊滤镜</a>
<a href="javascript:void(0)" onclick="mosaicEffect()">马赛克滤镜</a>
</div>
<script type="text/javascript"> var canvasa = document.getElementById('canvasa'); var contexta = canvasa.getContext('2d'); var canvasb = document.getElementById('canvasb'); var contextb = canvasb.getContext('2d'); canvasa.width = canvasb.width = 800; canvasa.height = canvasa.height = 800; </script>
<script type="text/javascript"> /*获取和设置图像像素*/ /** * context.getImageData(x,y,w,h) * context.putImageData(imageData,dx,dy,dirtyX,dirtyY,dirthW,dirthH); * 讲canvasa中的图片经过图形算法之后会知道canvasb的画布上 */ var image = new Image(); window.onload = function(){ image.src = '../images/detail-img.png'; image.onload = function(){ canvasa.width = canvasb.width = image.width; canvasa.height = canvasb.height = image.height; contexta.drawImage(image,0,0,canvasa.width,canvasa.height); }; } function filter(){ var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);//获取canvasa中的所有元素 //获取图像中所有的像素信息,实现修改像素信息,滤镜效果 var pexelData = imageData.data; /** * 1.在像素信息中,如果以一维数组来说图片像素的话 * 那么在canvas画布中就有canvas.width * canvas.height个像素 * 以4个位一组,分别代表r,g,b,a四个通道 * 第i个像素 * r--pexelData[4*i+0] * g--pexelData[4*i+1] * b--pexelData[4*i+2] * a--pexelData[4*i+3] * * 2.在像素信息中,以二位数组来说该图片的像素的话 * * 以4个位一组,分别代表r,g,b,a四个通道 * * 比如:第x行第y列的像素的四个通道的值反别是 * i = x * width + y * r--pexelData[4*i+0] * g--pexelData[4*i+1] * b--pexelData[4*i+2] * a--pexelData[4*i+3] */ //下面以以为数组为例 /*for(var i = 0;i < canvasa.width * canvasa.height;i++){ pexelData[4*i+0] = 0;//修改R通道 pexelData[4*i+1] = 0;//修改G通道 pexelData[4*i+2] = 0;//修改B通道 }*/ //下面以二位数组为例 for(var i = 0;i < canvasa.height;i++){ for(var j = 0;j < canvasa.width ; j++){ var index = i * canvasa.width + j; // pexelData[4*index+0] = 0; // pexelData[4*index+1] = 0; pexelData[4*index+2] = 0; } } contextb.putImageData(imageData,0,0,0,0,canvasb.width,canvasb.height); } </script>
<script type="text/javascript"> /*灰度滤镜*/ /** * 灰度滤镜系数:grey = r*0.3 + g*0.59 + b*0.11 */ function greyEffect(){ var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);//获取canvasa中的所有元素 var pexelData = imageData.data; for(var i = 0;i < canvasa.width * canvasa.height;i++){ var r = pexelData[4*i+0]; var g = pexelData[4*i+1]; var b = pexelData[4*i+2]; var grey = r*0.3 + g*0.59 + b*0.11; pexelData[4*i+0] = grey; pexelData[4*i+1] = grey; pexelData[4*i+2] = grey; } contextb.putImageData(imageData,0,0,0,0,canvasb.width,canvasb.height); } </script>
<script type="text/javascript"> /*黑白滤镜*/ /** * 原理:对灰度滤镜系数算出来的值进行判断,如果比255/2大的话,就设为白色,否则设为黑色 */ function blackEffect(){ var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);//获取canvasa中的所有元素 var pexelData = imageData.data; for(var i = 0;i < canvasa.width * canvasa.height;i++){ var r = pexelData[4*i+0]; var g = pexelData[4*i+1]; var b = pexelData[4*i+2]; var grey = r*0.3 + g*0.59 + b*0.11; var v; if(grey > 255/2){ v = 255; }else{ v = 0; } pexelData[4*i+0] = v; pexelData[4*i+1] = v; pexelData[4*i+2] = v; } contextb.putImageData(imageData,0,0,0,0,canvasb.width,canvasb.height); } </script>
<script type="text/javascript"> /*反色滤镜*/ /** * 原理:在原有的像素值下面,使用255减去原来的像素值,然后把结果再赋给该像素 */ function reverseEffect(){ var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);//获取canvasa中的所有元素 var pexelData = imageData.data; for(var i = 0;i < canvasa.width * canvasa.height;i++){ var r = pexelData[4*i+0]; var g = pexelData[4*i+1]; var b = pexelData[4*i+2]; pexelData[4*i+0] = 255 - r; pexelData[4*i+1] = 255 - g; pexelData[4*i+2] = 255 - b; } contextb.putImageData(imageData,0,0,0,0,canvasb.width,canvasb.height); } </script>
<script type="text/javascript"> /*模糊滤镜*/ /** * 原理:使用扫描到每一个像素点时,需要参考周围的像素点的值, * 那么周围的像素点就不能被算法所修改, * 所以我们需要创建一份相同的imageData来保存原有的像素信息,然后作为参考对象 * * * 本例中我们拿到该像素点周围的8个像素点以及本身共9个像素点, * 然后计算平均值赋给该像素点 * */ function blurEffect(){ //参考信息 var tempImageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);//获取canvasa中的所有元素 var tempPexelData = tempImageData.data; var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);//获取canvasa中的所有元素 var pexelData = imageData.data; var blurR = 3;//模糊半径 //计算总共参考了多少点 var totalNum = (2*blurR + 1) * (2*blurR + 1); //这里以二位数组进行循环 for(var i = blurR;i < canvasa.height -blurR;i++){ for(var j = blurR;j < canvasa.width -blurR ; j++){ //各个通道的值 var totalr = 0,totalg = 0,totalb = 0; //拿到该点周围的8个点,那么为防止数组越界,将i改为1 for(var dx = -blurR; dx<=blurR ; dx++){ for(var dy = -blurR; dy <= blurR; dy++){ //得到这8个点的坐标 var x = i + dx, y = j + dy; var p = x * canvasa.width + y; totalr += tempPexelData[4*p+0]; totalg += tempPexelData[4*p+1]; totalb += tempPexelData[4*p+2]; } } var index = i * canvasa.width +j; pexelData[4*index+0] = totalr/totalNum; pexelData[4*index+1] = totalg/totalNum; pexelData[4*index+2] = totalb/totalNum; } } contextb.putImageData(imageData,0,0,0,0,canvasb.width,canvasb.height); } </script>
<script type="text/javascript"> /*马赛克滤镜*/ /** * 原理:跟模糊滤镜不同的是 * 模糊滤镜是拿到周围的一块的平均值赋给当前像素点 * 马赛克则是把一块里面的所有值全部附上着一块的平均值 */ function mosaicEffect(){ //参考信息 var tempImageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);//获取canvasa中的所有元素 var tempPexelData = tempImageData.data; var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height);//获取canvasa中的所有元素 var pexelData = imageData.data; //定义每一个马赛克块的边长,这里需要计算为长可宽的最小公约数,即都能被该数整除 var size = 16; //计算总共参考了多少点 var totalNum = size*size; //这里以二位数组进行循环,每次循环一个马赛克块 for(var i = 0 ; i < canvasa.height ; i+= size){ for(var j = 0;j < canvasa.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, y = j + dy; var p = x * canvasa.width + y; totalr += tempPexelData[4*p+0]; totalg += tempPexelData[4*p+1]; totalb += tempPexelData[4*p+2]; } } var index = i * canvasa.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, y = j + dy; var p = x * canvasa.width + y; pexelData[4*p+0] = resr; pexelData[4*p+1] = resg; pexelData[4*p+2] = resb; } } } } contextb.putImageData(imageData,0,0,0,0,canvasb.width,canvasb.height); } </script>
</body>
</html>