快速开始
大约 9 分钟
快速开始
本章将引导你快速上手 唯杰WebCAD 开发,从项目创建到绘制第一个图形。
在线示例
在开始之前,可以先体验在线示例:
| 示例 | 描述 | 链接 |
|---|---|---|
| 初始化引擎 | MainView 初始化与配置选项 | 在线演示{target="_blank"} |
| 等待加载完成 | onLoad 异步等待示例 | 在线演示{target="_blank"} |
| Viewer 查看模式 | 只显示绘图区域 | 在线演示{target="_blank"} |
环境要求
- Node.js:16.0 或更高版本
- 包管理器:npm、yarn 或 pnpm
- 浏览器:支持 WebGL 的现代浏览器
创建项目
方式一:使用 Vite 创建新项目
# 创建 Vite + TypeScript 项目
npm create vite@latest my-webcad-app -- --template vanilla-ts
# 进入项目目录
cd my-webcad-app
# 安装 WebCAD 库
npm install vjcad
# 启动开发服务器
npm run dev方式二:在现有项目中添加
# 使用 npm
npm install vjcad
# 使用 yarn
yarn add vjcad
# 使用 pnpm
pnpm add vjcad项目结构
推荐的项目结构:
my-webcad-app/
├── public/
│ └── fonts/ # 字体文件目录
│ ├── simkai.woff # TrueType 字体
│ └── _default.shx # SHX 字体
├── src/
│ ├── main.ts # 入口文件
│ ├── commands/ # 自定义命令
│ └── plugins/ # 自定义插件
├── index.html
├── package.json
└── tsconfig.json初始化引擎
基础初始化
在 index.html 中添加容器:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebCAD 应用</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { width: 100%; height: 100%; overflow: hidden; }
#cad-app { width: 100%; height: 100%; }
</style>
</head>
<body>
<div id="cad-app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>在 main.ts 中初始化:
import { MainView, initCadContainer } from 'vjcad';
// 创建 MainView 实例
const cadView = new MainView({
appname: "我的CAD应用",
version: "v1.0.0"
});
// 将 CAD 视图挂载到容器
initCadContainer("cad-app", cadView);MainView 配置选项详解
MainView 构造函数接受一个配置对象,包含以下选项:
interface MainViewOptions {
/** 应用名称,显示在标题栏 */
appname?: string;
/** 应用版本号 */
version?: string;
/** WASM 服务地址,用于加载 WebAssembly 模块 */
wasmServiceUrl?: string;
/** 后端服务地址,用于文件操作等 API */
serviceUrl?: string;
/** 访问令牌,用于身份验证 */
accessToken?: string;
/** 访问密钥,用于加密图纸 */
accessKey?: string;
/** 插件市场配置文件地址 */
pluginMarketUrl?: string;
/**
* 侧边栏样式
* - "both": 左右两侧都显示
* - "left": 只显示左侧
* - "right": 只显示右侧(默认)
* - "none": 不显示侧边栏
*/
sidebarStyle?: "both" | "left" | "right" | "none";
/** 字体配置列表 */
fonts?: FontConfig[];
}
interface FontConfig {
/** 字体文件路径 */
path: string;
/** 字体名称(可选,会自动从文件名推断) */
name?: string;
/** 字体类型:'woff' | 'ttf' | 'shx' */
kind?: string;
}完整配置示例
import { MainView, initCadContainer } from 'vjcad';
const cadView = new MainView({
// 基础配置
appname: "唯杰WebCAD",
version: "v1.0.0",
// 服务配置
serviceUrl: "http://127.0.0.1:27660/api/v1",
// 认证配置
accessToken: "xxxx",
accessKey: "",
// 界面配置
sidebarStyle: "none", // 初始不显示侧边栏
// 插件配置(可为空)
pluginMarketUrl: './plugins/plugins.json',
// 字体配置
fonts: [
{
path: "./fonts/simkai.woff",
name: "simkai",
kind: "woff"
},
{
path: "./fonts/_default.shx",
name: "_default",
kind: "shx"
}
]
});
initCadContainer("cad-app", cadView);等待初始化完成
WebCAD 初始化是异步的,包括画布创建、WASM 加载、插件加载等。使用 onLoad() 方法可以等待初始化完成后再执行操作:
import { MainView, initCadContainer, Engine, LineEnt } from 'vjcad';
const cadView = new MainView({
appname: "唯杰WebCAD",
version: "v1.0.0",
serviceUrl: "http://127.0.0.1:27660/api/v1",
});
initCadContainer("cad-app", cadView);
// 等待初始化完成后执行操作
await cadView.onLoad();
// 此时可以安全地使用 Engine API
// 使用简化写法:数组代替 Point2D 对象
const line = new LineEnt([0, 0], [100, 100]);
line.setDefaults();
Engine.addEntities(line);
// 缩放到全图
Engine.zoomExtents();提示
onLoad() 返回一个 Promise,在以下初始化完成后 resolve:
- PixiJS 画布创建
- WASM 模块加载
- 字体加载
- 插件系统初始化
- URL 参数处理(自动打开图纸等)
第一个示例:绘制直线
import { Engine, LineEnt } from 'vjcad';
/**
* 绘制一条从 (0,0) 到 (100,100) 的直线
*/
function drawLine() {
// 1. 创建直线实体
// 支持两种写法:
// - 简化写法:new LineEnt([x1, y1], [x2, y2])
// - 标准写法:new LineEnt(new Point2D(x1, y1), new Point2D(x2, y2))
const line = new LineEnt([0, 0], [100, 100]);
// 2. 应用系统默认属性
// 这会设置当前图层、颜色、线型等属性
line.setDefaults();
// 3. 添加到画布(推荐方式)
// Engine.addEntities 会自动处理添加和撤销记录
Engine.addEntities(line);
// 4. 缩放到全图显示
Engine.zoomExtents();
console.log('直线已创建,长度:', line.Length);
}简化写法
WebCAD 支持使用数组 [x, y] 代替 new Point2D(x, y),让代码更简洁。大多数接受坐标参数的方法都支持这种简化写法。
绘制基本图形
绘制圆
import { Engine, CircleEnt } from 'vjcad';
/**
* 绘制圆形
* @param center 圆心坐标 [x, y]
* @param radius 半径
*/
function drawCircle(center: [number, number], radius: number) {
// 创建圆形实体(支持数组简化写法)
const circle = new CircleEnt(center, radius);
// 应用默认属性
circle.setDefaults();
// 添加到画布(自动处理撤销记录)
Engine.addEntities(circle);
// 输出圆的属性
console.log('圆心:', circle.center);
console.log('半径:', circle.radius);
}
// 使用示例
drawCircle([50, 50], 30);绘制圆弧
import { Engine, ArcEnt } from 'vjcad';
/**
* 通过圆心、半径和角度绘制圆弧
*/
function drawArc() {
// 创建圆弧:圆心(100, 100),半径50,从0度到90度
const arc = new ArcEnt(
[100, 100], // 圆心(支持数组简化写法)
50, // 半径
0, // 起始角度(弧度)
Math.PI / 2 // 结束角度(弧度,90度)
);
arc.setDefaults();
Engine.addEntities(arc);
console.log('圆弧起点:', arc.startPoint);
console.log('圆弧终点:', arc.endPoint);
console.log('圆弧长度:', arc.length);
}
/**
* 通过三点绘制圆弧
*/
function drawArcBy3Points() {
const arc = new ArcEnt();
// 三点定弧(支持数组简化写法)
arc.initBy3Pt([0, 0], [50, 50], [100, 0]);
arc.setDefaults();
Engine.addEntities(arc);
}绘制多段线
import { Engine, PolylineEnt, BulgePoints, BulgePoint } from 'vjcad';
/**
* 绘制矩形(闭合多段线)
*/
function drawRectangle(x: number, y: number, width: number, height: number) {
// 创建顶点集合
const points = new BulgePoints();
// 添加四个顶点(凸度为0表示直线段)
// BulgePoint 构造函数支持数组: new BulgePoint([x, y], bulge)
points.add(new BulgePoint([x, y], 0)); // 左下
points.add(new BulgePoint([x + width, y], 0)); // 右下
points.add(new BulgePoint([x + width, y + height], 0)); // 右上
points.add(new BulgePoint([x, y + height], 0)); // 左上
// 创建多段线
const pline = new PolylineEnt(points);
pline.isClosed = true; // 设置为闭合
pline.setDefaults();
Engine.addEntities(pline);
console.log('多段线长度:', pline.length);
console.log('多段线面积:', pline.area);
}
/**
* 绘制带圆弧的多段线
* 凸度(bulge)表示弧段的弯曲程度:
* - 0: 直线段
* - 正值: 逆时针弧段
* - 负值: 顺时针弧段
* - 1: 半圆弧
*/
function drawPolylineWithArc() {
const points = new BulgePoints();
// 直线段 -> 圆弧段 -> 直线段
points.add(new BulgePoint([0, 0], 0)); // 起点,直线到下一点
points.add(new BulgePoint([100, 0], 0.5)); // 弧段起点,凸度0.5
points.add(new BulgePoint([150, 50], 0)); // 弧段终点,直线到下一点
points.add(new BulgePoint([150, 100], 0)); // 终点
const pline = new PolylineEnt(points);
pline.setDefaults();
Engine.addEntities(pline);
}
// 使用示例
drawRectangle(0, 0, 200, 100);绘制文字
import { Engine, TextEnt, MTextEnt } from 'vjcad';
/**
* 绘制单行文字
*/
function drawText(position: [number, number], content: string, height: number = 10) {
const text = new TextEnt();
text.position = position;
text.text = content;
text.height = height;
text.rotation = 0; // 旋转角度(弧度)
text.setDefaults();
Engine.addEntities(text);
}
/**
* 绘制多行文字
*/
function drawMText(position: [number, number], content: string, width: number = 100) {
const mtext = new MTextEnt();
mtext.position = position;
mtext.text = content;
mtext.width = width;
mtext.height = 10;
mtext.setDefaults();
Engine.addEntities(mtext);
}
// 使用示例
drawText([0, 120], "WebCAD 示例文字", 15);
drawMText([0, 150], "这是一段\n多行文字\n示例", 80);设置实体属性
颜色设置
import { Engine, LineEnt } from 'vjcad';
// WebCAD 使用 AutoCAD 颜色索引 (ACI)
// 常用颜色索引:
// 1 = 红色 4 = 青色 7 = 白色
// 2 = 黄色 5 = 蓝色 256 = 随层 (ByLayer)
// 3 = 绿色 6 = 品红 0 = 随块 (ByBlock)
const line = new LineEnt([0, 0], [100, 0]);
line.setDefaults();
// 设置为红色
line.color = 1;
// 设置为随层颜色
line.color = 256;
// 也可以使用 Engine 的当前颜色
line.color = Engine.CECOLOR; // 当前绘图颜色图层设置
import { Engine, LineEnt } from 'vjcad';
const line = new LineEnt([0, 0], [100, 0]);
line.setDefaults();
// 设置图层名称
line.layer = "标注层";
// 获取当前图层
const currentLayer = Engine.CLAYER;
line.layer = currentLayer;
// 创建新图层(如果不存在)
const doc = Engine.currentDoc;
if (!doc.layers.has("我的图层")) {
doc.layers.add("我的图层", {
color: 3, // 绿色
lineType: "CONTINUOUS",
layerOn: true,
frozen: false
});
}
line.layer = "我的图层";线型设置
import { Engine, LineEnt } from 'vjcad';
const line = new LineEnt([0, 0], [100, 0]);
line.setDefaults();
// 设置线型名称
// 常用线型:CONTINUOUS(实线)、HIDDEN(虚线)、CENTER(中心线)
line.lineType = "HIDDEN";
// 设置线型比例
line.lineTypeScale = 2.0;
// 使用当前线型比例
line.lineTypeScale = Engine.CELTSCALE;获取用户输入
获取点
import { Engine, PointInputOptions, InputStatusEnum, LineEnt, Point2D } from 'vjcad';
/**
* 交互式绘制直线
*/
async function drawLineInteractive() {
// 获取第一个点
const opt1 = new PointInputOptions("指定起点:");
const result1 = await Engine.getPoint(opt1);
if (result1.status !== InputStatusEnum.OK) {
console.log('用户取消');
return;
}
const startPoint = result1.value as Point2D;
// 获取第二个点,设置基点用于橡皮线显示
const opt2 = new PointInputOptions("指定终点:");
opt2.basePoint = startPoint; // 设置基点
opt2.useBasePoint = true; // 启用橡皮线
const result2 = await Engine.getPoint(opt2);
if (result2.status !== InputStatusEnum.OK) {
console.log('用户取消');
return;
}
const endPoint = result2.value as Point2D;
// 创建直线(getPoint 返回的是 Point2D 对象,可直接使用)
const line = new LineEnt(startPoint, endPoint);
line.setDefaults();
Engine.addEntities(line);
}获取选择集
import {
Engine,
SelectionSetInputOptions,
InputStatusEnum,
EntityBase
} from 'vjcad';
/**
* 选择实体并修改颜色
*/
async function changeEntityColor(newColor: number) {
// 配置选择选项
const options = new SelectionSetInputOptions("选择要修改颜色的实体:");
// 获取选择集
const result = await Engine.getSelections(options);
if (result.status !== InputStatusEnum.OK) {
console.log('未选择任何实体');
return;
}
const entities = result.value as EntityBase[];
console.log(`选中了 ${entities.length} 个实体`);
// 修改颜色(setter 自动调用 setModified)
entities.forEach(entity => {
entity.color = newColor;
});
// 刷新显示
Engine.regen();
}获取数值输入
import { Engine, RealInputOptions, IntegerInputOptions, InputStatusEnum } from 'vjcad';
/**
* 获取实数输入
*/
async function getRealValue(): Promise<number | null> {
const options = new RealInputOptions("请输入半径值:");
options.defaultValue = 10; // 默认值
const result = await Engine.getReal(options);
if (result.status === InputStatusEnum.OK) {
return result.value as number;
}
return null;
}
/**
* 获取整数输入
*/
async function getIntegerValue(): Promise<number | null> {
const options = new IntegerInputOptions("请输入边数:");
options.defaultValue = 6; // 默认值
const result = await Engine.getInteger(options);
if (result.status === InputStatusEnum.OK) {
return result.value as number;
}
return null;
}带关键字的输入
import { Engine, PointInputOptions, InputStatusEnum } from 'vjcad';
/**
* 带选项的点输入
*/
async function getPointWithKeywords() {
const options = new PointInputOptions("指定点或 [设置(S)/退出(E)]:");
options.keywords = ["S", "E"]; // 定义关键字
const result = await Engine.getPoint(options);
switch (result.status) {
case InputStatusEnum.OK:
console.log('用户输入了点:', result.value);
break;
case InputStatusEnum.KEYWORD:
console.log('用户输入了关键字:', result.stringResult);
if (result.stringResult === "S") {
// 处理设置选项
} else if (result.stringResult === "E") {
// 处理退出选项
}
break;
case InputStatusEnum.CANCEL:
console.log('用户取消了操作');
break;
}
}视图操作
import { Engine } from 'vjcad';
// 缩放到全图(最常用)
Engine.zoomExtents();
// 缩放到选定实体
Engine.zoomToEntities([entity1, entity2]);
// 刷新显示
Engine.regen();使用 Engine 辅助方法添加实体
import { Engine, LineEnt, CircleEnt } from 'vjcad';
// 方式一:使用 Engine.addEntities(推荐)
// 需要先调用 setDefaults() 设置默认属性
const line = new LineEnt([0, 0], [100, 100]);
line.setDefaults();
Engine.addEntities(line); // 单个实体
// 添加多个实体
const circle = new CircleEnt([50, 50], 25);
circle.setDefaults();
Engine.addEntities([line, circle]);
// 方式二:自定义颜色等属性
const ent = new LineEnt([0, 0], [50, 50]);
ent.setDefaults();
ent.color = 1; // 设置为红色
Engine.addEntities(ent);
// 缩放到全图
Engine.zoomExtents();下一步
现在你已经掌握了 WebCAD 的基本使用方法,可以继续学习: