新收藏

(第五天)HTML5之弧度角度与sin&cos(五角星绘

2016-10-21  本文已影响259人  IOLG

弧度与sin及cos的关系


目的:

通过理解弧度与sin及cos的关系,可以根据弧度及半径求出旋转指定弧度后所到达的dx,dy坐标

弧度(angle)与角度(degree)的关系:

即:30角度的弧度值 = 30 * (π/180) ,30弧度的角度值 = 30 * (180/π)

通过弧度与半径求旋转指定弧度后目标点的坐标:
关系图解

故围绕中心点(0,0)旋转求值:dx = cos(angle) * r,dy = sin(angle) * r
注:若中心点为(10,20),则dx = 10 + cos(angle) * r,dy = 20 + sin(angle) * r

五角星代码示例1
<body>
    <script>
    window.onload = function() {
        var canvas = document.getElementById("canvas");
        if (canvas == null) {
            return false;
        }
        var ctx = canvas.getContext("2d");
        drawLine(ctx);
        drawStar(ctx);
    }

    //画横竖线(田字格)
    function drawLine(ctx) {
        ctx.strokeStyle = "#ccc";
        //划横线
        for (var i = 0.5; i < 500; i++) {
            ctx.beginPath();
            ctx.moveTo(0, i * 10);
            ctx.lineTo(500, i * 10);
            ctx.stroke();
        }
        //划竖线
        for (var i = 0.5; i < 500; i++) {
            ctx.beginPath();
            ctx.moveTo(i * 10, 0);
            ctx.lineTo(i * 10, 500);
            ctx.stroke();
        }

    }

    // 画五角星、外边圆,并绘画出以圆心为圆点的坐标轴及各角到圆心的直线
    function drawStar(ctx) {
        //五角星圆心的坐标位置
        var dx = 200;
        var dy = 200;
        //绘制出五角星外边圆圆心
        ctx.beginPath();
        ctx.arc(dx, dy, 5, 0, 2 * Math.PI, true);
        ctx.fillStyle = "#f00";
        ctx.strokeStyle = "#f00";
        //设置字号,字体
        ctx.font = "14px Verdana";
        ctx.strokeText("圆心", dx, dy);
        ctx.fill();
        //五角星外边圆的半径,即圆心到各个角的距离
        var size = 100;
        ctx.beginPath();

        /*定义一个起始弧度,从这个弧度开始画*/
        var startAngle = -Math.PI * 0.5; //逆时针的一个直角弧度,位于y轴坐标正上方位置

        /*
         *1.五角星划线的角度:一个圆的弧度为2π,分为5个角即2π/5(任意两个点到圆心形成的角度)
         *2.2π/5为蓝线圆心-0,圆心-3形成的角度,而五角星划线是从0-1,所以圆心-0,圆心-1的角度是它的两倍,故须*2
         *3.圆心-0,圆心-3可以通过此代码打开网页查看
         */
        /*dig为圆心-0,圆心-1形成的弧度*/
        var dig = (2 * Math.PI / 5) * 2;

        /*开始画五角星图*/
        ctx.beginPath();
        for (var i = 0; i < 5; i++) {
            //正弧度顺时针旋转,负弧度逆时针旋转
            var angle = startAngle + dig * i;
            /*获取当前角度下一个点的x轴坐标:Math.cos(angle) * size*/
            //cos(弧度) = x坐标/r  r为半径 = 这里的size
            var x = dx + Math.cos(angle) * size; //因弧度是以dx,dy为圆心旋转,所以需要加上dx,dy的坐标,以保持图形的圆心仍为dx,dy
            /*获取当前角度下一个点的y轴坐标:Math.sin(angle) * size*/
            //sin(弧度) = y坐标/r   r为半径 = 这里的size
            var y = dy + Math.sin(angle) * size;
            console.log("x:" + x);
            console.log("y:" + y);
            ctx.lineTo(x, y);
            //给输出文字设置颜色
            ctx.strokeStyle = "#00f";
            //输出划线先后顺序
            ctx.strokeText(i, x, y);
        }
        //这里必须写,否则五角星会少stroke一条线(不影响fill)
        //closePath,闭合图形在非闭合状态下,会通过此方法从当前点至起始点画一条直线
        ctx.closePath();
        ctx.fillStyle = "rgba(255,255,0,0.5)";
        //填充
        ctx.fill();
        //输出文字的时候设置过,状态已被ctx保存,无须再设置。
        //ctx.strokeStyle = "#00f";
        //划线
        ctx.stroke();

        /*划圆心到各角的线*/
        ctx.beginPath();
        var startAngle = -Math.PI * 0.5;
        for (var i = 0; i < 5; i++) {
            var angle = startAngle + dig * i;
            var x = dx + Math.cos(angle) * size;
            var y = dy + Math.sin(angle) * size;
            console.log("x:" + x);
            console.log("y:" + y);
            ctx.moveTo(x, y);
            ctx.lineTo(dx, dy);
        }
        //closePath这里可以不写,因为这里划的都是线,无需闭合
        //ctx.closePath();
        ctx.strokeStyle = "#f00";
        ctx.stroke();

        /*开始画五角星周边圆*/
        ctx.beginPath();
        ctx.arc(dx, dy, size, 0, 2 * Math.PI, true);
        ctx.strokeStyle = "#f00";
        ctx.stroke();

        /*以圆心为起点开始画坐标轴*/
        /*坐标轴颜色*/
        ctx.strokeStyle = "#000";
        //横坐标
        ctx.beginPath();
        ctx.moveTo(0, dy);
        ctx.lineTo(500, dy);
        ctx.stroke();
        //纵坐标
        ctx.beginPath();
        ctx.moveTo(dx, 0);
        ctx.lineTo(dx, 500);
        ctx.stroke();

    }
    </script>
    <canvas id="canvas" height="500" width="500"></canvas>
</body>
上述代码效果图
五角星代码示例2
<script>
    function strokeFiveStar() {
        var canvas = document.getElementById("canvas");
        if (canvas == null) {
            return false;
        }
        var ctx = canvas.getContext("2d");
        /*圆心坐标*/
        var cx = 200;
        var cy = 200;
        /*绘制圆心*/
        ctx.arc(cx, cy, 5, 0, 2 * Math.PI, false);
        ctx.fillStyle = "#f00";
        ctx.fill();

        /*定义起始绘制点弧度 -90角度,y轴正上方*/
        var startAngle = -Math.PI / 2;
        //定义半径
        var r = 100;
        //绘制线条两点(如第1个点与第2个点)与圆心点构成的弧度
        var dig = (2 * Math.PI / 5) * 2;
        ctx.beginPath();
        /*根据角度连接5个点*/
        for (var i = 0; i < 5; i++) {
            var dx = cx + Math.cos(startAngle + dig * i) * r;
            var dy = cy + Math.sin(startAngle + dig * i) * r;
            /*i=0时,因没有子路径,故lineTo的作用相当于moveTo*/
            ctx.lineTo(dx, dy);
            ctx.strokeText("第" + (i + 1) + "个点", dx, dy);
        }
        /*将最后一个点连接到第一个点*/
        ctx.closePath();
        ctx.stroke();
    }
</script>
上述代码示例效果图

Canvas图形综合操作globalCompositeOperation


使用方法:

ctx.globalCompositeOperation = type

12种type值的介绍:
  1. source-over:新图形覆盖原图形,其他部分正常显示
  2. destination-over:原图形覆盖新图形,其他部分正常显示
  3. source-in:只显示在原图形里面的新图形,其他部分透明
  4. destination-in:只显示在新图形里面的原图形,其他部分透明
  5. source-out:只显示在原图形之外的新图形,其他部分透明
  6. destination-out:只显示在新图形之外的原图形,其他部分透明
  7. source-atop:新图形只绘制在原图形之上,原图形其他部分正常显示
  8. destination-atop:原图形只绘制在新图形之上,原图形其他部分正常显示
  9. lighter:重叠部分变亮,其他部分正常显示
  10. darker:重叠部分变暗,其他部分正常显示
  11. xor:重叠部分透明,其他部分正常显示
  12. copy:只保留新图形,其他部分透明

以上类型的比较可参考Mozilla开发者文档的globalCompositeOperation属性

<!-- globalCompositeOperation demo-->
<head>
    <meta charset="UTF-8">
    <title>globalCompostionOperation</title>
    <script>
        function draw(id) {
            var canvas = document.getElementById(id);
            if(canvas == null) {
                return false;
            }
            var ctx = canvas.getContext("2d");
            var types = new Array(
                    /*0*/"source-over", /*覆盖原图形,其他部分正常显示*/
                    /*1*/"destination-over",/*覆盖新图形,其他部分正常显示*/
                    /*2 chrome不支持*/"source-in",/*原图形之内的新图形,其他(原图形&新图形)都透明*/
                    /*3 chrome不支持*/"destination-in",/*新图形之内的原图形,其他(原图形&新图形)都透明*/
                    /*4*/"source-out",/*原图形之外的新图形,其他(原图形&新图形)都透明*/
                    /*5 chrome不支持*/"destination-out",/*新图形之外的原图形,其他(原图形&新图形)都透明*/
                    /*6 chrome不支持*/"source-atop",/*原图形之上,新图形只绘制原图形范围内部分,其他部分正常显示*/
                    /*7*/"destination-atop",/*新图形之上,原图形只绘制新图形范围内部分,其他部分正常显示*/
                    /*8 chrome不支持*/"lighter",/*重叠部分加色,其他不变*/
                    /*9 chrome不支持*/"darker",/*重叠部分减色,其他不变*/
                    /*10*/"xor",/*重叠部分透明,其他不变*/
                    /*11*/"copy"/*只保留新图形,其他清除*/
                    /*以上类型,详情可参考:https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Compositing*/
            );
            /*设置图形叠加组合模式*/
            ctx.globalCompositeOperation = types[10];
            ctx.fillStyle = "#f00";
            ctx.fillRect(100,100,200,200);
            ctx.fillStyle = "#ff0";
            ctx.fillRect(150,150,200,200);

        }
    </script>
</head>
<body onload="draw('canvas')">
    <canvas id="canvas" height="500" width="500"></canvas>
</body>
type为xor的效果图

Canvas绘制阴影效果


功能:

为ctx设置阴影效果后,在当前ctx状态下,canvas中绘制的图像都将出现阴影。

使用方法:
代码示例:
<body>
<script>
    window.onload = function () {
        var canvas = document.getElementById("canvas");
        if (canvas == null) {
            return false;
        }
        var ctx = canvas.getContext("2d");
        /*设置x坐标阴影偏移量*/
        ctx.shadowOffsetX = -10;
        /*设置y坐标阴影偏移量*/
        ctx.shadowOffsetY = 10;
        /*设置阴影颜色*/
        ctx.shadowColor = "#ccc";
        /*设置阴影模糊程度,默认是0*/
        ctx.shadowBlur = 20;

        /*绘制图形*/
        ctx.fillStyle = "#ff0";
        ctx.fillRect(100,100,50,50);
        /*这个图形一样会有阴影效果,ctx的状态不断被更新*/
        ctx.fillStyle = "#ff0";
        ctx.fillRect(200,100,50,50);
    }
</script>
<canvas id="canvas" width="500" height="500">您的浏览器不支持</canvas>
</body>
上述代码效果图

Canvas的图像绘制:drawImage


功能:

通过canvas的drawImage方法 ,将指定图片绘制到canvas画布上。

绘制流程:
  1. 创建一个图片对象,用来承载图像 var img = new Image();
  2. 设置图像源 img.src = "xxx.jpg;"
  3. 监听图像对象的onload事件,图像加载完成后会执行该事件指定的函数 img.onload = draw
  4. 在onload制定的draw函数中通过drawImage方法将img对象中的图像绘制到canvas画布中
drawImage的3种方法:
  1. drawImage(img,destX,destY):以画布的destX、destY作为图像显示起始点,将整个img图像按图像原始像素绘制到画布中,超出画布不绘制;

  2. drawImage(img,destX,destY,destWidth,destHeight):将整个img图像绘制到画布中,以画布的destX、destY作为显示图像的起始点,destWidth、destHeight作为图像的显示大小;若destWidth、destHeight大于图像原始像素,则图像会放大(会模糊);反之则缩小。

  3. drawImage(img,sourceX,sourceY,sourceWidth,sourceHeight,destX,destY,destWidth,destHeight):从img的sourceX、sourceY起始点,获取sourceWidth、sourceHeight大小的图像,并将获取到的图像draw到画布中,从画布的destX、destY起始点开始绘制,将获取到的图像绘制成destWidth、destHeight大小(destWidth、destHeight若大于sourceWidth、sourceHeight,图像会放大即模糊;反之则缩小)

示例代码:
<script>
    window.onload = function () {
        var canvas = document.getElementById("canvas");
        if (canvas == null) {
            return false;
        }
        var ctx = canvas.getContext("2d");
        /*创建一个图片对象*/
        var img = new Image();
        /*监听图片加载,加载成功结束后执行*/
        img.onload = function () {
            /*将原图draw到画布上,超出画布部分,不绘制*/
            ctx.drawImage(img, 0, 0);
            /*将整个img绘制到画布上,画布上的img起始点为100,100,宽高为300*300*/
            ctx.drawImage(img, 100, 100, 200, 200);
            /*以img的200,200为起始点,在img上获取宽高位150*150范围的图片,
            并将获取到的图片粘贴到画布坐标300,300的位置上,图片大小为200*200*/
            /*图片会变模糊,因为source的大小是150*150,而dest的大小为200*200*/
            ctx.drawImage(img, 200, 200, 150, 150, 300, 300, 200, 200);
        }
        img.src = "../raw/1.jpg";
    };
</script>
上述代码示例效果图

CreateJs之EaselJs基础应用


EaselJs是什么?

EaselJs:一个javascript库,方便更快速的处理canvas。

EaselJs如何使用?
  1. 引入easeljs的js文件 <script src="https://code.createjs.com/easeljs-0.8.2.min.js"></script>
  2. 在body元素中创建一个canvas元素 <canvas id="demoCanvas" width="500" height="300"></canvas>
  3. 基于canvas元素创建一个createjs的舞台 var stage = new createjs.Stage("demoCanvas");
  4. 创建需要被添加到舞台的对象,如创建一个图形对象 var circle = new createjs.Shape();
  5. 对图形对象进行处理,如画一个圆circle.graphics.beginFill("DeepSkyBlue").drawCircle(0, 0, 50);
  6. 将图形对象添加到舞台中去 stage.addChild(circle);
  7. 更新舞台 stage.update();

如果需要根据指定的帧频率变化舞台,继续看下方:
8.设置帧频率计时模式createjs.Ticker.timingMode = createjs.Ticker.RAF;
9.设置刷新频率fsp值createjs.Ticker.framerate = 10;即10fsp,1/10秒的速度刷新。
10.设置Ticker的tick事件监听createjs.Ticker.addEventListener("tick", func);
11.定义func;通过tick事件,会根据指定的频率执行该func函数;所有对舞台的操作在这里处理即可,记得更新舞台stage.update();

*注意点:
1.默认的计时模式为createjs.Ticker.TIMEOUT,
2.RAF计时模式下,framerate无效,
3.RAF模式下动画效果更流畅,
4.不需要按指定帧频率时,可使用RAF计时模式

基础使用的示例代码:
<head>
    <meta charset="UTF-8">
    <title>easeljs的使用流程</title>
    <!--将js引入到文档中-->
    <script src="js/easeljs-0.8.2.min.js"></script>
    <script>
        function init() {
            /*基于canvas创建一个Stage对象*/
            var stage = new createjs.Stage("demoCanvas");
            /*创建一个图形对象*/
            var shape = new createjs.Shape();
            /*fill一个颜色为黄色,半径为50,圆心在100,100坐标的圆*/
            shape.graphics.beginFill("#ff0").drawCircle(100, 100, 50);
            /*设置圆的起始坐标点x,y,故圆心位于200,200*/
            shape.x = 100;
            shape.y = 100;
            /*将shape对象加入到stage中*/
            stage.addChild(shape);
            /*更新stage*/
            stage.update();

            /* 在shape对象中再画一个圆,圆心100,100,原因与shape
             * 的起始位置x,y相关
             * f是beginFill的Tiny写法,dc是drawCircle的Tiny写法
             * 更多Tiny写法可参考http://www.createjs.com/docs/easeljs/classes/Graphics.html*/
            shape.graphics.f("#f00").dc(0, 0, 50);
            /*shape发生变化后需要更新舞台才能显示最新的变化*/
            stage.update();

            /*设置Ticker的计时模式 RAF更流畅,缺点是
             忽略帧速率(即忽略createjs.Ticker.framerate)*/
            //createjs.Ticker.timingMode = createjs.Ticker.RAF;
            /* 设置帧速率,默认是30FSP,即1/30秒执行一次update
             * 如果Ticker计时模式设置为createjs.Ticker.RAF,那么此值无效;*/
            createjs.Ticker.framerate = 5;
            /* 添加一个tick监听事件,tick事件会根据指定的帧速率执行
             * 对应的函数,如这里的update*/
            createjs.Ticker.addEventListener("tick", update);

            /* 计时模式为TIMEOUT的情况下,framerate=5,
             * 故该函数会每隔1/5秒的频率被调用*/
            function update(event) {
                shape.x += Math.random() * 300;
                shape.y += Math.random() * 300;
                /* 这个500是canvas的宽度,可以通过获得canvas对象.width获得
                 * 如果shape的起始点x坐标大于canvas宽度,则初始化shape.x=0*/
                if (shape.x > 500) {
                    shape.x = 0;
                }
                /*如果shape的起始点y坐标大于canvas高度,则初始化shape.y=0*/
                if (shape.y > 500) {
                    shape.y = 0;
                }
                /*每一次变化都需要通过update()来更新舞台即stage*/
                stage.update();
            }
        }
    </script>
</head>
<body onload="init()">
<!--emment写法:canvas#demoCanvas[width=500,height=500]{您的浏览器不支持}-->
<canvas id="demoCanvas" width="500" height="500">您的浏览器不支持</canvas>
</body>
上述代码示例效果图
上一篇下一篇

猜你喜欢

热点阅读