{"id":16579533,"url":"https://github.com/hepengwei/sphere-collision","last_synced_at":"2025-10-29T05:31:18.002Z","repository":{"id":61794350,"uuid":"554276955","full_name":"hepengwei/sphere-collision","owner":"hepengwei","description":"🌈 一个用于在Canvas上实现球体碰撞和球体交互场景，高可用、高扩展的库。","archived":false,"fork":false,"pushed_at":"2023-09-07T12:15:35.000Z","size":18262,"stargazers_count":7,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-09-07T13:32:24.077Z","etag":null,"topics":["canvas","canvas-game","canvas2d","collision","javascript","sphere","spherecollision","typescript"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hepengwei.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-10-19T14:41:52.000Z","updated_at":"2023-09-02T06:49:08.000Z","dependencies_parsed_at":"2023-01-30T06:01:10.259Z","dependency_job_id":null,"html_url":"https://github.com/hepengwei/sphere-collision","commit_stats":null,"previous_names":[],"tags_count":0,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hepengwei%2Fsphere-collision","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hepengwei%2Fsphere-collision/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hepengwei%2Fsphere-collision/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hepengwei%2Fsphere-collision/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hepengwei","download_url":"https://codeload.github.com/hepengwei/sphere-collision/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219858328,"owners_count":16556046,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["canvas","canvas-game","canvas2d","collision","javascript","sphere","spherecollision","typescript"],"created_at":"2024-10-11T22:18:18.949Z","updated_at":"2025-10-29T05:31:16.777Z","avatar_url":"https://github.com/hepengwei.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003esphere-collision\u003c/h1\u003e\n\u003cdiv align=\"center\"\u003e\n一个用于在Canvas上实现球体碰撞和球体交互场景，高可用、高扩展的库。\n\u003c/div\u003e\n\n## 使用说明\n\n安装\n\n```\nnpm i sphere-collision\n```\n\n使用示例\n\n```\nimport SphereCollision from \"sphere-collision\";\n\nconst canvasWidth = 600; // 画布宽度\nconst canvasHeight = 600; // 画布高度\nconst globuleRadius = 60; // 球半径\n\nconst beforeDrawGlobules = (sphereCollision) =\u003e {\n    const { ctx } = sphereCollision;\n    // 绘制整个画布的背景色\n    ctx.clearRect(0, 0, canvasWidth, canvasHeight);\n    ctx.beginPath();\n    ctx.fillStyle = \"#000000\";\n    ctx.fillRect(0, 0, canvasWidth, canvasHeight);\n};\n\nconst canvas = document.getElementById(\"myCanvas\");\nif (canvas) {\n    canvas.width = canvasWidth;\n    canvas.height = canvasHeight;\n    const ctx = canvas.getContext(\"2d\");\n\n    // 实例化SphereCollision对象\n    const sphereCollision = new SphereCollision(\n        ctx,\n        canvas,\n        [\n            {\n                initX: 400,\n                initY: 400,\n                vx: 6,\n                vy: 3,\n                radius: globuleRadius,\n            },\n        ],\n        { beforeDrawGlobules }\n    );\n\n    // 开使执行动画\n    sphereCollision.start();\n}\n```\n\n## 案例展示\n\n### 1. 探照灯效果\n\n\u003cimg src=\"./images/searchlight.gif\" alt=\"\" width={1200}/\u003e\n\n### 2. 球体碰撞交互效果\n\n\u003cimg src=\"./images/globuleInteraction.gif\" alt=\"\" width={1000}/\u003e\n\n### 3. 消灭行星小游戏\n\n\u003cimg src=\"./images/killPlanet.gif\" alt=\"\" width={1000}/\u003e\n\n### 4.各类球体自由落体交互效果\n\n\u003cimg src=\"./images/freeFallingBody.gif\" alt=\"\" width={1000}/\u003e\n\n### 5. 炫酷倒计时动画\n\n\u003cimg src=\"./images/countDown.gif\" alt=\"\" width={1000}/\u003e\n\u003cbr/\u003e\n\n#### 在线体验(PC 端)：[https://hepengwei.github.io/visualization-collection/#/canvas/searchlight](https://hepengwei.github.io/visualization-collection/#/canvas/searchlight)\n\n#### 以上案例源码均在 visualization-collection 开源项目中，github 地址：[https://github.com/hepengwei/visualization-collection](https://github.com/hepengwei/visualization-collection)\n\n## API 文档\n\n**SphereCollisionC**\n| 参数（顺序从上往下依次传入） | 数据类型 | 说明 | 默认值 | 是否必需 |\n|:------------------------------|:-------------------------------------------------------|:------------------------------|:------------------------|:------|\n| ctx | CanvasRenderingContext2D | Context 对象 | null | 是 |\n| canvas | HTMLCanvasElement | Canvas 对象 | null | 是 |\n| globuleOptionsList | GlobuleOptions[] | 初始化球体的配置列表 | [] | 否 |\n| options | SphereCollisionOptions | 配置参数 | SphereCollisionOptions | 否 |\n| **属性** | | | | |\n| ctx | CanvasRenderingContext2D | Context 对象 | | |\n| canvas | HTMLCanvasElement | Canvas 对象 | | |\n| frameId | number | requestAnimationFrame 方法返回的 ID | | |\n| globuleList | GlobuleC[] | 保存所有球体实例的列表 | | |\n| animationState | enum AnimationState{\"waitStart\",\"inAnimation\",\"stop\"} | 当前动画状态 | | |\n| mousePos | MousePos | 当前鼠标在 Canvas 中的位置坐标 | | |\n| prevMousePos(v1.1.0 新增) | MousePos | 前一次鼠标在 Canvas 中的位置坐标 | | |\n| isMouseDown(v1.1.0 新增) | boolean | 当前鼠标在 Canvas 中是否按下 | | |\n| mouseDownPos(v1.1.0 新增) | MousePos | 鼠标在 Canvas 中按下时的位置坐标 | | |\n| mouseInGlobuleList(v1.1.0 新增) | GlobuleC[] | 当前鼠标所在球体中的球体实例列表 | | |\n| **方法** | | | | |\n| start | () =\u003e void | 必须调用该方法，Canvas 才渲染，开始执行相关动画 | | |\n| createGlobule | (globuleOptions: GlobuleOptions) =\u003e Globule | 创建球体实例的方法 | | |\n| updateGlobuleList | (newGlobuleList: GlobuleC[]) =\u003e void | 更新球体实例列表，用于动态增加或减少球体实例 | | |\n| stop | () =\u003e void | 停止整个 frame 动画 |\n\u003cbr/\u003e\n\n**GlobuleOptions**\n\n| 属性                                    | 数据类型                                                   | 说明                                                                                                                                                   | 默认值                                                                              | 是否必需 |\n| :-------------------------------------- | :--------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------- | :------- |\n| id                                      | any                                                        | 任意值，可存放数据                                                                                                                                     |                                                                                     | 否       |\n| initX                                   | number                                                     | 初始 x 坐标（向右为正方向）                                                                                                                            | 0                                                                                   | 否       |\n| initY                                   | number                                                     | 初始 y 坐标（向下为正方向）                                                                                                                            | 0                                                                                   | 否       |\n| vx                                      | number                                                     | 在水平方向的速度（向右为正方向）                                                                                                                       | 0                                                                                   | 否       |\n| vy                                      | number                                                     | 在垂直方向的速度（向下为正方向）                                                                                                                       | 0                                                                                   | 否       |\n| radius                                  | number                                                     | 半径                                                                                                                                                   | 10                                                                                  | 否       |\n| color                                   | string                                                     | 颜色                                                                                                                                                   | \"#666666\"                                                                           | 否       |\n| isPureColor(v1.1.3 新增)                | boolean                                                    | 是否为纯色                                                                                                                                             | false                                                                               | 否       |\n| alpha                                   | number                                                     | 透明度                                                                                                                                                 | 1                                                                                   | 否       |\n| alphaChangeV                            | number                                                     | 透明度改变的速度（正数增加，负数减小）                                                                                                                 | 0                                                                                   | 否       |\n| bgImg                                   | string                                                     | 背景图片                                                                                                                                               | \"\"                                                                                  | 否       |\n| collisionLossV                          | number                                                     | 碰撞时的速度损失                                                                                                                                       | 0                                                                                   | 否       |\n| moveLossV                               | number                                                     | 移动时的速度损失                                                                                                                                       | 0                                                                                   | 否       |\n| gDirection                              | \"toInit\" \\| \"toBottom\" \\| \"toTop\" \\| \"toLeft\" \\| \"toRight\" | 引力方向。\"toInit\"，指向球体的初始位置；\"toBottom\"，指向正下方；\"toTop\"，指向正上方；\"toLeft\"，指向正左方；\"toRight\"，指向正右方(后四个为 v1.1.0 新增) |                                                                                     | 否       |\n| gCoefficient                            | number                                                     | 引力系数                                                                                                                                               | 0                                                                                   | 否       |\n| requiredMouseInteraction                | boolean                                                    | 是否需要鼠标交互                                                                                                                                       | false                                                                               | 否       |\n| mouseInteractionBehavior(v1.1.0 新增)   | \"over\" \\| \"drag\"                                           | 鼠标交互行为。\"over\"，鼠标穿过；\"drag\"，鼠标拖拽                                                                                                       | 当 requiredMouseInteraction 为 true 时，默认值为\"over\"，当为 false 时，则没有默认值 | 否       |\n| fixedPos                                | boolean                                                    | 是否固定位置                                                                                                                                           | false                                                                               | 否       |\n| receiveOutForce                         | boolean                                                    | 是否接受外力                                                                                                                                           | true                                                                                | 否       |\n| receiveWallForce                        | boolean                                                    | 是否接受墙的力（与墙体发生碰撞）                                                                                                                       | true                                                                                | 否       |\n| resistanceWallDirection(v1.1.3 新增)    | Direction[]                                                | 有阻力的墙的方向                                                                                                                                       | [\"bottom\", \"top\", \"left\", \"right\"]                                                  | 否       |\n| onlyCheckCollision                      | boolean                                                    | 当不接受外力时，是否检测碰撞（检测碰撞相关状态但不获取外力）                                                                                           | false                                                                               | 否       |\n| perfectlyElasticCollision(v1.1.10 新增) | boolean                                                    | 是否完全弹性碰撞                                                                                                                                       | false                                                                               | 否       |\n| maxMouseOutForce                        | number                                                     | 鼠标交互时能提供的最大力限制                                                                                                                           | null                                                                                | 否       |\n| maxMoveV                                | number                                                     | 最大移动速度                                                                                                                                           | null                                                                                | 否       |\n| beforeDrawGlobule                       | (globule: GlobuleC) =\u003e void                                | 每一帧绘制该球体之前执行的钩子函数                                                                                                                     | null                                                                                | 否       |\n| afterDrawGlobule                        | (globule: GlobuleC) =\u003e void                                | 每一帧绘制该球体之后执行的钩子函数                                                                                                                     | null                                                                                | 否       |\n| afterCalculateNextFrameGlobule          | (nextFrameGlobule: GlobuleC) =\u003e void                       | 每一帧绘制球体后,计算并修改为下一帧状态后执行的钩子函数                                                                                                | null                                                                                | 否       |\n\n\u003cbr/\u003e\n\n**SphereCollisionOptions**\n\n| 属性                            | 数据类型                                                       | 说明                                                  |               |     |\n| :------------------------------ | :------------------------------------------------------------- | :---------------------------------------------------- | :------------ | :-- |\n| collisionRectX                  | number                                                         | 球体发生碰撞的矩形区域的左上角 x 坐标（向右为正方向） | 0             | 否  |\n| collisionRectY                  | number                                                         | 球体发生碰撞的矩形区域的左上角 y 坐标（向下为正方向） | 0             | 否  |\n| collisionRectWidth              | number                                                         | 球体发生碰撞的矩形区域的宽度                          | canvas.width  | 否  |\n| collisionRectHeight             | number                                                         | 球体发生碰撞的矩形区域的高度                          | canvas.height | 否  |\n| monitorMousePos                 | boolean                                                        | 是否监听鼠标的位置                                    | false         | 否  |\n| beforeDrawGlobules              | (sphereCollision: SphereCollisionC) =\u003e void                    | 每一帧绘制所有球体之前执行的钩子函数                  | null          | 否  |\n| afterDrawGlobules               | (sphereCollision: SphereCollisionC) =\u003e void                    | 每一帧绘制所有球体之后执行的钩子函数                  | null          | 否  |\n| onMouseDownCanvas(v1.1.0 新增)  | (event: MouseEvent, sphereCollision: SphereCollisionC) =\u003e void | 鼠标按下时执行的钩子函数                              | null          | 否  |\n| onMouseMoveCanvas(v1.1.0 新增)  | (event: MouseEvent, sphereCollision: SphereCollisionC) =\u003e void | 鼠标移动时执行的钩子函数                              | null          | 否  |\n| onMouseUpCanvas(v1.1.0 新增)    | (event: MouseEvent, sphereCollision: SphereCollisionC) =\u003e void | 鼠标松开时执行的钩子函数                              | null          | 否  |\n| onMouseLeaveCanvas(v1.1.0 新增) | (event: MouseEvent, sphereCollision: SphereCollisionC) =\u003e void | 鼠标离开时执行的钩子函数                              | null          | 否  |\n\n\u003cbr/\u003e\n\n**MousePos**\n\n| 属性   | 数据类型       | 说明                                      |\n| :----- | :------------- | :---------------------------------------- |\n| mouseX | number \\| null | 鼠标在 Canvas 中的 x 坐标（向右为正方向） |\n| mouseY | number \\| null | 鼠标在 Canvas 中的 y 坐标（向下为正方向） |\n\n\u003cbr/\u003e\n\n**Direction**\n\n| 属性      | 数据类型                               | 说明 |\n| :-------- | :------------------------------------- | :--- |\n| Direction | \"bottom\" \\| \"top\" \\| \"left\" \\| \"right\" | 方向 |\n\n\u003cbr/\u003e\n\n**GlobuleC**\n\n| 属性                                    | 数据类型                                                                       | 说明                                                                                                                                                   |\n| :-------------------------------------- | :----------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| id                                      | any                                                                            | 任意值,可存放数据                                                                                                                                      |\n| ctx                                     | CanvasRenderingContext2D                                                       | Context 对象                                                                                                                                           |\n| canvas                                  | HTMLCanvasElement                                                              | Canvas 对象                                                                                                                                            |\n| requiredMouseInteraction                | boolean                                                                        | 是否需要鼠标交互                                                                                                                                       |\n| mouseInteractionBehavior(v1.1.0 新增)   | \"over\" \\| \"drag\"                                                               | 鼠标交互行为。\"over\"，鼠标穿过；\"drag\"，鼠标拖拽                                                                                                       |\n| maxMouseOutForce                        | number \\| null                                                                 | 鼠标交互时能提供的最大力限制                                                                                                                           |\n| initX                                   | number                                                                         | 初始 x 坐标（向右为正方向）                                                                                                                            |\n| initY                                   | number                                                                         | 初始 y 坐标（向下为正方向）                                                                                                                            |\n| x                                       | number                                                                         | x 坐标（向右为正方向）                                                                                                                                 |\n| y                                       | number                                                                         | y 坐标（向下为正方向）                                                                                                                                 |\n| previousX(v1.1.8 新增)                  | number \\| null                                                                 | 前一帧 x 坐标（向右为正方向）                                                                                                                          |\n| previousY(v1.1.8 新增)                  | number \\| null                                                                 | 前一帧 y 坐标（向右为正方向）                                                                                                                          |\n| vx                                      | number                                                                         | 在水平方向的速度（向右为正方向）                                                                                                                       |\n| vy                                      | number                                                                         | 在垂直方向的速度（向下为正方向）                                                                                                                       |\n| radius                                  | number                                                                         | 半径                                                                                                                                                   |\n| color                                   | string                                                                         | 颜色                                                                                                                                                   |\n| isPureColor(v1.1.3 新增)                | boolean                                                                        | 是否为纯色                                                                                                                                             |\n| alpha                                   | number                                                                         | 透明度                                                                                                                                                 |\n| alphaChangeV                            | number                                                                         | 透明度改变的速度（正数增加，负数减小）                                                                                                                 |\n| bgImg                                   | string                                                                         | 背景图片                                                                                                                                               |\n| collisionLossV                          | number                                                                         | 碰撞时的速度损失                                                                                                                                       |\n| moveLossV                               | number                                                                         | 移动时的速度损失                                                                                                                                       |\n| gDirection                              | \"toInit\" \\| \"toBottom\" \\| \"toTop\" \\| \"toLeft\" \\| \"toRight\"                     | 引力方向。\"toInit\"，指向球体的初始位置；\"toBottom\"，指向正下方；\"toTop\"，指向正上方；\"toLeft\"，指向正左方；\"toRight\"，指向正右方(后四个为 v1.1.0 新增) |\n| gCoefficient                            | number                                                                         | 引力系数                                                                                                                                               |\n| fixedPos                                | boolean                                                                        | 是否固定位置                                                                                                                                           |\n| receiveOutForce                         | boolean                                                                        | 是否接受外力                                                                                                                                           |\n| receiveWallForce                        | boolean                                                                        | 是否接受墙的力（与墙体发生碰撞）                                                                                                                       |\n| resistanceWallDirection(v1.1.3 新增)    | Direction[]                                                                    | 有阻力的墙的方向                                                                                                                                       |\n| onlyCheckCollision                      | boolean                                                                        | 当不接受外力时，是否检测碰撞（检测碰撞相关状态但不获取外力）                                                                                           |\n| perfectlyElasticCollision(v1.1.10 新增) | boolean                                                                        | 是否完全弹性碰撞                                                                                                                                       |\n| mousePos                                | MousePos                                                                       | 鼠标相对于 canvas 的位置坐标                                                                                                                           |\n| maxMoveV                                | number \\| null                                                                 | 最大移动速度                                                                                                                                           |\n| controlledByMouse(v1.1.0 新增)          | boolean                                                                        | 当前是否受鼠标控制(被鼠标拖拽)                                                                                                                         |\n| inCollisionGlobule                      | boolean                                                                        | 是否与其他球体发生碰撞的状态                                                                                                                           |\n| inCollisionGlobuleList                  | GlobuleC[]                                                                     | 与其他球体碰撞的其他球体实例列表                                                                                                                       |\n| inCollisionWall                         | boolean                                                                        | 是否与墙体发生碰撞的状态                                                                                                                               |\n| beforeDrawGlobule                       | (globule: GlobuleC) =\u003e void \\| null                                            | 每一帧绘制该球体之前执行的钩子函数                                                                                                                     |\n| afterDrawGlobule                        | (globule: GlobuleC) =\u003e void \\| null                                            | 每一帧绘制该球体之后执行的钩子函数                                                                                                                     |\n| afterCalculateNextFrameGlobule          | (nextFrameGlobule: GlobuleC) =\u003e void \\| null                                   | 每一帧绘制球体后,计算并修改为下一帧状态后执行的钩子函数                                                                                                |\n| **方法**                                |                                                                                |                                                                                                                                                        |\n| addOutForce                             | (outForceVX: number, outForceVY: number, isCollision?:boolean = false) =\u003e void | 添加外力。用于动态增加或减小球体的速度                                                                                                                 |\n\n## 特别说明\n\n- 球体的 fixedPos 属性为 true 时， 获取不了外力，所以球体不会移动，但还是会使其他球体受到外力，进行反弹。\n- 球体的 receiveOutForce 属性为 false 时，获取不了鼠标穿过和其他球体碰撞产生的外力，即使另一个球体的 receiveOutForce 属性为 true。\n- 球体的 receiveWallForce 属性为 false 时，获取不了来自墙体的外力，所以不会与墙体发生碰撞。\n- 球体的 beforeDrawGlobule 和 afterDrawGlobule 两个钩子函数，主要作用是在绘制球体之前和之后分别去绘制其他元素，而 afterCalculateNextFrameGlobule 钩子函数是用于做一些其他的逻辑判断，因为只有这个函数里拿到的球体实例是带有是否发生碰撞等相关信息的\n- 如果实例化 SphereCollision 对象时传入了 beforeDrawGlobules 钩子函数，并且需要在每一帧绘制前要清除整个画布，则需要使用者自己清除，这是考虑到有些不需要清除的场景。\n- 如果要获取鼠标相关的信息或者想要实现鼠标交互，实例化 SphereCollision 对象时就必须在第四个参数 options 中传入 monitorMousePos 为 true。\n- 如果给球体配置了 gDirection 和 gCoefficient 属性，建议就不要配置 collisionLossV 了。\n- 非完全弹性碰撞会有速度的抵消，可能碰撞后的 x 轴或 y 轴方向上的速度相互抵消为 0，球体可能会停下来；完全弹性碰撞则不会有速度的抵消，速度大小不会改变(速度为 0 除外，速度为 0 的，碰撞后会和撞它的另一球的速度大小一致)，碰撞后仅改变方向; 在碰撞时如果其中有一个球体的 perfectlyElasticCollision 为 true，则两球均使用完全弹性碰撞算法进行计算。\n- 如果需要的话，可以在任何时候动态地修改球体实例的所有属性值，以满足自己的自定义需求。\n\n## 关键版本更新日志\n\n- v1.1.10\n\n1. 新增支持球体完全弹性碰撞\n2. 优化代码\n\n- v1.1.8\n\n1. 优化碰撞算法\n2. 解决一些已知 bug\n\n- v1.1.3\n\n1. 新增支持纯色球体\n2. 新增支持四面墙中只有部分墙面有阻力，与球体发生碰撞\n3. 解决一些已知 bug\n\n- v1.1.0\n\n1. 考虑后续的功能扩展，修改了 SphereCollision 类的参数，将之前的第四个及之后的参数都统一放到 options 对象中，并作为第四个参数传入。\n2. 新增支持上下左右四个引力方向\n3. 新增支持球体进行鼠标拖拽交互\n4. 新增的相关属性及方法可自行查阅 API 文档\n   \u003cbr/\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhepengwei%2Fsphere-collision","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhepengwei%2Fsphere-collision","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhepengwei%2Fsphere-collision/lists"}