zoukankan      html  css  js  c++  java
  • html5 canvas 学习

    1.定义画布,取得画布上下文下文

     <canvas id="canvas"></canvas>

    js:

    var cvs = document.getElementById("canvas");
            var context = cvs.getContext('2d');
            cvs.width = 1000;
            cvs.height = 600;

    2.绘制一条直线

    context.moveTo(100, 100);
    context.lineTo(300, 200);
    context.strokeStyle="red";//笔刷颜色,填充颜色用 .fillStyle
    context.lineWidth=10;//笔刷宽度
    context.stroke();//填充用.fill()方法

    如果要绘制多条线段 ,并且分别对线段指定样式,但最终显示都是最后指定的一个样式,这是因为canvas是状态绘制,所以对每个线段绘制可都应该用beginPath方法来告知是一个全新绘制就没有问题了

    context.lineWidth = 10;
    
            context.beginPath();
            context.lineTo(100, 100);
            context.lineTo(300, 200);
            context.lineTo(100, 300);
            context.strokeStyle = "#003399";
            context.stroke();
    
            context.beginPath();
            context.moveTo(300, 100);
            context.lineTo(600, 200);
            context.lineTo(300, 300);
            context.strokeStyle = "#330022";
            context.stroke();

    以上线段没有首尾闭合,如要闭合添加context.closePath()即可。

    注意,context.beignPath()与context.closePath()不是一定要成对出现的,只要线段间需要闭合时才使用closePath

    3.画矩形方法

    context.rect(100, 100, 200, 200);
    context.fill()//或context.stroke()
    
    context.fillRect(100, 100, 200, 200);
    
    context.strokeRect(100, 100, 200, 200);

    对fillStyle样式可以指定颜色,还可以指定透明度:

            context.lineWidth = 10;
            context.beginPath();
            context.fillStyle = "red";
            context.fillRect(100, 100, 300, 300);
           
            context.beginPath();
            context.fillStyle = "rgba(0, 255, 0, 0.5)";
            context.fillRect(200, 200, 300, 300);

    4.直线两端的样式:context.lineCap="round",值分别可以butt(默认),round,square,注意使用round和square会比默认的多出来一小段长度,

    直线与直线相交的形式:context.lineJoin,值分别:miter(默认)|bevel|round .如果绘制的角很尖时,还需要考虑另一个值:  cxt.miterLimit = 20;默认值为10

    5.画五角形,函数如下:

    function drawStar(cxt, x, y, outerR, innerR, rot) {
                 cxt.beginPath();
                 for (var i = 0; i < 5; i++) {
                     cxt.lineTo(Math.cos((18+i*72-rot)/180*Math.PI)*outerR+x,
                     -Math.sin((18+i*72-rot)/180*Math.PI)*outerR+y);
                     cxt.lineTo(Math.cos((54 + i * 72 - rot) / 180 * Math.PI) * innerR + x,
                         -Math.sin((54 + i * 72 - rot) / 180 * Math.PI) * innerR + y);
                 }
                 cxt.closePath();
    
                 cxt.fillStyle = "#fb3";
                 cxt.strokeStyle = "#fd5";
                 cxt.lineWidth = 3;
                 cxt.lineJoin = "rount";
    
                 cxt.fill();
                 cxt.stroke();
             }

    在画布上添加200个五角星

    for (var i = 0; i < 200; i++) {
                     var r = Math.random() * 10 + 10;
                     var x = Math.random() * cvs.width;
                     var y = Math.random() * cvs.height;
                     var a = Math.random() * 360;
                     drawStar(context, x, y, r, r / 2.0, a);
                 }

     6.图形变换:tanslate,rotate,scale

    如果对图形时行多次变换,最终结果可能会与实现想象中有差异,最好使用context.save()和context.restore(),这里context.save();和context.restore();是两个相互匹配出现的,作用是用来保存画布的状态和取出保存的状态的

            context.translate(100, 0),是向右移动100个像素,如果没有save和restore,会对多次出现的平移进行叠加

    context.scale(x,y),缩放使用可注意,它不仅对图形大小时行缩放,还会对边框和起点坐标也会一起缩放,所以使用scale一定要注意。

    如果绘制起点设置在(0,0)坐标开始绘制,那缩放将对起点不起任何作用,这样就可能可保证起点不发生改变,此时tanslate移动起点是正确的显示器。

    通过学习图形变换,把显示200星星的实例修改一下,使用图形变换的方式显示出来,不过由于使用缩放方法会使描边也发生缩放,所以这里就去掉星星的边框。

     context.fillStyle = "#fb3";
            context.lineJoin = "rount";
            for (var i = 0; i < 200; i++) {
                var r = Math.random() * 10 + 10;
                var x = Math.random() * cvs.width;
                var y = Math.random() * cvs.height;
                var a = Math.random() * 360;
                drawStar(context, x, y, r, a);
            }
    
            function drawStar(context,x,y,r,rot) {
                context.save();
                context.translate(x, y);
                context.rotate(rot / 180 * Math.PI);
                context.scale(r, r);
                starPath(context);
                context.fill();
                context.restore();
            }
            function starPath(context) {
                context.beginPath();
                for (var i = 0; i < 5; i++) {
                    context.lineTo(Math.cos((18 + i * 72) / 180 * Math.PI) ,
                    -Math.sin((18 + i * 72 ) / 180 * Math.PI) );
                    context.lineTo(Math.cos((54 + i * 72) / 180 * Math.PI) * 0.5,
                        -Math.sin((54 + i * 72 ) / 180 * Math.PI) * 0.5);
                }
                context.closePath();
            }

    除了用translate,rotate,scale对图形变换外,还可以使用transform一次设定这几个方法的参数 :transform(a,b,c,d,e,f) ,如果参数设置成(1,0,0,1,0,0)对图形的变化不会产生任何变化。参数:a

    、d是控件水平和垂直缩放的,b和c是倾斜,e和f是位移。多个 transform()一起使用会是效果级联叠加,如果想恢复到最初状态开始可以使用setTransform();

    7.渐变:

    线性渐变:

     var linearGradient = context.createLinearGradient(0, 0, 800, 0);
            linearGradient.addColorStop(0.0, "red");
            linearGradient.addColorStop(1.0, "blue");
    
            context.fillStyle = linearGradient;
            context.fillRect(0, 0, 800, 800);

    径向渐变:

            var linearGradient = context.createRadialGradient(400, 400, 0,400,400,800);
            linearGradient.addColorStop(0.0, "red");
            linearGradient.addColorStop(1.0, "blue");
    
            context.fillStyle = linearGradient;
            context.fillRect(0, 0, 800, 800);    
    为了图像颜色鲜艳可以添加多个addColorStop
    图案填充:
            var img = new Image();
            img.src = "imgs/head.jpg";
            img.onload = function () {
                var pattern = context.createPattern(img,"repeat");
                
                context.fillStyle = pattern;
                context.fillRect(0, 0, 800, 800);
            };
    
    

    画布作为图案填充:

      var pattern = context.createPattern(drawRect(), "repeat");
            context.fillStyle = pattern;
            context.fillRect(0, 0, 800, 800);
    
            function drawRect() {
                var v = document.createElement("canvas");
                v.width = 50;
                v.height = 50;
                var c = v.getContext('2d');
                c.lineWidth = 5;
                c.strokeRect(0, 0, 45, 45);
                return v;
            }

    还可以使用视频来作为图案填充

    8.画园角矩形

            var cvs = document.getElementById("canvas");
            var context = cvs.getContext('2d');
            cvs.width = 1000;
            cvs.height = 700;
           
            context.transform(1, 0, 0, 1, 100, 100);
            drawRoundRect(350, 150, 20);
            
    
            context.stroke();
            function drawRoundRect( w, h, r) {
                
                context.beginPath();
                context.arc(r, r, r, Math.PI, 3 * Math.PI / 2);
                context.arc(w - r, r, r, Math.PI * 3 / 2, 0);
                context.arc(w - r, h - r, r, 0, Math.PI / 2);
                context.arc(r, h - r, r, Math.PI / 2, Math.PI);
                context.closePath();
            }

    9.曲线,不细说了,可以查看贝塞尔曲线(二次,三次),网上有直接生成三次贝塞尔曲线的网页

    10.字体:

    context.font = "bold 40px 雅黑";
    context.fillText("我是一个兵", 200, 200);

    context.measureText("我是一个兵").width,可以取宽度

    11.阴影

    context.shadowBlur = 5;
            context.shadowOffsetX = 20;
            context.shadowOffsetY = 20;
            context.shadowColor = "gray";

    12.生成100个小球

    var cvs = document.getElementById("canvas");
            var context = cvs.getContext('2d');
            cvs.width = 1000;
            cvs.height = 700;
            context.globalAlpha = 0.7;
            for (var i = 0; i < 100; i++) {
                var x = Math.random() * cvs.width;
                var y = Math.random() * cvs.height;
                var r = Math.random() * 50;
                var cr = Math.floor(Math.random() * 255);
                var g = Math.floor(Math.random() * 255);
                var b = Math.floor(Math.random() * 255);
                context.fillStyle = "rgb(" + cr + "," + g + "," + b + ")";
                context.beginPath();
                context.arc(x, y, r, 0, 2 * Math.PI);
                context.fill();
            }
    context.globalAlpha 是透明度,context.globalCompositeOperation 属性设置或返回如何将一个源(新的)图像绘制到目标(已有)的图像上
    描述
    source-over 默认。在目标图像上显示源图像。
    source-atop 在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。
    source-in 在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。
    source-out 在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。
    destination-over 在源图像上方显示目标图像。
    destination-atop 在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。
    destination-in 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。
    destination-out 在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
    lighter 显示源图像 + 目标图像。
    copy 显示源图像。忽略目标图像。
    source-over 使用异或操作对源图像与目标图像进行组合。

    11.剪辑区域

    context.clip();

    12.非零环绕原则,

    context.beginPath();
            context.arc(400, 400, 300, 0, 2 * Math.PI,true);
            context.arc(400, 400, 150, 0, 2 * Math.PI);
            context.closePath();
            context.fillStyle = "red";
            context.shadowColor = "gray";
            context.shadowOffsetX = 10;
            context.shadowOffsetY = 10;
            context.shadowBlur = 5;
            context.fill();

    非零环绕规则:对于路径中指定范围区域,从该区域内部画一条足够长的线段,使此线段的完全落在路径范围之外。


    非零环绕规则计数器:
    然后,将计数器初始化为0,每当这个线段与路径上的直线或曲线相交时,就改变计数器的值,如果是与路径顺时针相交时,那么计数器就加1, 如果是与路径逆时针相交时,那么计数器就减1.
    如果计数器始终不为0,那么此区域就在路径范围里面,在调用fill()方法时,浏览器就会对其进行填充。如果最终值是0,那么此区域就不在路径范围内,浏览器就不会对其进行填充。

    13.事件:

    var ball = [];
    var cvs = document.getElementById("canvas");
            var context = cvs.getContext('2d');
            cvs.width = 1000;
            cvs.height = 700; window.onload
    =function() { for (var i = 0; i < 10; i++) { ball[i] = { x: Math.random() * cvs.width, y:Math.random()*cvs.height, r:Math.random()*100 }; } draw(); cvs.addEventListener("mouseup", function (e) { e.stopPropagation(); var x =e.clientX- cvs.getBoundingClientRect().left; var y = e.clientY - cvs.getBoundingClientRect().top; for (var i = 0; i < 10; i++) { context.beginPath(); context.arc(ball[i].x, ball[i].y, ball[i].r, 0, 2 * Math.PI); if(context.isPointInPath(x, y)){ context.fillStyle = "red"; context.fill(); } } }); } function draw() { for (var i = 0; i < 10; i++) { context.beginPath(); context.arc(ball[i].x, ball[i].y, ball[i].r, 0, 2 * Math.PI); context.fillStyle = "gray"; context.fill(); } }

    14.如果想偷懒,当然可以找一些现成的图形库,直接应用就可以,比如RGraph是一个使用HTML5 Canvas标签实现的图表制作Library。利用该Library生成的Chart具有可交互性,当鼠标点击或移过时会显示相应的信息,可以动态加载Chart或对特殊点进行缩放。当前支持的图表类型包括:

    • bar、pie、donut、gantt、radar、funnel、bi-polar charts
    • line and scatter graphs
    • LED display
    • meter
    • odometer
    • progress bar

    http://www.rgraph.net/download

    15.最后来一个动画:

     var bgcolor = "#000";
                var balls = [];
                var canvas = document.getElementById("canvas");
                var context = canvas.getContext('2d');
                canvas.width = 1000,
                canvas.height = 700;
                //添加小球
                getBall();
                setInterval(function () {
                        drawBall();
                }, 50);
    
                function drawBall() {
                    context.globalCompositeOperation = "lighter";
                    context.clearRect(0, 0, canvas.width, canvas.height);
                    //画背景色
                    context.beginPath();
                    context.fillStyle = bgcolor;
                    context.fillRect(0, 0, canvas.width, canvas.height);
                    
                    //画球
                    for (var i = 0; i < balls.length; i++) {
                        var ball = balls[i];
                        if ((ball.x - ball.r) < 0 || (ball.x + ball.r) >= canvas.width) {
                            ball.vx = -ball.vx;
                        }
                        if ((ball.y - ball.r) <= 0 || (ball.y + ball.r) >= canvas.height) {
                            ball.vy = -ball.vy;
                        }
                        ball.x += ball.vx;
                        ball.y += ball.vy;
    
                        context.beginPath();
                        context.arc(ball.x, ball.y, ball.r, 0, 2 * Math.PI);
                        context.closePath();
                        context.fillStyle = ball.color;
                        context.fill();
                    }
    
    
                }
                function getBall() {
                    for (var i = 0; i < 100; i++) {
                        var r =Math.random() * 40 + 10;
                        var x =Math.random() * (canvas.width-2*r)+r;
                        var y = Math.random() * (canvas.height - 2 * r)+ r;
                        var vx = (Math.random() * 5 + 2) * Math.pow(-1, Math.floor(Math.random() * 100));
                      var  vy = (Math.random() * 5 + 2) * Math.pow(-1, Math.floor(Math.random() * 100));
                        var R = Math.floor(Math.random() * 255);
                        var G = Math.floor(Math.random() * 255);
                        var B = Math.floor(Math.random() * 255);
                        var color = "rgba(" + R + "," + G + "," + B + ","+Math.random()+")";
                        balls[i] = { x: x, y: y, r: r, vx: vx, vy: vy, color: color };
                    }
                }
  • 相关阅读:
    [ACM] POJ 3258 River Hopscotch (二分,最大化最小值)
    c语言全局变量和局部变量问题汇总
    surfaceDestroyed什么时候被调用
    JDBC连接MySQL数据库及演示样例
    30天自制操作系统之第11天 制作窗体
    bugFree与zentao
    java实现第七届蓝桥杯生日蜡烛
    java实现第七届蓝桥杯生日蜡烛
    java实现第七届蓝桥杯生日蜡烛
    java实现第七届蓝桥杯生日蜡烛
  • 原文地址:https://www.cnblogs.com/lunawzh/p/5170902.html
Copyright © 2011-2022 走看看