首页 HTML/CSS正文

canvas中级部分--运动,弧度,文字,变形

景先 HTML/CSS 2016-01-02 2180 0 canvashtml5

canvas运动

 本质是一堆像素点的运动,需要用到定时器setInterval及gd.clearRect(x,y,w,h);

 原理是先擦除,在重新绘画,这不需要考虑性能,因为canvas的性能相当高。

定时器这里给的时间是60fps,保证canvas运动基本流畅


*帧频

高帧   1000/60 =16 ms

低帧    30ms

此处是关于运动的演示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas运动demo</title>
    <style>
        body{
            background: #000;
        }
        #c1{
            background: #fff;
        }
    </style>
    <script>
        window.onload=function(){
            var oC=document.getElementById('c1');

            var gd=oC.getContext('2d');

            var x=100;
            setInterval(function(){
                gd.clearRect(0,0,oC.width,oC.height);

                gd.strokeRect(x++,100,200,100);
            },16);
        };
    </script>
</head>
<body>
    <canvas id="c1" width="800" height="600"></canvas>
</body>
</html>

通过上述的概括,这里写一个canvas比较好的运动,windows线性屏保

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        html,body{
            height:100%;
            overflow: hidden;
        }
        #c1{
            background: #000;
        }
    </style>
    <script>
        function rnd(n,m){
            return parseInt(Math.random()*(m-n))+n;
        }
        window.onload=function(){
            var oC=document.getElementById('c1');

            var gd=oC.getContext('2d');

            var winW=document.documentElement.clientWidth;
            var winH=document.documentElement.clientHeight;

            oC.width=winW;
            oC.height=winH;

            var N=5;
            var len=20;

            var aPoint=[]; //存储点
 var oldArr=[];  //[[{},{}]]

 for(var i=0; i<N; i++){
                aPoint[i]={
                    x:rnd(0,winW),
                    y:rnd(0,winH),
                    iSpeedX:rnd(-5,5),
                    iSpeedY:rnd(-10,10)
                };
            }

            setInterval(function(){
                gd.clearRect(0,0,oC.width,oC.height);

                //画出来
 for(var i=0; i<aPoint.length; i++){
                    drawPoint(aPoint[i]);
                }

                //开始走
 for(var i=0; i<aPoint.length; i++){
                    if(aPoint[i].y<=0){
                        aPoint[i].y=0;
                        aPoint[i].iSpeedY*=-1;
                    }
                    if(aPoint[i].y>=winH){
                        aPoint[i].y=winH;
                        aPoint[i].iSpeedY*=-1;
                    }
                    if(aPoint[i].x<=0){
                        aPoint[i].x=0;
                        aPoint[i].iSpeedX*=-1;
                    }
                    if(aPoint[i].x>=winW){
                        aPoint[i].x=winW;
                        aPoint[i].iSpeedX*=-1;
                    }
                    aPoint[i].x+=aPoint[i].iSpeedX;
                    aPoint[i].y+=aPoint[i].iSpeedY;
                }

                //画线
 gd.beginPath();
                gd.strokeStyle='#fff';
                gd.moveTo(aPoint[0].x,aPoint[0].y);
                for(var i=1; i<aPoint.length; i++){
                    gd.lineTo(aPoint[i].x, aPoint[i].y);
                }
                gd.closePath();
                gd.stroke();

                //处理尾巴
 var arr=[];
                for(var i=0; i<aPoint.length; i++){
                    arr[i]={
                        x:aPoint[i].x,
                        y:aPoint[i].y
 };
                }

                oldArr.push(arr);

                if(oldArr.length>len){
                    oldArr.shift();
                }

                //画尾巴
 for(var i=0; i<oldArr.length; i++){
                    var opacity=i/oldArr.length;

                    gd.beginPath();
                    gd.strokeStyle='rgba(255,255,255,'+opacity+')';
                    gd.moveTo(oldArr[i][0].x,oldArr[i][0].y);
                    for(var j=0; j<oldArr[i].length; j++){
                        gd.lineTo(oldArr[i][j].x, oldArr[i][j].y);
                    }
                    gd.closePath();
                    gd.stroke();
                }
            },16);


            function drawPoint(p){
                var pW=1;
                var pH=1;

                gd.fillStyle='#fff';
                gd.fillRect(p.x-pW/2, p.y-pH/2, pW, pH);
            }
        };
    </script>
</head>
<body>
<canvas id="c1"></canvas>
</body>
</html>

弧度

gd.arc(cx,cy,r,起始角度,结束角度,是否逆时针);弧度本身也是路径

起始角度和结束角度都是弧度

角度            弧度

360            2PI

180            PI

1                PI/180


n                n*PI/180

function d2a(n){
    return n*Math.PI/180;
}

当绘制圆的时候默认是从3点钟方向开始,如果想要从12点钟方向开始,就要减去90°

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas--弧度</title>
    <style>
        body{
            background: #000;
        }
        #c1{
            background: #fff;
        }
    </style>
    <script>
        function d2a(n){
            return n*Math.PI/180;
        }
        window.onload=function(){
            var oC=document.getElementById('c1');
            var gd=oC.getContext('2d');

            /*gd.arc(200,200,100,0,360,false);

            gd.stroke();*/

 gd.arc(200,200,100,d2a(0),d2a(-90),true);

            gd.stroke();
        };
    </script>
</head>
<body>
    <canvas id="c1" width="800" height="600"></canvas>
</body>
</html>

以前根据矩形写过统计图,现在根据弧度也写个饼图。

思路:

所有的数据放在数组中,求比例,显示对应弧度,然后绘制,分配颜色

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas饼图</title>
    <style>
        body{
            background: #000;
        }
        #c1{
            background: #fff;
        }
    </style>
    <script>
        function d2a(n){
            return n*Math.PI/180;
        }
        function rnd(n,m){
            return parseInt(Math.random()*(m-n))+n;
        }
        window.onload=function(){
            var oC=document.getElementById('c1');
            var gd=oC.getContext('2d');
            
            //定义圆心位置,半径
            var cx=200;
            var cy=200;
            var r=100;

            var arr=[123,45,90,100,50,200];

            //求和
            var res=0;
            for(var i=0; i<arr.length; i++){
                res+=arr[i];
            }
            //根据求的和算角度数组
            var aDeg=[];
            for(var i=0; i<arr.length; i++){
                aDeg[i]=arr[i]/res*360;
            }

            function drawPie(start,end){
                gd.beginPath();
                gd.fillStyle='rgb('+rnd(0,256)+','+rnd(0,256)+','+rnd(0,256)+')';
                gd.moveTo(cx,cy);
                gd.arc(cx,cy,r,d2a(start),d2a(end),false);
                gd.closePath();
                gd.stroke();
                gd.fill();
            }

            var d=0;
            for(var i=0; i<aDeg.length; i++){
                drawPie(d,aDeg[i]+d);

                d+=aDeg[i];
            }
        };
    </script>
</head>
<body>
    <canvas id="c1" width="800" height="600"></canvas>
</body>
</html>

进度条运动演示

思路:循环i,每次自增5,当i=360的时候关闭定时器,注意运动的时候需要先清屏,在gd.beginPath(),后绘制clearRect(0,0,oC.width,oC.height);

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas弧形进度条</title>
    <style>
        body{
            background: #000;
        }
        #c1{
            background: #fff;
        }
    </style>
    <script>
        function d2a(n){
            return n*Math.PI/180;
        }
        window.onload=function(){
            var oC=document.getElementById('c1');
            var gd=oC.getContext('2d');

            gd.lineWidth=20;
            var i=0;
            var timer=setInterval(function(){
                gd.clearRect(0,0,oC.width,oC.height);
                gd.beginPath();
                gd.strokeStyle='rgb('+i/360*255+','+i/360*255+',0)';
                i+=5;
                gd.arc(200,200,100,d2a(0), d2a(i),false);
                gd.stroke();

                if(i>=360){
                    clearInterval(timer);
                }
            },16);
        };
    </script>
</head>
<body>
    <canvas id="c1" width="800" height="600"></canvas>
</body>
</html>

canvas文字

gd.strokeText(str,x,y,[最大宽度]);

gd.font="30px a"

gd.fillText(str,x,y,[最大宽度]);

gd.lineWidth = 10;

gd.fillStyle = "#f60";


文字排列方向:   默认居中的位置是左下角 ,排列方向按照文字的中心点排列

gd.textAlgin = "left/center/right"      水平方向

gd.textBaseline="top/middle/bottom"   垂直方向


测量文字的宽度:

gd.measureText(str).width

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas文字位置</title>
    <style>
        body{
            background: #000;
        }
        #c1{
            background: #fff;
        }
    </style>
    <script>
        window.onload=function(){
            var oC=document.getElementById('c1');

            var gd=oC.getContext('2d');

            gd.fillStyle='red';
            gd.font='60px s';
            gd.lineWidth=10;
            gd.textAlign="center";
            gd.textBaseline="middle";
            var str='你好啊';
            gd.fillText(str+"fillText",300,100);
            gd.strokeText(str+"stroke",300,200);

            //1.
 gd.beginPath();
            gd.lineWidth=1;
            gd.moveTo(300,0);
            gd.lineTo(300,oC.height);
            gd.stroke();

            //2.
 gd.beginPath();
            gd.moveTo(0,100);
            gd.lineTo(oC.width,100);
            gd.stroke();

        };
    </script>
</head>
<body>
    <canvas id="c1" width="800" height="600"></canvas>
</body>
</html>

canvas变形

这里的变形本质是指变化的画布

旋转    gd.rotate(弧度)

平移    gd.translate(100,0)

缩放    gd.scale(x,y)


旋转----是否是按照中心点旋转?

默认是按照画布的左上角进行旋转的

比如定义一个矩形,旋转要分成以下几步才能够进行中心点旋转

gd.strokeRect(x,y,w,h);

gd.translate(x+w/2,y+h/2);

//旋转
gd.rotate(d2a(n));
gd.strokeRect(-w/2,-h/2,w,h);

请看详细代码--按照中心点旋转

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas按照中心点旋转</title>
    <style>
        body{
            background: #000;
        }
        #c1{
            background: #fff;
        }
    </style>
    <script>
        function d2a(n){
            return n*Math.PI/180;
        }
        window.onload=function(){
            var oC=document.getElementById('c1');

            var gd=oC.getContext('2d');

            //gd.rotate(d2a(30));
            //gd.strokeRect(100,100,200,100);

 gd.translate(100+100,100+50);
            gd.rotate(d2a(30));
            gd.strokeRect(-100,-50,200,100);

        };
    </script>
</head>
<body>
    <canvas id="c1" width="800" height="600"></canvas>
</body>
</html>

canvas按照右上角旋转

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas右上角旋转</title>
    <style>
        body{
            background: #000;
        }
        #c1{
            background: #fff;
        }
    </style>
    <script>
        function d2a(n){
            return n*Math.PI/180;
        }
        window.onload=function(){
            var oC=document.getElementById('c1');

            var gd=oC.getContext('2d');

            //gd.rotate(d2a(30));
            //gd.strokeRect(100,100,200,100);

 gd.translate(100+200,100);
            gd.rotate(d2a(30));
            gd.strokeRect(-200,0,200,100);

        };
    </script>
</head>
<body>
    <canvas id="c1" width="800" height="600"></canvas>
</body>
</html>

canvas按照左上角进行旋转

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas按照左上角进行旋转</title>
    <style>
        body{
            background: #000;
        }
        #c1{
            background: #fff;
        }
    </style>
    <script>
        function d2a(n){
            return n*Math.PI/180;
        }
        window.onload=function(){
            var oC=document.getElementById('c1');

            var gd=oC.getContext('2d');

            //gd.rotate(d2a(30));
            //gd.strokeRect(100,100,200,100);

 gd.translate(100,100);
            gd.rotate(d2a(30));
            gd.strokeRect(0,0,200,100);

        };
    </script>
</head>
<body>
    <canvas id="c1" width="800" height="600"></canvas>
</body>
</html>

canvas变形--->变化不是覆盖,而是累加,下一个变形方式会累加上一个变形方式。

平移:gd.translate(100,0);

解决变形的累加方式:

    a)  gd.rotate(d2a(10));

         gd.strokeRect(100,100,200,100);

         gd.rotate(d2a(-10));

    b).

        保存画布此时的状态:gd.save();

        恢复到save状态:gd.restore();


因此定义一个画布流程:

gd.save();

gd.beginPath();


//绘图


gd.closePath();

gd.restore();

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas--按照中心点旋转</title>
    <style>
        body{
            background: #000;
        }
        #c1{
            background: #fff;
        }
    </style>
    <script>
        function d2a(n){
            return n*Math.PI/180;
        }
        window.onload=function(){
            var oC=document.getElementById('c1');

            var gd=oC.getContext('2d');

            var linear=gd.createLinearGradient(-300,-300,400,400);
            linear.addColorStop(0,'red');
            linear.addColorStop(1,'yellow');

            gd.strokeStyle=linear;
            var d=0;
            setInterval(function(){
                gd.clearRect(0,0,oC.width,oC.height);
                gd.save();
                gd.translate(100+100,100+50);
                gd.rotate(d2a(d++));
                gd.strokeRect(-100,-50,200,100);
                gd.restore();
            },16);

        };
    </script>
</head>
<body>
    <canvas id="c1" width="800" height="600"></canvas>
</body>
</html>

        

版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

评论