mskalign-canvas
Version:
一个用于图片标注的javascript库,基于canvas,简单轻量,支持矩形、多边形、点、折线、圆形。
349 lines (251 loc) • 7.32 kB
Markdown
# 面向对象脊椎曲线系统库
基于 NURBS 曲线的脊椎模拟系统,采用面向对象设计,便于在其他项目中集成和使用。
## 特性
- 🎯 **面向对象设计**:清晰的类结构,易于扩展和维护
- 🔧 **灵活配置**:支持多种参数配置,适应不同需求
- 🖱️ **交互式操作**:支持鼠标拖拽、悬停等交互
- 📊 **状态管理**:支持导出/导入状态,便于数据持久化
- 🎨 **可视化效果**:支持网格、连接线、发光效果等视觉元素
- 🔄 **实时物理约束**:模拟真实脊椎的物理特性
## 快速开始
### 1. 引入依赖
```html
<!-- 引入 verb-nurbs 库 -->
<script src="https://unpkg.com/verb-nurbs"></script>
<!-- 引入脊椎系统库 -->
<script src="spine-system.js"></script>
```
### 2. 创建 HTML 结构
```html
<canvas id="spineCanvas" width="400" height="600"></canvas>
```
### 3. 初始化脊椎系统
```javascript
// 脊椎点数据:[x, y] 坐标数组
const spineData = [
[200, 50],
[201, 70],
[202, 90],
[203, 110],
[204, 130],
[205, 150],
[206, 170],
[207, 190],
[208, 210],
[209, 230],
];
// 获取canvas元素
const canvas = document.getElementById("spineCanvas");
// 创建脊椎系统实例
const spineSystem = new SpineSystem(canvas, spineData, {
influence: 1.5, // 影响强度
curveDegree: 2, // 曲线次数
smoothness: 0.3, // 平滑度
influenceRange: 4, // 影响范围
showGrid: true, // 显示网格
});
// 渲染系统
spineSystem.render();
```
## 核心类介绍
### SpineSystem - 主系统类
主要的脊椎系统类,协调所有组件的工作。
#### 构造函数
```javascript
new SpineSystem(canvas, initialData, options);
```
- `canvas`: HTML Canvas 元素
- `initialData`: 初始脊椎点数据,格式为 `[[x1, y1], [x2, y2], ...]`
- `options`: 配置选项对象
#### 配置选项
```javascript
const options = {
influence: 1.5, // 影响强度 (0.1 - 2.5)
curveDegree: 2, // 曲线次数 (2 - 5)
smoothness: 0.3, // 平滑度 (0.1 - 2.0)
influenceRange: 4, // 影响范围 (3 - 12)
showGrid: true, // 显示网格
};
```
#### 主要方法
```javascript
// 更新配置
spineSystem.updateConfig(newConfig);
// 重置到初始状态
spineSystem.reset();
// 获取当前点位置
const points = spineSystem.getPoints();
// 获取原始点位置
const originalPoints = spineSystem.getOriginalPoints();
// 导出当前状态
const state = spineSystem.exportState();
// 导入状态
spineSystem.importState(state);
// 手动渲染
spineSystem.render();
// 销毁实例
spineSystem.destroy();
```
### SpinePoint - 脊椎点类
表示脊椎上的一个点。
#### 属性
```javascript
point.x, point.y; // 当前坐标
point.originalX, point.originalY; // 原始坐标
point.index; // 点的索引
point.isEndPoint; // 是否为端点
point.isHovered; // 是否被悬停
point.isDragged; // 是否被拖拽
point.influenceState; // 影响状态:'normal' | 'influenced' | 'lightlyFollowing'
```
#### 方法
```javascript
// 重置到原始位置
point.reset();
// 计算到指定坐标的距离
const distance = point.distanceTo(x, y);
// 获取点的颜色
const color = point.getColor();
// 获取点的半径
const radius = point.getRadius();
```
### SpinePhysics - 物理系统类
处理脊椎的物理约束和影响计算。
#### 方法
```javascript
// 应用物理约束
physics.applyConstraints(points, smoothness);
// 应用影响效果
physics.applyInfluence(points, dragIndex, dragOffset, config);
// 计算三点间的角度
const angle = physics.calculateAngle(p1, p2, p3);
```
### SpineRenderer - 渲染器类
负责所有的绘制工作。
#### 方法
```javascript
// 清空画布
renderer.clear();
// 绘制网格
renderer.drawGrid();
// 绘制NURBS曲线
renderer.drawNurbsCurve(curve, smoothness);
// 绘制连接线
renderer.drawConnectionLines(points);
// 绘制脊椎点
renderer.drawPoints(points);
// 绘制悬停信息
renderer.drawHoverInfo(point, mouseX, mouseY);
```
### SpineInteraction - 交互处理类
处理鼠标交互逻辑。
#### 方法
```javascript
// 获取鼠标位置
const pos = interaction.getMousePosition();
// 获取悬停的点
const hoveredPoint = interaction.getHoveredPoint();
```
## 使用示例
### 基本使用
```javascript
const spineSystem = new SpineSystem(canvas, spineData);
spineSystem.render();
```
### 动态更新配置
```javascript
// 监听滑块变化
document.getElementById("influenceSlider").addEventListener("input", (e) => {
spineSystem.updateConfig({ influence: parseFloat(e.target.value) });
});
```
### 状态管理
```javascript
// 保存状态
const currentState = spineSystem.exportState();
localStorage.setItem("spineState", JSON.stringify(currentState));
// 恢复状态
const savedState = JSON.parse(localStorage.getItem("spineState"));
spineSystem.importState(savedState);
```
### 多实例使用
```javascript
// 创建多个独立的脊椎系统
const spineSystem1 = new SpineSystem(canvas1, spineData1, config1);
const spineSystem2 = new SpineSystem(canvas2, spineData2, config2);
// 各自独立运行
spineSystem1.render();
spineSystem2.render();
```
## 高级用法
### 自定义物理约束
```javascript
// 继承并扩展物理系统
class CustomSpinePhysics extends SpinePhysics {
applyConstraints(points, smoothness) {
// 先应用基础约束
super.applyConstraints(points, smoothness);
// 添加自定义约束
this.applyCustomConstraints(points);
}
applyCustomConstraints(points) {
// 自定义约束逻辑
}
}
// 使用自定义物理系统
const customSpineSystem = new SpineSystem(canvas, spineData);
customSpineSystem.physics = new CustomSpinePhysics();
```
### 自定义渲染效果
```javascript
// 继承并扩展渲染器
class CustomSpineRenderer extends SpineRenderer {
drawPoints(points) {
// 先绘制基础点
super.drawPoints(points);
// 添加自定义效果
this.drawCustomEffects(points);
}
drawCustomEffects(points) {
// 自定义绘制逻辑
}
}
// 使用自定义渲染器
const customSpineSystem = new SpineSystem(canvas, spineData);
customSpineSystem.renderer = new CustomSpineRenderer(canvas);
```
## 事件监听
```javascript
// 可以通过覆盖交互处理方法来添加自定义事件
class CustomSpineInteraction extends SpineInteraction {
handleMouseDown(e) {
// 调用原始处理
super.handleMouseDown(e);
// 添加自定义逻辑
console.log("点击了脊椎点");
}
}
```
## 性能优化建议
1. **避免频繁重绘**:只在必要时调用 `render()` 方法
2. **合理设置参数**:过高的平滑度会影响性能
3. **控制点数量**:建议脊椎点数量在 10-20 个之间
4. **使用 requestAnimationFrame**:对于动画效果,使用 RAF 优化
5. **及时销毁**:页面卸载时调用 `destroy()` 方法
## 浏览器兼容性
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
## 依赖库
- [verb-nurbs](https://github.com/pboyer/verb): NURBS 曲线计算库
## 许可证
MIT License
## 贡献
欢迎提交 Issue 和 Pull Request 来改进这个库。
## 更新日志
### v1.0.0
- 初始版本发布
- 支持基本的脊椎曲线模拟
- 面向对象设计
- 完整的 API 文档