用变量的方式绘制一个五角星,首先求五角星十个顶点的坐标。

可以把每个五角星看成外顶点用一个大圆绘制,内顶点用小圆绘制。在坐标系(0deg)下,根据每个顶点的角度和圆的半径求得x,y。

而每个大顶点相差72deg(180/5),每个小顶点也差72deg.所以下一个顶点的度数就是当前点加上72deg.(逆时针)

代码实现画一个五角星


 drawStar(context, 300, 150, 400, 400,30);
function drawStar(context, R, r, x, y,rot) {  // R:大圆半径,r:小圆半径,x: x方向圆心位置 y: y方向圆心位置,rot:旋转角度
context.beginPath();
for (var i = 0; i <; i++) {
          //因为角度是逆时针计算的,而旋转是顺时针旋转,所以是度数是负值。
context.lineTo(x + Math.cos((18 + 72 * i - rot) / 180 * Math.PI) * R,
y - Math.sin((18 + 72 * i - rot) / 180* Math.PI)* R);
context.lineTo(x + Math.cos((54 + 72 * i - rot) / 180 * Math.PI) * r,
y - Math.sin((54 + 72 * i - rot) / 180 * Math.PI) * r);
}
context.closePath();
context.stroke();
}

画多个五角星

     for (var i = 0; i <; i++) {
var r = Math.random() * 10 + 10; //大小随机
var x = Math.random() * canvas.width; //位置随机
var y = Math.random() * canvas.height;
var rot = Math.random() * 360; //星星旋转角度随机
drawStar(context, r, r / 2, x, y, rot);
}
function drawStar(context, R, r, x, y, rot) {
context.beginPath();
for (var i = 0; i < 5; i++) {
context.lineTo(x + Math.cos((18 + 72 * i - rot) / 180 * Math.PI) * R,
y - Math.sin((18 + 72 * i - rot) / 180 * Math.PI) * R);
context.lineTo(x + Math.cos((54 + 72 * i - rot) / 180 * Math.PI) * r,
y - Math.sin((54 + 72 * i - rot) / 180 * Math.PI) * r);
}
context.closePath();
context.fillStyle = '#fb3';
context.strokeStyle = '#fd5';
context.lineWidth = 3;
context.lineJoin = 'round';
context.fill();
context.stroke();
}

然而上面代码并不符合软件工程的设计原则,一个函数包含了很多功能(绘制星星和位移,旋转角度都放在一个方法里)。当需求发生变化时,例如将五角星变成圆或多边形,就需要重新修改整个方法。在图形学中任何的图形学都使用先绘制基本轮廓再根据需求进行图形变换。也就是说一个方法绘制原始图形的路径,一个方法对图形进行变换(位移,角度,大小...) , 用户也可以直接传一个图形的路径或方法,根据路径进行绘制。

图形变换

  • context.translate(x, y);   对canvas坐标系进行整体位移
  • context.rotate(angle);   给canvas画布添加旋转矩阵,顺时针方向默认旋转中心点是Canvas的左上角(0, 0)坐标点,如果希望改变旋转中心点,例如以Canvas画布的中心旋转,需要先使用translate()位移旋转中心点。

注意:以上两个方法平移,旋转的是坐标系,而非元素。因此,实际开发的时候,平移或旋转完毕,需要将坐标系再还原。使用save(),restore().

  

  • context.scale(x, y);用来缩放Canvas画布的坐标系,只是影响坐标系,之后的绘制会受此方法影响,但之前已经绘制好的效果不会有任何变化。因此下面代码虽然起始点一样,但是由于坐标系被放大,使得放大后的图形起始点改变。如果设置lineWidth,也会放大。使用时要注意。

context.strokeRect(50, 50, 100, 100);
context.scale(2, 2);
context.strokeRect(50, 50, 100, 100);

     for (var i = 0; i < 200; i++) {
var x = Math.random() * canvas.width;
var y = Math.random() * canvas.height;
var rot = Math.random() * 360;
var r = Math.random() * 10 + 10;
transDraw(context, x, y, r,rot);
} // 用户可以直接传一个图形的路径或方法,根据路径进行绘制。
function transDraw(context, x, y, r, rot){
context.save(); //将当前状态压入栈中。 context.translate(x, y);
context.scale(r, r);
context.rotate(Math.PI / 180 * rot); context.fillStyle = '#fb3'; drawPath(context);
context.fill();
context.restore(); //将变换后的坐标系恢复到之前状态
}
     //绘制一个图形路径,无旋转角度,偏移,大小设置为1的五角星
function drawPath(context) {
context.beginPath();
for (var i = 0; i < 5; i++) {
context.lineTo(Math.cos((18 + 72 * i) / 180 * Math.PI) ,
-Math.sin((18 + 72 * i) / 180 * Math.PI) ) ;
context.lineTo(Math.cos((54 + 72 * i) / 180 * Math.PI) * 0.5,
-Math.sin((54 + 72 * i) / 180 * Math.PI) * 0.5);
}
context.closePath();
}

绘制月亮

最外面的弧用半圆进行绘制,里面的弧使用画弧的arcTo()方法,传入的参数为:控制点,终止点,半径。

起始点,控制点,终止点这些都是根据不同的需求位置可变,所以我们需要根据可以可变的点求出同样可变的半径。以AOC为角,因为tan = 对边 / 邻边,所以根据下面的公式可以求出半径。

AC和AH的长度很好求,而AC的长度只需要使用两点间距离公式

具体代码,还是使用先绘制原始路径,在进行变换。

变换函数drawMoon传入的参数d代表arcTo的控制点的横坐标

    function drawMoon(context, d, x, y, R, rot, fillColor) {
context.save();
context.translate(x, y);
context.scale(R, R);
context.rotate(Math.PI / 180 * rot);
MoonPath(context, d);
context.fillStyle=fillColor; context.fill();
context.restore();
}
function MoonPath(context, d) {
context.beginPath();
context.arc(0, 0, 1, Math.PI * 0.5, Math.PI * 1.5, true); //绘制外面的弧
context.arcTo(d, 0, 0, 1, distance(0, -1, d, 0) / d); //绘制里面的弧
}
function distance(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
}

最后就可以结合上面的星星月亮来绘制下面的一幅图

canvas绘制星星和月亮的更多相关文章

  1. HTML5学习总结——canvas绘制象棋(canvas绘图)

    一.HTML5学习总结——canvas绘制象棋 1.第一次:canvas绘制象棋(笨方法)示例代码: <!DOCTYPE html> <html> <head> & ...

  2. 用canvas绘制折线图

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. 封装 用canvas绘制直线的函数--面向对象

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. 学习笔记:HTML5 Canvas绘制简单图形

    HTML5 Canvas绘制简单图形 1.添加Canvas标签,添加id供js操作. <canvas id="mycanvas" height="700" ...

  5. canvas绘制经典折线图(一)

    最终效果图如下: 实现步骤如下:注-引用了jQuery HTML代码 <!doctype html> <html lang="en"> <head&g ...

  6. Canvas绘制图形

    1.Canvas绘制一个蓝色的矩形 <!DOCTYPE html> <html> <head lang="en"> <meta chars ...

  7. [canvas]利用canvas绘制自适应的折线图

    前段时间学习了用canvas绘制折现图,且当画布变换大小,折现图会随之变化,现附上代码 <!DOCTYPE html> <html lang="en"> & ...

  8. 使用Canvas绘制背景图

    原文  http://www.imququ.com/post/use-canvas-as-background-image.html 最近iCloud Web的Beta版换了UI,整体风格变得和iOS ...

  9. html5的canvas绘制迷宫地图

    canvas标签一直是html5的亮点,用它可以实现很多东西.我想用它来绘画像迷宫那样的地图.借助到的工具有瓦片地图编辑器tiled(点击跳转到下载链接). 如图:如果你想要画像这样的迷宫地图,如果不 ...

随机推荐

  1. C#_.NetCore_WebAPI项目_EXCEL数据导出(ExcelHelper_第二版_优化逻辑)

    项目需要引用NPOI的Nuget包:DotNetCore.NPOI-v1.2.2 本篇文章是对WebAPI项目使用NPOI操作Excel时的帮助类:ExcelHelper的改进优化做下记录: 备注:下 ...

  2. 域控权限提升PTH攻击

    0x01 漏洞利用条件 1.被pth攻击的计算机未打补丁(KB2871997)2.拿到一台域成员主机并且拿到管理员组的域用户的NTML 3.对方主机存在相同账号并且是管理员组成员 0x02 本地用户N ...

  3. 轻松玩转windows之redis实战

    Redis是一个常用的键值对数据库.本篇分享一下如何轻松在睿江云上实现基于windows的redis开发环境. 1. 登录睿江云 点击右上角登录框 ​ 进入登录页面,输入账号密码登录 ​ 进入控制台, ...

  4. flyway 非常坑爹的中文乱码问题

    flyway 也真是够了, 动不动乱码,烦死了! 我的 命令是这样的: flyway  -driver=com.mysql.jdbc.Driver -user=root -password=12345 ...

  5. Comet OJ - Contest #11 B题 usiness

    ###题目链接### 题目大意:一开始手上有 0 个节点,有 n 天抉择,m 种方案,在每天中可以选择任意种方案.任意次地花费 x 个节点(手上的节点数不能为负),使得在 n 天结束后,获得 y 个节 ...

  6. 东芝开发板驱动OLED模块显示LOGO图片

    前言 在之前的两篇评测文章: 使用系统定时器SysTick实现精确延时微秒和毫秒函数 东芝MCU实现位带操作 介绍了系统SysTick实现精确延时,GPIO的输入输出使用,并实现了位带方式操作GPIO ...

  7. 避免网络爬虫IP被封的策略

    背景 这两天一直在搞Java网络爬虫作为Java课程设计,目标是爬取豆瓣电影top250的影评,之后可能还需要进行情感分析,当然这就不是爬虫的内容了.我的爬虫程序在一开始只是一个页面一个页面的爬取信息 ...

  8. Java对象 POJO和JavaBean的区别

    转载自https://www.jianshu.com/p/224489dfdec8 这篇博客很通俗易懂的讲明白了什么是POJO,对于刚开始学开发做java项目的菜鸟来说,很有帮助,网课老师是不会讲这些 ...

  9. C# copy source directory files with original folder to the destination path

    private static void PathCopyFilesWithOriginalFolder() { ; try { string sourceDir = @"E:\Source& ...

  10. Filter Lookup Editor Data Source 筛选器查找编辑器数据源

    In this lesson, you will learn how to filter the data displayed by a lookup editor. This editor is s ...