canvas基础学习(二)

一、图像绘制

canvas绘制图像的方法是ctx.drawImage();该方法有三种使用方式

1、ctx.drawImage(img,x,y);

img是指图像对象,x和y分别是这个图像左上角在canvas画布的坐标,而图像显示的大小为图像本身的像素值,超出canvas画布的部分不显示。

2、ctx.drawImage(img,x,y,w,h);

和上面的那个函数相比,可以控制图像在canvas中显示的宽度和高度,而不再是图片自身的高宽像素

3、ctx.drawImage(img , dx , dy , dw , dh , x , y , w , h);

这个又比之前的函数多了dx、dy、dw、dh这四个参数,这四个参数可以控制图片切片显示在canvas画布中。在图片上同样以左上角为原点,向右为X轴正方向,向下为Y轴正方向,这四个参数表示,在图片中在(dx,dy)这个坐标,切dw和dh大小的切片。然后将这个切片显示在canvas画布上。

最后这个img参数,不单单可以是Image对象,还可以是video对象,也可以是另外的canvas对象。所以可以通过该方法对video视频进行截屏,也可以通过加载canvas制作图像水印、放大镜、以及淘宝双11主会场那样的特效,一个canvas加载另一个canvas,也被称为canvas的离屏技术。

二、图像的像素级处理

1、ctx.getImageData(x , y , w , h);

这个方法是获取画布(x,y)坐标,宽高分别为w和h的像素对象。而这个对象的data属性,则是其rgba的值。一个画布的像素值是从画布的原点,从左向右,从上到下,一排一排的排列下来的。常用取出canvas像素值的方法有两种,一种是采用一层循环,另一种是采用双重for循环,代码如下:

var imageData = ctx.getImageData(0 , 0 , canvasW , canvasH),
      pixelData = imageData.data;
//方式一
for(var i = 0; i < canvasH*canvasW ; i++){
    var  r = pixelData[4*i + 0],
          g = pixelData[4*i + 1],
          b = pixelData[4*i + 2],
              a = pixelData[4*i + 3];
}
//方式二
for(var y = 0 ; i < canvasH  ; y++){
   for(var x = 0 ; x < canvasW ; x++){
      var pixe = canvasW*y + x,
          r = pixelData[4*pixe + 0],
          g = pixelData[4*pixe + 1],
          b = pixelData[4*pixe + 2],
          a = pixelData[4*pixe + 3];
    }
}

2、ctx.putImageData()

该方法是设置canvas画布上的像素数据,它有七个参数,在w3c上是这么解释的

我的理解就是将imgData,放在画布上的位置是(x + dirtyX , y + dirtyY),高宽分别是dirtyHeight、dirtyWidth的矩形。

三、代码demo

1、图片缩放,以及像素变换

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>图像学习</title>
        <style>
            #main,#copy,.contain{
                margin: 15px;
                padding: 0;
                float: left;

            }
            #main{
                cursor:move
            }
            .contain *{
                padding: 2px;
                margin: 0;
z            }
            .contain a{
                display: block;
                text-align: center;
                margin-top:5px;
                font-size:15px;
                line-height: 20px;
            }
        </style>
    </head>
    <body>
        <canvas id="main" width="400" height="300" style="display:block;border: 1px solid #AAA;">
            亲,您的浏览器不支持canvas
        </canvas>
        <div class="contain" style="width: 290px;height: 300px;">
            <div>
                <span>缩放</span>
                <input type="range" id="scaleChange" min="0.5" max="4.0" step="0.03" value="1.0"
                    style="display:inline-block;width: 240px;"/>
            </div>
            <a href="javascript:void(0)" id="greyChange">灰度转换</a>
            <a href="javascript:void(0)" id="blackChange">黑度转换</a>
            <a href="javascript:void(0)" id="reverChange">反相转换</a>
            <a href="javascript:void(0)" id="blurChange">模糊处理</a>
            <a href="javascript:void(0)" id="mosaicChange">马赛克处理</a>
        </div>
        <canvas id="copy" width="400" height="300" style="display:block;border: 1px solid #AAA;">
            亲,您的浏览器不支持canvas
        </canvas>
        <canvas id="waterMark" style="display: none;">
              亲,您的浏览器不支持canvas
              <!--
                      水印作图的canvas,把一个canvas载入另一个canvas的做法叫做,离屏canvas
              -->
        </canvas>
    </body>
    <script>
        document.body.onload = function(){
            var canvas = document.getElementById("main"),
                scaleChange = document.getElementById("scaleChange"),
                copyCanvas = document.getElementById("copy"),
                waterMarkCanvas = document.getElementById("waterMark"),
                ctx = canvas.getContext("2d"),
                copyCtx = copyCanvas.getContext("2d"),
                canvasW = canvas.width,
                canvasH = canvas.height;
            var img = new Image();
            img.src = "img.jpg";
            img.onload = function(){        //当图片加载完毕后,执行canvas画图函数
                init();
            }
            //用于初始化
            function init(){
                toolFunc.handleWaterMark();
                toolFunc.handleScale();
                toolFunc.drawImg();
                toolFunc.handleEffect();
                toolFunc.handleCanvasMove();
            }
            var toolFunc = {
                scaleImgX : 0,
                scaleImgY : 0,
                drawImg : function(moveX , moveY){    //绘制图片
                    var scale = scaleChange.value;
                        //根据比例计算缩放后图像的大小
                        var imgW = canvasW*scale,
                            imgH = canvasH*scale,
                            x = (canvasW - imgW)/2,
                            y = (canvasH - imgH)/2,
                            tempX = x , tempY = y;
                        if(moveX || moveY){
                            x = this.scaleImgX + moveX;
                            y = this.scaleImgY + moveY;
                            if(x >= 0 || y >= 0 || x <= 2*tempX || y <= 2*tempY){
                                return;
                            }
                        }
                        ctx.clearRect(0 , 0 , canvasW , canvasH);
                        ctx.drawImage(img , x , y , imgW , imgH);
                        ctx.drawImage(waterMarkCanvas ,
                            canvasW - waterMarkCanvas.width ,
                            canvasH - waterMarkCanvas.height ,
                            waterMarkCanvas.width , waterMarkCanvas.height);
                        this.scaleImgX = x;
                        this.scaleImgY = y;
                },
                handleWaterMark : function(){        //用于处理水印
                    waterMarkCanvas.width = 200;
                    waterMarkCanvas.height = 70;
                    var waterCtx = waterMarkCanvas.getContext("2d");
                    waterCtx.font = "bold 20px Arial";
                    waterCtx.lineWidth = 1;
                    waterCtx.fillStyle = "white";
                    waterCtx.textAlign = "center";
                    waterCtx.textBaseline = "middle";
                    waterCtx.fillText( "~!~ sky ~!~" , 140 , 50 , waterMarkCanvas.width);
                },
                handleScale : function(){        //用于处理缩放
                    var isScale = false,
                        _this = this;
                    scaleChange.onmousedown = function(){
                        isScale = true;
                    }
                    scaleChange.onmousemove = function(){
                        if(isScale){        //画图
                            _this.drawImg();
                        }
                    }
                    scaleChange.onmouseup = function(){
                        isScale = false;
                    }
                },
                handleEffect : function(){    //处理效果变换
                    var imageData,pixelData;
                    document.getElementById("greyChange").onclick = function(){        //灰度变换
                        imageData = ctx.getImageData(0 , 0 , canvasW , canvasH);
                        pixelData = imageData.data;
                        for(var i = 0; i < canvasH*canvasW ; i++){
                            var r = pixelData[4*i + 0],
                                g = pixelData[4*i + 1],
                                b = pixelData[4*i + 2],
                                grey = r*0.3+g*0.59+b*0.11;//此为灰度图像的算法
                            pixelData[4*i + 0] = grey;
                            pixelData[4*i + 1] = grey;
                            pixelData[4*i + 2] = grey;
                        }
                        copyCtx.putImageData(imageData,0,0,0,0,canvasW,canvasH);
                    }
                    document.getElementById("blackChange").onclick = function(){        //黑度变换
                        imageData = ctx.getImageData(0 , 0 , canvasW , canvasH);
                        pixelData = imageData.data;
                        for(var i = 0; i < canvasH*canvasW ; i++){
                            var r = pixelData[4*i + 0],
                                g = pixelData[4*i + 1],
                                b = pixelData[4*i + 2],
                                grey = (function(n){        //黑度图像就只有黑白两色
                                    if(n > 127){
                                        return 255;
                                    }else{
                                        return 0;
                                    }
                                })(r*0.3+g*0.59+b*0.11);
                            pixelData[4*i + 0] = grey;
                            pixelData[4*i + 1] = grey;
                            pixelData[4*i + 2] = grey;
                        }
                        copyCtx.putImageData(imageData,0,0,0,0,canvasW,canvasH);
                    }
                    document.getElementById("reverChange").onclick = function(){        //反向变换
                        imageData = ctx.getImageData(0 , 0 , canvasW , canvasH);
                        pixelData = imageData.data;
                        for(var i = 0; i < canvasH*canvasW ; i++){
                            var r = pixelData[4*i + 0],
                                g = pixelData[4*i + 1],
                                b = pixelData[4*i + 2];
                            pixelData[4*i + 0] = 255 - r;
                            pixelData[4*i + 1] = 255 - g;
                            pixelData[4*i + 2] = 255 - b;
                        }
                        copyCtx.putImageData(imageData,0,0,0,0,canvasW,canvasH);
                    }
                    document.getElementById("blurChange").onclick = function(){        //模糊处理
                        imageData = ctx.getImageData(0 , 0 , canvasW , canvasH);
                        pixelData = imageData.data;
                        var pixelTmpData = pixelData;    //作为一个备份数据
                        var r = 3 , totalNum = (2*r + 1)*(2*r + 1);    //去上下左右四个方向各3个像素点的平均值
                        for(var i = r ; i < canvasH - r ; i++){
                            for(var j = r ; j < canvasW - r; j++){
                                var totalR,totalG,totalB;
                                totalR = totalG = totalB = 0;
                                for(var m = -r ; m <= r ; m++){
                                    for(var n = -r ; n <= r ; n++){
                                        var pixeY = i + m , piexX = j + n,
                                            pixe = canvasW*pixeY + piexX;
                                        totalR += pixelTmpData[4*pixe + 0];
                                        totalG += pixelTmpData[4*pixe + 1];
                                        totalB += pixelTmpData[4*pixe + 2];
                                    }
                                }
                                var p = i*canvasW + j;
                                pixelData[4*p + 0] = totalR/totalNum;
                                pixelData[4*p + 1] = totalG/totalNum;
                                pixelData[4*p + 2] = totalB/totalNum;
                            }
                        }
                        copyCtx.putImageData(imageData,0,0,0,0,canvasW,canvasH);
                    }
                    document.getElementById("mosaicChange").onclick = function(){    //马赛克处理
                        imageData = ctx.getImageData(0 , 0 , canvasW , canvasH);
                        pixelData = imageData.data;
                        var pixelTmpData = pixelData;    //作为一个备份数据
                        var size = 8,total = size*size;
                        for(var i = 0 ; i < canvasH ; i += size){
                            for( var j = 0 ; j < canvasW ; j += size){
                                var totalR,totalG,totalB;
                                totalR = totalG = totalB = 0;
                                for(var y = 0 ; y < size ; y++){
                                    for(var x = 0 ; x < size ; x++){
                                        var py = i + y,
                                            px = j + x,
                                            pixe = px + py*canvasW;
                                        totalR += pixelTmpData[4*pixe + 0];
                                        totalG += pixelTmpData[4*pixe + 1];
                                        totalB += pixelTmpData[4*pixe + 2];
                                    }
                                }
                                var newR = totalR/total,
                                    newG = totalG/total,
                                    newB = totalB/total;
                                for(var dy = 0 ; dy < size ; dy++){
                                    for(var dx = 0 ; dx < size ; dx++ ){
                                        var py = i + dy,
                                            px = j + dx,
                                            pixe = px + py*canvasW;
                                        pixelData[4*pixe + 0] = newR;
                                        pixelData[4*pixe + 1] = newG;
                                        pixelData[4*pixe + 2] = newB;
                                    }
                                }
                            }
                        }
                        copyCtx.putImageData(imageData,0,0,0,0,canvasW,canvasH);
                    }

                },
                handleCanvasMove:function(){        //处理canvans移动
                    var isCanvasMove = false,
                        lastX,lastY;
                    canvas.onmousedown = function(e){
                        e.preventDefault();
                        isCanvasMove = true;
                        lastX = e.clientX - canvas.getBoundingClientRect().left;
                        lastY = e.clientY - canvas.getBoundingClientRect().top;
                    }
                    canvas.onmousemove = function(e){
                        e.preventDefault();
                        if(!isCanvasMove || scaleChange.value <= 1) return;
                        var x = e.clientX - canvas.getBoundingClientRect().left,
                            y = e.clientY - canvas.getBoundingClientRect().top;
                        var moveX = (x - lastX),
                            moveY = (y - lastY);
                        toolFunc.drawImg(moveX,moveY);
                        lastX = x;
                        lastY = y;
                    }
                    canvas.onmouseup = function(e){
                        e.preventDefault();
                        isCanvasMove = false;
                    }
                    canvas.onmouseout = function(e){
                        e.preventDefault();
                        isCanvasMove = false;
                    }
                }
            };
        }
    </script>
</html>

效果图为

用的图片是

2、图片放大镜

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>canvas放大镜</title>
        <style type="text/css">
            *{
                margin: 0;
                padding: 0;
            }
        </style>
    </head>
    <body>
        <canvas id="main" width="800" height="600"
            style="display: block;margin: 0 auto;border: 1px solid #AAA;">
            亲,您的浏览器不支持canvas
        </canvas>
        <canvas id="magnify" width="200" height="200" style="display: none;"></canvas>
        <script>
            var canvas = document.getElementById("main"),
                ctx = canvas.getContext("2d"),
                canvasW = canvas.width,
                canvasH = canvas.height,
                magnifyCanvas = document.getElementById("magnify"),
                mCtx = magnifyCanvas.getContext("2d"),
                magnifyR = 100;
            var img = new Image();
            img.src = "magnify.jpg";
            img.onload = function(){
                ctx.drawImage(this , 0 , 0 , canvasW , canvasH);
                handleEvent();
            }
            function handleEvent(){
                var isShow = false;
                canvas.onmousedown = function(e){
                    e.preventDefault();
                    draw(e);
                }
                canvas.onmouseup = function(e){
                    e.preventDefault();
                    draw(e);
                }
                canvas.onmousemove = function(e){
                    e.preventDefault();
                    if(!isShow) return;
                    draw(e);
                }
                canvas.onmouseout = function(e){
                    e.preventDefault();
                    draw(e);
                }

                function draw(event){
                    isShow = (event.type == "mousedown" || event.type == "mousemove");
                    ctx.clearRect(0 , 0 , canvas.width , canvas.height);
                    ctx.drawImage(img , 0 , 0 , canvasW , canvasH);
                    if(!isShow) return;
                    var x = event.clientX - canvas.getBoundingClientRect().left,
                        y = event.clientY - canvas.getBoundingClientRect().top;
                    mCtx.save();
                    mCtx.lineWidth = 3;
                    mCtx.strokeStyle = "skyblue";
                    mCtx.beginPath();
                    mCtx.arc(100,100,90,0,Math.PI*2);
                    mCtx.stroke();
                    mCtx.clip();
                    mCtx.drawImage(img , 2*x - 90 , 2*y - 90 ,
                            180 , 180,
                            0 , 0 , magnifyCanvas.width, magnifyCanvas.height);
                    mCtx.closePath();
                    mCtx.restore();
                    ctx.drawImage(magnifyCanvas, (x-(magnifyCanvas.width/2)) , (y-(magnifyCanvas.height/2)) ,
                        magnifyCanvas.width , magnifyCanvas.height);
                }
            }

        </script>
    </body>
</html>

用的图片是

时间: 2024-10-01 22:32:18

canvas基础学习(二)的相关文章

puppet基础学习(二)

puppet基础学习(二) 六.ResourceOrdering(资源定序) 使用变化参数before , require , notify , subscribe catalog是对一个给定的系统的所有资源及关系的编译,在编译catalog时,除非我们指定资源的执行顺序,不然puppet是以其自己的顺序管理,大多数时候puppet指定适当的方式,例如puppet管理用户gigabyte应该存在和文件夹/home/gigabyte/bin应该存在并属于用户gigabyte时,puppet会自动指

五分钟学会 Canvas 基础(二)

0. 前言 相信各位小伙伴读了之前的文章,对 Canvas 基础已经有了一定的认识和了解,但是大家也一定记得我在上一篇文章留了一个小的坑. 就是我没有告诉大家该如何去绘制圆,之所以没有说是因为绘制圆实际上是因为 CanvasRenderingContext2D 对象只提供了两个绘制矩形的方法,并没有直接提供绘制圆,椭圆等几何图形的方法.为了在 Canvas 上绘制更复杂的方法,必须在 Canvas 上启用路径,借用路径来绘制图形. 那么我们现在就一起来看一看,该如何使用路径来绘制圆等图形吧. -

11.分钟学会 Canvas 基础(二)

0. 前言 相信各位小伙伴读了之前的文章,对 Canvas 基础已经有了一定的认识和了解,但是大家也一定记得我在上一篇文章留了一个小的坑. 就是我没有告诉大家该如何去绘制圆,之所以没有说是因为绘制圆实际上是因为 CanvasRenderingContext2D 对象只提供了两个绘制矩形的方法,并没有直接提供绘制圆,椭圆等几何图形的方法.为了在 Canvas 上绘制更复杂的方法,必须在 Canvas 上启用路径,借用路径来绘制图形. 那么我们现在就一起来看一看,该如何使用路径来绘制圆等图形吧. -

canvas基础学习(一)

一.概述 canvas它和其它的HTML5标签的使用基本一致,但是它相当于在浏览器中建立一个画布,可以再这个画布上画图.创建动画甚至是3D游戏.由于canvas要适配不同终端的分辨率,所以尽可能的在标签内设置高度和宽度,这个也符合W3C的标准.代码格式如下,当浏览器不支持canvas标签的时候,会显示其中的文字. <canvas id="main" width="800" height="600" > 亲,您的浏览器不支持canvas

CSS入门基础学习二

我们下午继续学习CSS的入门基础,搬上你的小板凳赶快进入吧! 一.背景(background) Background-color:背景颜色 background-image (背景图片) background-repeat(设置背景平铺)  repeat (默认值) no-repeat (不平铺) repeat-x  (横向平铺) repeat-y (纵向平铺) background-position (设置背景位置) 设置具体值: left| right| top| bottom| cnete

HTML基础学习(二)&mdash;CSS

一.CSS概述     CSS(Cascading Stytle Sheets)层叠样式表,用来定义网页的显示效果.可以解决HTNL代码对样式定义的重复,提高了后期样式代码的可维护性,并增强了网页的显示效果.即CSS将网页内容和显示样式分离,提高了显示功能.   二.CSS与HTML结合方式 1.style属性方式      利用标签中style属性来改变每个标签的显示样式. <body> <div style="background-color: #76EE00;"

Mybatis基础学习(二)&mdash;开发Dao方式

一.原始Dao开发方式 UserDao.java public interface UserDao{ public User findUserByID(Serializable id); public List<User> findUsersByName(String name); } UserDaoImpl.java public class UserDaoImpl implements UserDao{ //SqlSessionFactory是单例存在,不应该在具体实例中创建,需要外部依赖

jQuery基础学习(二)&mdash;jQuery选择器

一.jQuery基本选择器 1.CSS选择器     在学习jQuery选择器之前,先介绍一下之前学过的CSS选择器. 选择器 语法 描述 示例   标签选择器 E {                 CSS规则   }   以文档元素为选择符   ID选择器 #ID{                  CSS规则 }   以ID为选择符   类选择器 E.className{                 CSS规则 }   以文档元素的Class为选择符   群组选择器 E1,E2{   

Canvas基础学习(一)——实现简单时钟显示

HTML5最受欢迎的功能就是<canvas>元素.这个元素负责在页面中设定一个区域,然后就可以通过JavaScript动态地在这个区域中绘制图形.关于<canvas>元素的一些基本用法可以参考w3school. 花了一下午时间熟悉了下常用的API,也参考了下网上的一些demo,实现了一个简单的时钟显示,代码记录如下: 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <met