原文地址:http://jeffzhong.space/2017/10/26/solar/
  学习canvas有一段时间了,顺便写个小项目练手,该项目用到的知识点包括:

  1. ES6面向对象
  2. 基本的三角函数
  3. canvas部分有:坐标变换,渐变,混合模式,线条和图形的绘制。

实际效果: solar system(推荐在chrome或safari下运行)

场景

  首先建立场景类,主要用来组织管理对象,统一更新和绘制对象。这里用到了ES6的类语法,构造函数建立对象列表属性planets,绘制背景方法drawBG,使用requestAnimationFrame反复执行的动画方法animate

  绘制背景使用到了径向渐变:createRadialGradient(x1,y1,r1,x2,y2,r2); 该渐变主要用于创建两个圆相交过渡效果,如果前后两个圆心相同(x1==x2 && y1==y2),则会构造同心圆样式的渐变。 这样我们就以太阳为中心的黄色调渐变到黑色,最后用fillRect填充整个背景。

    //场景class Stage {constructor(){this.planets=[];}init(ctx){ctx.translate(W/2,H/2);//坐标重置为中间this.animate(ctx);}//绘制背景drawBG(ctx){ctx.save();ctx.globalCompositeOperation = "source-over";var gradient=ctx.createRadialGradient(0,0,0,0,0,600);gradient.addColorStop(0,'rgba(3,12,13,0.1)');gradient.addColorStop(1,'rgba(0,0,0,1');ctx.fillStyle=gradient;// ctx.fillStyle='rgba(0,0,0,0.9)';ctx.fillRect(-W/2,-H/2,W,H);ctx.restore();}//执行动画animate(ctx){var that=this,startTime=new Date();(function run(){that.drawBG(ctx);that.planets.forEach(item=>{item.update(startTime);item.draw(ctx);});requestAnimationFrame(run);}());}}

星球

  然后建立星球基类,除构造函数,还有更新位置角度的方法Update,对象绘制方法draw。之后所有的星球,都会初始化该类或者继承该类建立对应星球。

  行星绕太阳做圆周运动,这个可以用三角函数根据角度和半径求出x,y,但还有更加方便的方法,那就是使用canvas提供的坐标旋转方法rotate,以360度为一个周期。

    /*** 星球基类*/class Planet{/*** @param  {Number} x         x坐标* @param  {Number} y         y坐标* @param  {Number} r         半径* @param  {Number} duration  周期(秒)* @param  {Object} fillStyle * @param  {Object} blurStyle */constructor(x,y,r,duration,fillStyle,blurStyle){this.x=x;this.y=y;this.r=r;this.duration=duration;this.angle=0;this.fillStyle=fillStyle;this.blurStyle=blurStyle;}update(startTime){this.angle=Tween.linear(new Date()-startTime,0,Math.PI*2,this.duration*1000);}draw(ctx){ctx.save();ctx.rotate(this.angle);// ctx.translate(this.x,this.y);drawCircle(this.x,this.blurStyle.color);ctx.beginPath();// ctx.globalCompositeOperation = "lighter";ctx.fillStyle=this.fillStyle;ctx.shadowColor=this.blurStyle.color;ctx.shadowBlur=this.blurStyle.blur;             // ctx.arc(0,0,this.r,Math.PI*2,false);ctx.arc(this.x,this.y,this.r,0,Math.PI*2,false);ctx.fill();ctx.restore();}};

太阳

  开始建立第一个对象-太阳,继承上面的星球基类Planet,重写draw方法

    /*** 太阳*/class Sun extends Planet{draw(ctx){ctx.save();ctx.beginPath();ctx.globalCompositeOperation = "source-over";ctx.fillStyle=this.fillStyle;ctx.shadowColor=this.blurStyle.color;ctx.shadowBlur=this.blurStyle.blur;             ctx.arc(this.x,this.y,this.r,0,Math.PI*2,false);ctx.fill();ctx.restore();  }}

土星

  土星有美丽的土星环,所以也继承出一个单独的类,重写draw方法,其中土星环比较麻烦,建立了很多颜色节点的径向渐变。

    /*** 土星*/class Saturn extends Planet{draw(ctx){ctx.save();ctx.rotate(this.angle);drawCircle(this.x,this.blurStyle.color);ctx.beginPath();ctx.fillStyle=this.fillStyle;           ctx.arc(this.x,this.y,this.r,Math.PI*2,false);ctx.fill();//土星光环ctx.globalCompositeOperation = "source-over";var gradient=ctx.createRadialGradient(this.x,this.y,0,this.x,this.y,this.r 25);var startStop=(this.r 3)/(this.r 24);gradient.addColorStop(startStop,'#282421');gradient.addColorStop(startStop 0.06,'#282421');gradient.addColorStop(startStop 0.1,'#7e7966');gradient.addColorStop(startStop 0.18,'#706756');gradient.addColorStop(startStop 0.24,'#7e7966');gradient.addColorStop(startStop 0.25,'#282421');gradient.addColorStop(startStop 0.26,'#282421');gradient.addColorStop(startStop 0.27,'#807766');gradient.addColorStop(1,'#595345');ctx.fillStyle=gradient;ctx.beginPath();ctx.arc(this.x,this.y,this.r 24,0,Math.PI*2,true);ctx.arc(this.x,this.y,this.r 3,0,Math.PI*2,false);ctx.fill();ctx.restore();  }}

建立星球

  接着开始初始化星球对象,包括太阳和八大行星,然后所有的星球颜色都使用了径向渐变,这样更加的美观。这里给出太阳,水星,土星的例子,其他的行星如此类推。

    // 初始化场景类var stage=new Stage();// sunvar sunStyle=ctx.createRadialGradient(0,0,0,0,0,60);sunStyle.addColorStop(0,'white');sunStyle.addColorStop(0.5,'white');sunStyle.addColorStop(0.8,'#ffca1e');sunStyle.addColorStop(1,'#b4421d');var sun=new Sun(0,0,60,0,sunStyle,{color:'#b4421d',blur:300});stage.planets.push(sun);// mercuryvar mercuryStyle=ctx.createRadialGradient(100,0,0,100,0,9);mercuryStyle.addColorStop(0,'#75705a');mercuryStyle.addColorStop(1,'#464646');var mercury=new Planet(100,0,9,8.77,mercuryStyle,{color:'#464646'});stage.planets.push(mercury);//saturn var saturnStyle=ctx.createRadialGradient(500,0,0,500,0,26);saturnStyle.addColorStop(0,'#f2e558');saturnStyle.addColorStop(1,'#4c4a3b');var saturn =new Saturn(500,0,26,1075.995,saturnStyle,{color:'#4c4a3b'});stage.planets.push(saturn);

小行星带

  当然还有火星和木星之间的小行星带,同理继承星球基类,这里用到了图像混合模式globalCompositeOperation,使用xor可以和背景对比度没那么突兀。当然还有其他属性值,比如source-over, lighter等。这里我们随机生成了300个对象,一样填充进场景类的planets属性统一更新绘制。

    /*** 小行星*/class Asteroid extends Planet{draw(ctx){ctx.save();ctx.rotate(this.angle);ctx.beginPath();ctx.globalCompositeOperation = "xor";ctx.fillStyle=this.fillStyle;           ctx.arc(this.x,this.y,this.r,0,Math.PI*2,false);ctx.fill();ctx.restore();  }}function createAsteroids(){var asteroid=null,x=300,y=0, r=2,rd=300,angle=0, d=283, color='#fff';for(var i=0;i<400;i  ){rd=Random(300,320);angle=Random(0,Math.PI*2*1000)/1000;x=Math.round(Math.cos(angle)*rd);y=Math.round(Math.sin(angle)*rd);r=Random(1,3);d=Random(28.3,511);color=getAsteroidColor();// console.log(angle,color);asteroid = new Asteroid(x,y,r,d,color,{color:color,blur:1});stage.planets.push(asteroid);}}

彗星

  基本快完成了,但我们除此之外,可以再添加做椭圆运动的彗星,这样更加酷。一样随机生成20个彗星填充进场景类统一更新绘制。

    /*** 彗星*/class Comet {constructor(cx,cy,a,b,r,angle,color,duration){this.a=a;this.b=b;this.r=r;this.cx=cx;this.cy=cy;this.x=0;this.y=0;this.color=color;this.angle=angle;this.duration=duration;}update(startTime){var t=Tween.linear(new Date()-startTime,0,Math.PI*2,this.duration*1000);this.x=this.cx this.a*Math.cos(this.angle t);this.y=this.cy this.b*Math.sin(this.angle t);}draw(){ctx.save();ctx.rotate(this.angle);//画运动轨迹ctx.lineWidth=0.5;ctx.strokeStyle='rgba(15,69,116,0.2)';Shape.ellipse(ctx,this.cx,this.cy,this.a,this.b);//画球ctx.beginPath();// ctx.globalCompositeOperation = "lighter";ctx.globalCompositeOperation = "source-atop";ctx.shadowColor=this.color;ctx.shadowBlur=1;ctx.fillStyle=this.color;ctx.arc(this.x,this.y,this.r,0,Math.PI*2,false);ctx.fill();//画尾迹ctx.restore();}}function createComets(){var l=180,a=800,b=300,cx=a-l,cy=0,r=3,duration=30,angle=0,color='#fff',comet = null;for(var i=0;i<20;i  ){l=Random(120,350)a=Random(600,1000);b=a/Random(1,3);cx=a-l;r=Random(2,4);angle=Random(0,Math.PI*2*1000)/1000;color=getCometColor();duration=Random(20,100);stage.planets.push(new Comet(cx,cy,a,b,r,angle,color,duration));}}

运动轨迹

  最后的细节,就是标识出行星圆周运动的轨道,当然最简单的是按运动半径画个圆。但我们用线性渐变添加好看的尾迹,这样效果更好

    function drawCircle(r,color){var hsl=Color.hexToHsl(color);ctx.lineWidth=1;// ctx.strokeStyle='rgba(176,184,203,0.3)';// ctx.arc(0,0,this.x,Math.PI*2,false);// ctx.stroke();var gradient=ctx.createLinearGradient(-r,0,r,0);gradient.addColorStop(0,'hsla(' hsl[0] ',' hsl[1] '%,0%,.3)');gradient.addColorStop(0.6,'hsla(' hsl[0] ',' hsl[1] '%,50%,.9)');gradient.addColorStop(1,'hsla(' hsl[0] ',' hsl[1] '%,80%,1)');ctx.strokeStyle=gradient;// ctx.shadowColor=color;// ctx.shadowBlur=4;    ctx.beginPath();ctx.arc(0,0,r,0,Math.PI,true);ctx.stroke();}

最后

  所有的部分都已经完成,我们只需要启动场景类即可

    createAsteroids();createComets();stage.init(ctx);

更多专业前端知识,请上 【猿2048】www.mk2048.com

canvas绘制太阳系相关推荐

  1. HTML5 canvas绘制太阳系各行星(包括月球的公转)

    HTML5 canvas绘制太阳系   看了好多canvas绘制太阳系行星,他们都忽略了月亮,虽然月亮不是行星,但是绘图少了月亮也就没有挑战性了,今天我就计算了一下月亮的轨迹,然后按照公转的比例画了上 ...

  2. 通过Canvas绘制一个小型太阳系

    绘制一个地球绕太阳转,月球绕地球转的小型太阳系 运行效果如下          代码如下 <!DOCTYPE html> <html><head><meta ...

  3. canvas绘制的文字如何换行

    <html><head><title>canvas绘制的文字如何换行</title><style type="text/css" ...

  4. HTML5 canvas绘制雪花飘落

    Canvas是HTML5新增的组件,它就像一块幕布,可以用JavaScript在上面绘制各种图表.动画等.没有Canvas的年代,绘图只能借助Flash插件实现,页面不得不用JavaScript和Fl ...

  5. canvas绘制时钟

    听了慕课网Sliav Zhou 的课程canvas绘制时钟,记录下来的代码,每句做了注解便于以后学习,原先每次边听别的课边敲码,错误百出,明明原封不动复制的代码,就会出错,还找不到原因,今天可能运气好 ...

  6. canvas绘制圆形

    canvas绘制圆形的思路: 1.创建路径 XXX.beginpath(); 2.创建圆形的路径: 3.关闭路径:XXX.closepath(); 路径不关闭也能绘制出图形 4.设定绘制样式. 创建圆 ...

  7. java canvas 画图片_[Java教程][HTML5] Canvas绘制简单图片

    [Java教程][HTML5] Canvas绘制简单图片 0 2016-05-13 13:00:04 获取Image对象,new出来 定义Image对象的src属性,参数:图片路径 定义Image对象 ...

  8. html5 canvas绘制圆形进度实例

    2019独角兽企业重金招聘Python工程师标准>>> html5 canvas绘制圆形进度实例 <canvas id="test" width=200 h ...

  9. 【Android 应用开发】Canvas 绘制文字 ( 文字尺寸测量 | 基线绘制 )

    文章目录 I . 文字尺寸测量 II . 基线绘制 I . 文字尺寸测量 1 . 精准绘制需求 : Canvas 绘制文字时 , 有时需要精准的控制文字的绘制 , 如绘制到指定的区域 , 居中 , 或 ...

  10. 小猿圈html5教程之canvas绘制线段方法

    HTML5现在是时下较火的编程语言之一,但是对于怎么学习很多朋友都是不了解的,不知道从何处下手,针对以上内容小猿圈web前端讲师每天会分享一个web前端知识,希望对你的前端学习有一定的帮助,今天分享的 ...

最新文章

  1. LeetCode简单题之最少操作使数组递增
  2. 常用插值算法介绍(二)
  3. 【Rational Rose使用笔记】用例图
  4. 关于经典机器学习算法的一个总结
  5. java integer_Java之Integer类
  6. 光驱安装centos7系统过程_centos7可以ping通外网_可以ping通内网其他机器_但是其他机器就是ping不通centos7_太神奇了---linux工作笔记041
  7. iptables第二部分
  8. Collectors.toSet()
  9. Latex 常用代码
  10. 查看git brach_Excel Go Brach – Excelebrations
  11. lsd 特征点匹配代码_直线匹配-LSD算法
  12. 关于五笔字型学习五笔难拆汉字学习总结
  13. # Python第一节课
  14. Ansible Playbook 变量与 register 详解
  15. app直播源代码是如何实现直播间小游戏的
  16. xuelipay 个人即时到账收款平台 原理及源码详解 支持支付宝微信
  17. Android绘制饼状图
  18. 国内高速下载 GitHub 下载单文件夹和 release 的方法
  19. html布局结构瀑布流,三种方式实现瀑布流布局
  20. windows系统遇到的问题?

热门文章

  1. 股票中,什么是净资产收益率,有什么作用?
  2. solidworks装配教程:快速给装配体添加新零件
  3. Java手机列表(供开发者参考)
  4. 优秀的免版权图库软件推荐,软件内图片均可免费商用。
  5. H3C运维审计系统 Web配置指导(笔记)
  6. 大学十年(一个程序员的路程)
  7. html5 3d动画效果代码,精选9款迷人的HTML5 3D动画效果及源码
  8. matlab的零极点分布图,matlab零极点分布图
  9. 华为手机鸿蒙切换主页,京东APP可一键切换“华为鸿蒙版界面”:简洁多了
  10. 加减乘除等符号大全中英对照,在英语中的用法