点击上方“程序员黑叔”,选择“置顶或者星标”

你的关注意义重大!

先看最终效果[2]

先说明一下,此效果启发于第二本参考书。

中心红色球是太阳,水蓝色小球是地球。可以看出地球的运行轨道是椭圆,验证了开普勒三定律的第一条。在近日点运行速度比较快,远日点比较慢,符合常识。

你猜测我写这个效果用了多长时间?

不到半个小时吧,其实掌握原理后实现起来还是比较快的。

原理相对来说还是简单的,前提是要使用向量工具。

1. 用向量来思考问题

本系列的前几篇文章,都是使用 x、y 轴分量来计算小球的物理矢量。

fx = f * Math.cos(angle)
fy = f * Math.sin(angle)
ax = fx / ball.m
ay = fy / ball.m
vx += ax
vy += ay
ball.x += vx
ball.y += vy

上述代码中,f 是力,m 是质量,a 是加速度,v 是速度。而带后缀的是相应矢量的分量,比如 fx 是力矢量 f 的横轴分量。

上述运算,本质上还是使用小学的加减法,没有真正用到矢量或者说向量。

假设我们向量 p 表示小球当前位置,向量 v 表示当前速度,那么下一帧的小球的位置为下图中的粉色向量。不用再分别计算 x 轴 和 y 轴的分量。

为了表示向量这一数据类型,我们简单地封装一个 Vector 类:

class Vector {constructor(x, y) {this.x = xthis.y = y}scale(n) {this.x *= nthis.y *= nreturn this}mag() {return Math.sqrt(this.x * this.x + this.y * this.y);}normalize() {var m = this.mag()if (m != 0 && m != 1) {this.scale(1 / m)}return this}add(other) {this.x += other.xthis.y += other.yreturn this}sub(other) {this.x -= other.xthis.y -= other.yreturn this}static add(one, other) {return new Vector(one.x + other.x, one.y + other.y)}static sub(one, other) {return new Vector(one.x - other.x, one.y - other.y)}static dist(one, other) {var dx = one.x - other.xvar dy = one.y - other.yreturn Math.sqrt(dx * dx + dy * dy)}
}

这些向量操作都很简单,比如 add 表示当前向量加上一个新向量,mag 用来求取向量大小,scale 用来放缩向量的大小,normalize 用于计算单位向量等等。虽然底层仍是 x、y 分量用于计算。但是我们思维的最小单位是向量,维度高级一些。

比如之前的代码用向量的形式表示:

a = f.scale(1 / ball.m)
v.add(a)
ball.p.add(v)

有了向量工具,处理万有引力公式起来就很 easy 了。

2. 动画原理

这部分,我们来大体看下开篇动画的原理,看看是否真的简单。

地球人都知道牛顿的万有引力定律这一伟大发现:

任意两个质点有通过连心线方向上的力相互吸引。该引力大小与它们质量的乘积成正比与它们距离的平方成反比,与两物体的化学组成和其间介质种类无关。

其中 G 是万有引力常数,动画里我们简化为 1 就行。

把公式写成代码:

var dist = Vector.dist(sun.p, earth.p)
var f = sun.m * earth.m / (dist * dist)

而这个 f 目前仍是标量,只有大小,没有方向。地球受到的万有引力,方向应该是朝向太阳的,因此完整代码是:

function gravity (sun, earth) {var dist = Vector.dist(sun.p, earth.p)var f = sun.m * earth.m / (dist * dist)var vec = Vector.sub(sun.p, earth.p)return vec.normalize().scale(f)
}

之所以封装成函数是因为地日之间的万有引力是时刻发生变化的。其中向量 vec 方向是朝向太阳的,对其取单位向量,并放缩大小为 f。这样,最终返回的结果是引力向量。

因此地球的运动核心代码很容易写出来:

var g = gravity(sun, earth)
var a = g.scale(1 / earth.m)
v.add(a)
earth.p.add(v)

核心原理就是这些,剩下就是实现了。

3. 实现

太阳和地球采用的都是小球模型:

class Ball{constructor() {this.p = new Vector(0, 0)this.m = 0this.radius = 20this.color = 'white'}draw(context) {context.save()context.translate(this.p.x, this.p.y)context.beginPath()context.arc(0, 0, this.radius, 0, 2 * Math.PI)context.fillStyle = this.colorcontext.fill()context.restore()}
}

这段代码不是本系列第一次出现了,唯一不同的是原先的 this.x 和 this.y 改用向量 this.p 替换了。

初始化太阳和地球:

var sun = new Ball()
sun.radius = 30
sun.color = 'red'
sun.p = new Vector(canvas.width / 2, canvas.height / 2)
sun.m = 1000var earth = new Ball()
earth.radius = 3
earth.color = 'aqua'
earth.p = new Vector(canvas.width / 2 + 100, canvas.height / 2 + 80)
earth.m = 1

其中太阳和地球的质量比是 1000: 1。地球的位置比较随便选取了一个位置。

接下来就是原理的核心代码,其中我们假设太阳不动的。

;(function drawFrame() {window.requestAnimationFrame(drawFrame)context.clearRect(0, 0, canvas.width, canvas.height)var g = gravity(sun, earth)var a = g.scale(1 / earth.m)v.add(a)earth.p.add(v)earth.draw(context)sun.draw(context)
})()

这里有一个至关重要的点,是地球需要有个初始速度 v 。

不同大小和方向的速度,地球的运行轨道会有所不同。假如初始速度为 0 向量的话,根据万有引力,地球将会撞向太阳:

当然这里地球撞上太阳后,没有销毁,但是地球迅速远离太阳。因为速度比较快,万有引力再也拉不回来了。这其实就是三体小说中的“引力弹弓”。

我们让太阳尺寸小点,速度选择为:

var v = new Vector(-0.3, 1)

引力弹弓效果将更好些:

假如速度选择为:

var v = new Vector(-0.8, 1).scale(2.2)

小球将会走圆形轨道:

你可以随便调节参数,尝试其他情形,看看效果。

点击查看最终效果和完整代码[3]

感谢你看到这里,希望有所帮助。

本文完。


下面的内容是关于本系列的介绍。

2019年末,本人立了个flag,2020年要研究透canvas动画技术。

(图中二维码是我的唯一微信号,如有掘友想加的,麻烦备注下掘金哈。)

在这个系列,我想写一些常见动画知识,本文是第 5 篇,篇幅可能会长短不一。更多的请查看我的个人主页,或者《系列目录》[4]

因为篇幅问题,根据以往的经验,赞数不会太多,毕竟大家都喜欢给那种短时间看不完的文章点赞。嗯,我好像也是这样。^_^

其实写文章,主要还是给自己看的,算是自我进步的一个见证吧。抱着这种心态也许能好些。

另外关于canvas技术,我目前完整看完了3本书。算是过了基础一关。

1.《HTML5 Canvas核心技术》[5]

2.《HTML5+JavaScript动画基础》[6]

3.《WebGL编程指南》[7]

本系列一些文章可能会参考里面的知识体系,对于一些属于领域共识知识,如有局部雷同,只能说:“自己凭本事学来的,怎能算抄袭。。。”。

开玩笑了,想法来源能提一句还是要提一句的。特别喜欢《精英日课》文章里的一段话:

至于文章内容,canvas的API,本系列可能不会准备逐条介绍了,还请初学的童鞋见谅哈。MDN都有的,挺详细的。同时,文章中遇到的还是会简单提下。主要核心是阐述一些技巧和原理层面的知识个人理解吧。另外也打算分析一些codepen上炫酷动画的实现原理,如果有时间可能会分析几个动画引擎,当然都是2D的。

最后

  1. 感谢阅读,欢迎分享给身边的朋友,

  2. 记得关注噢,黑叔带你飞!

亲,点这涨工资 

万有引力特效?我用canvas就能实现了相关推荐

  1. html银河特效编码,html5 canvas银河星系动画特效

    特效描述:html5 canvas 银河星系动画特效.html5 canvas绘制闪闪发光移动的银河星系背景动画特效.(上传服务器正常演示,本地无法直接预览) 代码结构 1. 引入JS 2. HTML ...

  2. 6个网页背景特效源码 canvas+three.js科技贴图 webgl源码

    隧道穿梭特效 粒子矩阵特效 几何随机变换特效 下载地址: 6个网页背景特效源码 canvas+three.js科技贴图 webgl源码-素材美

  3. html5页面特效网,HTML5 Canvas打造超梦幻网页背景特效

    这是一款使用javascript和HTML5 Canvas来制作的超梦幻网页背景特效.该网页背景特效使用两个canvas元素进行重叠,制作出圆形光影运动的梦幻效果,非常的炫酷. 使用方法 HTML结构 ...

  4. 五十个html js特效动画,html5 canvas酷炫的月食动画特效

    特效描述:html5 canvas 月食动画特效.html5月食动画 代码结构 1. 引入JS 2. HTML代码 varying vec3 vNormal; void main() { vNorma ...

  5. 表白html特效在线,html5 canvas酷炫表白爱心动画特效

    特效描述:酷炫表白动画 表白爱心动画 动画特效.html5爱心动画 代码结构 1. 引入JS 2. HTML代码 var container; var camera, scene, renderer; ...

  6. H5炫酷特效系列2——canvas特效-炫酷的心

    之前已经有了一个满屏幕红心的案例,这次带来一个更加炫酷的心型炫酷动效,直接上图,有兴趣的就继续往下看,没兴趣直接过. 屏幕上眼花缭乱的心,不停的冲击着你的视线,让那些少女心砰砰直跳,绝对表白利器,同志 ...

  7. H5炫酷特效系列1——canvas满屏幕变换爱心示例

    啥都不说,先上效果图,同志们觉得满意就继续看,不中意直接过. 效果为满屏幕的红心到处乱窜,红心自动变换大小和透明度,代码也不多,同志们直接复制就可以运行查看. <!DOCTYPE html> ...

  8. HTML粒子漩涡特效,使用HTML5 Canvas绘制经典漩涡粒子特效

    JavaScript 语言: JaveScriptBabelCoffeeScript 确定 // create a canvas element var canvas = document.creat ...

  9. html 流动效果,html5 canvas流动的海浪特效

    特效描述:html5canvas 流动的海浪特效.html5 canvas流动的海浪特效 代码结构 1. 引入JS 2. HTML代码 'use strict'; var gui = new dat. ...

最新文章

  1. struts2中struts.xml和web.xml文件解析及工作原理
  2. 如何配置 SQL Server 2005 以允许远程连接
  3. 在2003 server系统上部署DHCP服务器
  4. Webwork 学习之路【02】前端OGNL试练
  5. java 复制文件_Java中复制文件的4种方法
  6. 如何只导出mysql表结构_navicat如何只导出表结构
  7. 关于提高自己Java水平十大技术
  8. 屏幕旋转后_网易哒哒H5又又叒刷屏了,TCL·XESS 旋转智屏竟然是一大亮点
  9. 制作stick侧边栏导航效果
  10. 《数据算法:Hadoop_Spark大数据处理技巧》艾提拉笔记.docx 第1章二次排序:简介 19 第2章二次排序:详细示例 42 第3章 Top 10 列表 54 第4章左外连接 96 第5
  11. 如何保证战略落地_企业战略如何实现落地
  12. 基于生物特征密钥生成研究 ------应用于区块链领域密钥的生成办法
  13. springcloud阿里巴巴五大组件_阿里巴巴内部独家微服务全解手册已“重现江湖”大厂核心技术,你确定不了解一下?...
  14. 期货卖出平仓价和买入平仓价(期货平仓价和结算价)
  15. 西南民族大学第十届校赛 题解
  16. MAC版 破解百度云、百度网盘限速的方法
  17. 卫生专业计算机考试,快熟悉一下2019卫生专业技术资格考试人机对话系统
  18. 配置Linux发送日志到syslog服务器
  19. java报表查询 跟 语句查询区别_Java报表FineReport在医院院长查询分析系统中有什么用...
  20. C语言自增自减运算、判断奇偶数、三角形面积

热门文章

  1. Fina Cut Pro X免费下载,学习,文档
  2. 学生台灯用暖光好还是白光好?光线柔和的暖光护眼灯推荐
  3. (干货) 差分对信号的长度和间距基于什么而界定的,一文了解。
  4. BFGS算法及其matlab实现
  5. 华为猫复活记(ADSL猫固件升级失败修复)
  6. springboot 自定义切面类
  7. node.js sharp 裁剪图片方形为圆形,矩形
  8. ios添加真机调试方法,和xcode查询udid方法
  9. 【论坛精华】个人微信小游戏发布流程
  10. 高尿酸痛风饮食红黑榜