singularity-frame
v1.1.3
Published
A powerful and highly customizable whiteboard component library for Vue and Nuxt.
Downloads
39
Readme
sFrame
sFrame 是一个为 Vue 3 和 Nuxt 设计的,功能强大、高度可定制的白板组件库。它集成了基础绘图、数学几何、响应式渲染和协作功能接口,旨在提供极致的易用性和无与伦比的灵活性。
✨ 特性
- 小白友好: 一行代码即可拥有一个功能完整的白板。
- 高度可定制: 使用 Vue 插槽 (slots) 自由组合、替换或扩展任何 UI 部分。
- 功能丰富: 内置画笔、几何图形、选择、缩放、平移、撤销/重做等功能。
- 数据驱动: 通过
v-model绑定图形数据,轻松实现状态管理。 - 文件支持: 原生支持加载和保存为
.sframe(JSON) 文件格式。 - Nuxt 集成: 提供 Nuxt 模块,实现组件自动导入和无缝集成。
- 主题系统: 支持预设主题和通过 CSS 变量进行的深度自定义。
📦 安装
# 使用 yarn
yarn add singularity-frame
# 使用 npm
npm install singularity-frame
# 使用 pnpm
pnpm add singularity-frame🚀 快速开始
Vue 3 项目中使用
// main.ts
import { createApp } from 'vue'
import SFrame from 'singularity-frame'
import App from './App.vue'
const app = createApp(App)
app.use(SFrame)
app.mount('#app')<template>
<div style="height: 600px;">
<SFrame />
</div>
</template>Nuxt 3 项目中使用
在 nuxt.config.ts 中添加模块:
export default defineNuxtConfig({
modules: [
'singularity-frame/nuxt'
]
})然后在页面中直接使用:
<template>
<div style="height: 100vh;">
<SFrame />
</div>
</template>2. 加载 .sframe 文件
将你的 .sframe 文件放入 public 目录,然后使用 src prop 指定路径。
<template>
<div style="height: 100vh;">
<SFrame src="/my-awesome-drawing.sframe" />
</div>
</template>📖 详细使用指南
基础配置选项
<template>
<SFrame
:theme="'dark'"
:show-grid="true"
:readonly="false"
:icons="customIcons"
src="/path/to/file.sframe"
/>
</template>
<script setup>
const customIcons = {
pen: '<svg>...</svg>',
select: '<svg>...</svg>'
// 其他自定义图标
}
</script>高级自定义用法
sFrame 的核心是 <SFrameBoard> 组件,它提供了所有功能逻辑和插槽。你可以完全控制布局和组件。
<template>
<div style="height: 100vh; display: flex; flex-direction: column;">
<!-- 1. 提供上下文和 props -->
<SFrameBoard :theme="'dark'" :show-grid="false" readonly>
<!-- 2. 使用 v-slot 获取上下文并构建你的 UI -->
<template #toolbar="{ tools, activeTool, setActiveTool, utilityIcons, undo, redo }">
<div class="my-custom-toolbar">
<button
v-for="tool in tools"
:key="tool.name"
:class="{ active: activeTool === tool.name }"
@click="setActiveTool(tool.name)"
>
{{ tool.icon }}
</button>
<button @click="undo">撤销</button>
<button @click="redo">重做</button>
<button @click="save">保存</button>
</div>
</template>
<template #canvas>
<SFrameCanvas />
</template>
<template #sidebar>
<MyCustomPropertiesPanel />
<SFrameLayers />
</template>
</SFrameBoard>
</div>
</template>
<script setup>
import {
SFrameBoard, SFrameCanvas, SFrameLayers, useSFrame
} from 'singularity-frame'
// useSFrame 必须在 SFrameBoard 的子组件中使用
// 这里我们只是为了演示如何获取上下文
function save() {
// const { serialize } = useSFrame() // 这种方式不可行
// 正确的方式是在 SFrameBoard 内部或通过 ref 获取
console.log('保存功能需要从外部触发')
}
</script>
<style>
.my-custom-toolbar {
padding: 10px;
background: #333;
color: white;
}
.my-custom-toolbar button.active {
background: #555;
}
</style>📄 .sframe 文件格式
.sframe 是一个描述画板状态的 JSON 文件。它包含元数据(如视口、主题)和所有图形对象的数组。
结构示例:
{
"version": "1.0",
"meta": {
"viewport": { "x": 0, "y": 0, "zoom": 1 }
},
"shapes": [
{
"id": "shape_1",
"type": "rectangle",
"points": [ { "x": 100, "y": 100 }, { "x": 300, "y": 200 } ],
"style": { "strokeColor": "#ff0000", "strokeWidth": 3 },
"visible": true,
"locked": false
}
]
}📖 API
Props for <SFrame> / <SFrameBoard>
| Prop | Type | Default | Description |
|------------|--------------------------|-------------|-------------------------------------------|
| src | String | undefined | 要加载的 .sframe 文件的 URL。 |
| theme | String or Object | 'light' | 预设主题 ('light', 'dark') 或自定义主题对象。 |
| showGrid | Boolean | true | 是否显示背景网格。 |
| readonly | Boolean | false | 是否将画板设为只读模式。 |
Events
| Event Name | Payload | Description |
|--------------------|----------------|--------------------------------------|
| @shape-created | Shape object | 当一个新图形创建完成时触发。 |
| @selection-changed| String[] | 当选中的图形 ID 列表发生变化时触发。 |
Slots for <SFrameBoard>
| Slot Name | Scope / Props (v-slot="{ ... }") | Description |
|----------------|--------------------------------------------|----------------------------------------------------|
| toolbar | SFrameContext | 工具栏区域。上下文包含所有状态和方法。 |
| canvas | SFrameContext | 画布区域,通常放置 <SFrameCanvas>。 |
| properties | SFrameContext | 属性面板区域,通常放置 <SFrameProperties>。 |
| layers | SFrameContext | 图层面板区域,通常放置 <SFrameLayers>。 |
⌨️ 键盘快捷键
| 快捷键 | 功能 |
|------------------|---------------------|
| Ctrl + Z | 撤销 |
| Ctrl + Y | 重做 |
| Ctrl + Shift + Z | 重做 |
| Delete/Backspace | 删除选中的形状 |
| Ctrl + A | 全选 |
| Escape | 取消选择 |
| V | 选择工具 |
| P | 画笔工具 |
| L | 直线工具 |
| R | 矩形工具 |
| C | 圆形工具 |
| T | 文本工具 |
| E | 橡皮擦工具 |
🎨 主题自定义
使用预设主题
<template>
<SFrame theme="dark" />
</template>自定义主题
<template>
<SFrame :theme="customTheme" />
</template>
<script setup>
const customTheme = {
colors: {
primary: '#007acc',
background: '#1e1e1e',
toolbar: '#2d2d30',
canvas: '#252526',
text: '#cccccc',
border: '#3e3e42'
},
fonts: {
ui: 'Segoe UI, sans-serif',
math: 'KaTeX_Main, serif'
}
}
</script>使用 CSS 变量
:root {
--sf-bg: #f5f5f5;
--sf-text: #333333;
--sf-border: #e0e0e0;
--sf-canvas-bg: #ffffff;
}🔧 高级用法
程序化控制
<template>
<SFrameBoard ref="boardRef">
<!-- 自定义 UI -->
</SFrameBoard>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const boardRef = ref()
onMounted(() => {
const context = boardRef.value.context
// 添加形状
context.addShape({
id: 'my-shape',
type: 'rectangle',
points: [{ x: 100, y: 100 }, { x: 200, y: 200 }],
style: { strokeColor: '#ff0000', fillColor: 'transparent', strokeWidth: 2, opacity: 1 },
visible: true,
locked: false
})
// 选择形状
context.selectedShapes.value = ['my-shape']
// 导出数据
const data = context.serialize()
console.log(data)
})
</script>文本形状与数学公式
sFrame 集成了 singularity-engine,支持在文本形状中使用变量和 LaTeX 数学公式:
<script setup>
// 创建包含数学公式的文本形状
const mathShape = {
id: 'math-example',
type: 'text',
point: { x: 100, y: 100 },
template: '当 x = {x} 时,方程 $f(x) = x^2 + {a}x + {b}$ 的值为 {result}',
variables: {
x: 5,
a: 2,
b: 3,
result: 38
},
width: 400,
height: 60,
style: { strokeColor: 'transparent', fillColor: '#000', strokeWidth: 1, opacity: 1 },
visible: true,
locked: false
}
</script>🤝 贡献
欢迎提交 Issue 和 Pull Request!
📄 许可证
MIT License
| properties | SFrameContext | 属性面板区域。 |
| layers | SFrameContext | 图层面板区域。 |
| statusbar | SFrameContext | 状态栏区域。 |
🤝 贡献
欢迎提交 Pull Requests 和 Issues!
📜 License
MIT
