实现球体碰撞,使用这个库就够了
一、简述
大家在用Canvas实现球体碰撞的动画场景时是否感觉无从下手,或者是知道怎么去实现,但是要进行大量的计算,考虑非常多的细节,比如要考虑将外力分解为水平和垂直两个方向,然后考虑各种碰撞的检测,发生重叠后的修正,还有可能考虑引力方向和大小、透明度渐变等等这些,思考这些个计算逻辑时真的很让人头大,今天我就和大家分享一个非常好用的库,一个专门用于在Canvas上实现球体碰撞和球体交互场景的库–sphere-collision,通过简单配置便可快速实现碰撞效果,而且还提供了钩子函数,扩展性极强,让你实现想要的效果。
二、案例展示
下面展示几个案例的实现效果,这些都是使用这个库实现的动画效果,只要涉及到球体碰撞或球体交互的场景都可以使用这个库。
1.探照灯效果
2.球体碰撞交互效果
3.消灭行星小游戏
4.各类球体自由落体交互效果
5. 炫酷倒计时动画
以上案例源码均在visualization-collection开源项目中,github地址:https://github.com/hepengwei/visualization-collection
三、基本用法
安装
npm i sphere-collision
使用
import SphereCollision from "sphere-collision";const canvasWidth = 600; // 画布宽度
const canvasHeight = 600; // 画布高度
const globuleRadius = 60; // 球半径const beforeDrawGlobules = (sphereCollision) => {const { ctx } = sphereCollision;// 绘制整个画布的背景色ctx.clearRect(0, 0, canvasWidth, canvasHeight);ctx.beginPath();ctx.fillStyle = "#000000";ctx.fillRect(0, 0, canvasWidth, canvasHeight);
};const canvas = document.getElementById("myCanvas");
if (canvas) {canvas.width = canvasWidth;canvas.height = canvasHeight;const ctx = canvas.getContext("2d");// 实例化SphereCollision对象const sphereCollision = new SphereCollision(ctx,canvas,[{initX: 400,initY: 400,vx: 6,vy: 3,radius: globuleRadius,},],{ beforeDrawGlobules });// 开使执行动画sphereCollision.start();
}
四、API文档
SphereCollisionC
参数(顺序从上往下依次传入) | 数据类型 | 说明 | 默认值 | 是否必需 |
---|---|---|---|---|
ctx | CanvasRenderingContext2D | Context对象 | null | 是 |
canvas | HTMLCanvasElement | Canvas对象 | null | 是 |
globuleOptionsList | GlobuleOptions[] | 初始化球体的配置列表 | [] | 否 |
options | SphereCollisionOptions | 配置参数 | SphereCollisionOptions | 否 |
属性 | ||||
ctx | CanvasRenderingContext2D | Context对象 | ||
canvas | HTMLCanvasElement | Canvas对象 | ||
frameId | number | requestAnimationFrame方法返回的ID | ||
globuleList | GlobuleC[] | 保存所有球体实例的列表 | ||
animationState | enum AnimationState{“waitStart”,“inAnimation”,“stop”} | 当前动画状态 | ||
mousePos | MousePos | 当前鼠标在Canvas中的位置坐标 | ||
prevMousePos(v1.1.0新增) | MousePos | 前一次鼠标在Canvas中的位置坐标 | ||
isMouseDown(v1.1.0新增) | boolean | 当前鼠标在Canvas中是否按下 | ||
mouseDownPos(v1.1.0新增) | MousePos | 鼠标在Canvas中按下时的位置坐标 | ||
mouseInGlobuleList(v1.1.0新增) | GlobuleC[] | 当前鼠标所在球体中的球体实例列表 | ||
方法 | ||||
start | () => void | 必须调用该方法,Canvas才渲染,开始执行相关动画 | ||
createGlobule | (globuleOptions: GlobuleOptions) => Globule | 创建球体实例的方法 | ||
updateGlobuleList | (newGlobuleList: GlobuleC[]) => void | 更新球体实例列表,用于动态增加或减少球体实例 | ||
stop | () => void | 停止整个frame动画 | ||
GlobuleOptions
属性 | 数据类型 | 说明 | 默认值 | 是否必需 |
---|---|---|---|---|
id | any | 任意值,可存放数据 | 否 | |
initX | number | 初始x坐标(向右为正方向) | 0 | 否 |
initY | number | 初始y坐标(向下为正方向) | 0 | 否 |
vx | number | 在水平方向的速度(向右为正方向) | 0 | 否 |
vy | number | 在垂直方向的速度(向下为正方向) | 0 | 否 |
radius | number | 半径 | 10 | 否 |
color | string | 颜色 | “#666666” | 否 |
isPureColor(v1.1.3新增) | boolean | 是否为纯色 | false | 否 |
alpha | number | 透明度 | 1 | 否 |
alphaChangeV | number | 透明度改变的速度(正数增加,负数减小) | 0 | 否 |
bgImg | string | 背景图片 | “” | 否 |
collisionLossV | number | 碰撞时的速度损失 | 0 | 否 |
moveLossV | number | 移动时的速度损失 | 0 | 否 |
gDirection | “toInit” | “toBottom” | “toTop” | “toLeft” | “toRight” | 引力方向。“toInit”,指向球体的初始位置;“toBottom”,指向正下方;“toTop”,指向正上方;“toLeft”,指向正左方;“toRight”,指向正右方(后四个为v1.1.0新增) | 否 | |
gCoefficient | number | 引力系数 | 0 | 否 |
requiredMouseInteraction | boolean | 是否需要鼠标交互 | false | 否 |
mouseInteractionBehavior(v1.1.0新增) | “over” | “drag” | 鼠标交互行为。“over”,鼠标穿过;“drag”,鼠标拖拽 | 当requiredMouseInteraction为true时,默认值为"over",当为false时,则没有默认值 | 否 |
fixedPos | boolean | 是否固定位置 | false | 否 |
receiveOutForce | boolean | 是否接受外力 | true | 否 |
receiveWallForce | boolean | 是否接受墙的力(与墙体发生碰撞) | true | 否 |
resistanceWallDirection(v1.1.3新增) | Direction[] | 有阻力的墙的方向 | [“bottom”, “top”, “left”, “right”] | 否 |
onlyCheckCollision | boolean | 当不接受外力时,是否检测碰撞(检测碰撞相关状态但不获取外力) | false | 否 |
maxMouseOutForce | number | 鼠标交互时能提供的最大力限制 | null | 否 |
maxMoveV | number | 最大移动速度 | null | 否 |
beforeDrawGlobule | (globule: GlobuleC) => void | 每一帧绘制该球体之前执行的钩子函数 | null | 否 |
afterDrawGlobule | (globule: GlobuleC) => void | 每一帧绘制该球体之后执行的钩子函数 | null | 否 |
afterCalculateNextFrameGlobule | (nextFrameGlobule: GlobuleC) => void | 每一帧绘制球体后,计算并修改为下一帧状态后执行的钩子函数 | null | 否 |
SphereCollisionOptions
属性 | 数据类型 | 说明 | ||
---|---|---|---|---|
collisionRectX | number | 球体发生碰撞的矩形区域的左上角x坐标(向右为正方向) | 0 | 否 |
collisionRectY | number | 球体发生碰撞的矩形区域的左上角y坐标(向下为正方向) | 0 | 否 |
collisionRectWidth | number | 球体发生碰撞的矩形区域的宽度 | canvas.width | 否 |
collisionRectHeight | number | 球体发生碰撞的矩形区域的高度 | canvas.height | 否 |
monitorMousePos | boolean | 是否监听鼠标的位置 | false | 否 |
beforeDrawGlobules | (sphereCollision: SphereCollisionC) => void | 每一帧绘制所有球体之前执行的钩子函数 | null | 否 |
afterDrawGlobules | (sphereCollision: SphereCollisionC) => void | 每一帧绘制所有球体之后执行的钩子函数 | null | 否 |
onMouseDownCanvas(v1.1.0新增) | (event: MouseEvent, sphereCollision: SphereCollisionC) => void | 鼠标按下时执行的钩子函数 | null | 否 |
onMouseMoveCanvas(v1.1.0新增) | (event: MouseEvent, sphereCollision: SphereCollisionC) => void | 鼠标移动时执行的钩子函数 | null | 否 |
onMouseUpCanvas(v1.1.0新增) | (event: MouseEvent, sphereCollision: SphereCollisionC) => void | 鼠标松开时执行的钩子函数 | null | 否 |
onMouseLeaveCanvas(v1.1.0新增) | (event: MouseEvent, sphereCollision: SphereCollisionC) => void | 鼠标离开时执行的钩子函数 | null | 否 |
MousePos
属性 | 数据类型 | 说明 |
---|---|---|
mouseX | number | null | 鼠标在Canvas中的x坐标(向右为正方向) |
mouseY | number | null | 鼠标在Canvas中的y坐标(向下为正方向) |
Direction
属性 | 数据类型 | 说明 |
---|---|---|
Direction | “bottom” | “top” | “left” | “right” | 方向 |
GlobuleC
属性 | 数据类型 | 说明 |
---|---|---|
id | any | 任意值,可存放数据 |
ctx | CanvasRenderingContext2D | Context对象 |
canvas | HTMLCanvasElement | Canvas对象 |
requiredMouseInteraction | boolean | 是否需要鼠标交互 |
mouseInteractionBehavior(v1.1.0新增) | “over” | “drag” | 鼠标交互行为。“over”,鼠标穿过;“drag”,鼠标拖拽 |
maxMouseOutForce | number | null | 鼠标交互时能提供的最大力限制 |
initX | number | 初始x坐标(向右为正方向) |
initY | number | 初始y坐标(向下为正方向) |
x | number | x坐标(向右为正方向) |
y | number | y坐标(向下为正方向) |
vx | number | 在水平方向的速度(向右为正方向) |
vy | number | 在垂直方向的速度(向下为正方向) |
radius | number | 半径 |
color | string | 颜色 |
isPureColor(v1.1.3新增) | boolean | 是否为纯色 |
alpha | number | 透明度 |
alphaChangeV | number | 透明度改变的速度(正数增加,负数减小) |
bgImg | string | 背景图片 |
collisionLossV | number | 碰撞时的速度损失 |
moveLossV | number | 移动时的速度损失 |
gDirection | “toInit” | “toBottom” | “toTop” | “toLeft” | “toRight” | 引力方向。“toInit”,指向球体的初始位置;“toBottom”,指向正下方;“toTop”,指向正上方;“toLeft”,指向正左方;“toRight”,指向正右方(后四个为v1.1.0新增) |
gCoefficient | number | 引力系数 |
fixedPos | boolean | 是否固定位置 |
receiveOutForce | boolean | 是否接受外力 |
receiveWallForce | boolean | 是否接受墙的力(与墙体发生碰撞) |
resistanceWallDirection(v1.1.3新增) | Direction[] | 有阻力的墙的方向 |
onlyCheckCollision | boolean | 当不接受外力时,是否检测碰撞(检测碰撞相关状态但不获取外力) |
mousePos | MousePos | 鼠标相对于canvas的位置坐标 |
maxMoveV | number | null | 最大移动速度 |
controlledByMouse(v1.1.0新增) | boolean | 当前是否受鼠标控制(被鼠标拖拽) |
inCollisionGlobule | boolean | 是否与其他球体发生碰撞的状态 |
inCollisionGlobuleList | GlobuleC[] | 与其他球体碰撞的其他球体实例列表 |
inCollisionWall | boolean | 是否与墙体发生碰撞的状态 |
beforeDrawGlobule | (globule: GlobuleC) => void | null | 每一帧绘制该球体之前执行的钩子函数 |
afterDrawGlobule | (globule: GlobuleC) => void | null | 每一帧绘制该球体之后执行的钩子函数 |
afterCalculateNextFrameGlobule | (nextFrameGlobule: GlobuleC) => void | null | 每一帧绘制球体后,计算并修改为下一帧状态后执行的钩子函数 |
方法 | ||
addOutForce | (outForceVX: number, outForceVY: number, isCollision?:boolean = false) => void | 添加外力。用于动态增加或减小球体的速度 |
五、特别说明
- 球体的fixedPos属性为true时, 获取不了外力,所以球体不会移动,但还是会使其他球体受到外力,进行反弹。
- 球体的receiveOutForce属性为false时,获取不了鼠标穿过和其他球体碰撞产生的外力,即使另一个球体的receiveOutForce属性为true。
- 球体的receiveWallForce属性为false时,获取不了来自墙体的外力,所以不会与墙体发生碰撞。
- 球体的beforeDrawGlobule和afterDrawGlobule两个钩子函数,主要作用是在绘制球体之前和之后分别去绘制其他元素,而afterCalculateNextFrameGlobule钩子函数是用于做一些其他的逻辑判断,因为只有这个函数里拿到的球体实例是带有是否发生碰撞等相关信息的
- 如果实例化SphereCollision对象时传入了beforeDrawGlobules钩子函数,并且需要在每一帧绘制前要清除整个画布,则需要使用者自己清除,这是考虑到有些不需要清除的场景。
- 如果要获取鼠标相关的信息或者想要实现鼠标交互,实例化SphereCollision对象时就必须在第四个参数options中传入monitorMousePos为true。
- 如果需要的话,可以在任何时候动态地修改球体实例的所有属性值,以满足自己的自定义需求。
六、关键版本更新日志
v1.1.3
- 新增支持纯色球体
- 新增支持四面墙中只有部分墙面有阻力,与球体发生碰撞
- 解决一些已知bug
v1.1.0
- 考虑后续的功能扩展,修改了SphereCollision类的参数,将之前的第四个及之后的参数都统一放到options对象中,并作为第四个参数传入。
- 新增支持上下左右四个引力方向
- 新增支持球体进行鼠标拖拽交互
- 新增的相关属性及方法可自行查阅API文档
更多个人文章
- 两个跨域页面进行跳转传参的终极方案
- 彻底搞懂盒子模型
- hashHistory和browserHistory的区别
- 十分钟带你入门Chrome插件开发
- 面试秘籍之排序算法
实现球体碰撞,使用这个库就够了相关推荐
- Canvas实现球体碰撞交互效果(一)
一.Canvas简介 提到Canvas相信做前端开发的同学都不陌生,它是一个用于绘制图形的容器,我们会在一些特殊场景时需要用到Canvas,比如我们要在页面上显示一个流程图,这个流程图需要根据后端返回 ...
- MD5碰撞与撞库和题
MD5 相同的情况叫做"碰撞",现在网络中已经出现了两个相同的 MD5 可执行文件,所以MD5现在已经被弃用了,发生碰撞的概率是1/(2^128). SHA-1 也会发生碰撞,但是 ...
- python 统计组合用什么库_Python数据科学,用这些库就够了
为了方便学习,本文列出的20个Python库将按领域进行分类,有些你可能并不熟悉,但是真的能提高你的模型算法实现效率,多一点尝试,多一些努力! ▌核心库和统计数据 1. NumPy (Commits: ...
- unity 画球面_unity3d第一个例子--制作一个简单的球体碰撞墙面
思路 当然首先应该先新建立一个地面,有地面才有一切(floor) 再建立一面墙WaLl,一面墙也就是用100个预制的正方体组成 我们不可能让发射的子弹bullet,朝着一个方向射击shoot 所以需要 ...
- uni-app框架看这五款组件库就够了
uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS.Android.Web(响应式).以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉 ...
- 设计必备丨ICON素材哪里找 这五个素材库就够了
页面设计和特效制作中我们会用到一些ICON图标和插画,但有些ICON不足够精美,今天就来给大家推荐5个ICON素材网站,供大家日常的设计及使用. 1.Iconfont(日常使用必备) Iconfont ...
- 视频剪辑有这6个高清视频素材库就够了
视频剪辑必备的6个网站,免费.可商用,建议收藏! 1.菜鸟图库 https://www.sucai999.com/video.html?v=NTYxMjky 菜鸟图库网素材类型非常多,平面设计.UI设 ...
- 胶囊体 ,正方体,球体碰撞器差别,碰撞体以脚为基准与以腰为基准
- 企业云盘够快云库的「战斗与前行」
由36氪举办的2016 wise独角兽大会将于12月6日召开.作为国内首家挂牌的企业云盘--够快云库也应邀参加了此次wise独角兽大会,并独家支持现场资料下载.现场将会有50位独角兽公司CEO.200 ...
最新文章
- 建模案例:最优截断切割问题
- Java 文件 IO 操作
- EL与JSTL注意事项汇总
- percona-toolkit(pt工具)使用总结
- Java基础视频笔记(四):泛型
- Your account has been locked out. Please contact the system administrator for further assistance.
- 开源中国翻译频道链接收藏
- 克劳斯比的零缺陷——《可以量化的管理学》
- java时间格式转换
- Python 用异常处理改写猜数游戏程序
- 在国产系统(Linux)上,安装运行Steam游戏详解
- SpringBoot图片上传报错:The field headImg exceeds its maximum permitted size of 1048576 bytes.
- thrift开源项目研究
- Protected multilib versions XXX
- 2017双11核心技术揭秘—双十一海量数据下EagleEye的使命和挑战
- 360断网急救箱 dns服务器未响应,发现DNS服务异常,用360断网急救箱修复后过一段时间又复发。怎么办?...
- 计算机毕业设计Java物流信息管理系统录像演示(源码+系统+mysql数据库+Lw文档)
- 重温马云英文演讲:最伟大的成功
- 商业智慧——三国职场人
- 高薪诚聘中高级软件工程师