唯杰地图 logo唯杰地图
VJMAP
EN

预览视图(PreviewView)

vjcad/references/ui/preview-view.md 8.2 KB179 行
原文

文档:vjcad/doc/ui/preview-view.md 示例:vjcad/example/ui/03previewview.js — 基础 PreviewView

1. 用途

PreviewView 是一个独立 Web Component,用来在 不影响主视图 的前提下显示 CAD 实体或文档。常见场景:

  • 块 / 符号库小图预览
  • 对话框里"预览效果"
  • 缩略图 / 截图
  • Hover 提示框中显示局部内容

它是只读 / 极简的:没有命令系统,没有侧边栏,只支持基本缩放和平移。

2. 模式 1:addEntity

const { PreviewView, LineEnt, CircleEnt, TextEnt } = vjcad;

const preview = new PreviewView({
    backgroundColor: 0x1a242e,    // 深色背景
    interactive: true,            // 允许鼠标缩放 / 平移
    defaultColor: 0x00ff00        // 默认绘制颜色(绿色)
});

document.getElementById('preview-container').appendChild(preview);
await preview.onLoad();           // 等待初始化

const line = new LineEnt([0, 0], [100, 50]); line.setDefaults();
preview.addEntity(line);                    // 用默认颜色

const circle = new CircleEnt([50, 50], 30); circle.setDefaults();
preview.addEntity(circle, 0xff0000);        // 第二参数覆盖颜色

preview.zoomExtents();                      // 缩放到所有内容(方法名是 zoomExtents,不是 zoomToFit)

特点:

  • 实体只是绘制进预览,不会真的写入文档;addEntity 不触发回调 / 事件
  • 第二个 color 参数是 RGB 数值(0xRRGGBB),不是 ACI 颜色索引
  • ⚠️ addEntity 用的是不依赖 Engine 的简化绘制器,只画 LINE / CIRCLE / ARC / ELLIPSE,SPLINE 画成控制点折线;分支里判断的是 'POLYLINE',而 PolylineEnt.type 实际是 'PLINE',所以多段线也画不出;文字、填充、块、标注等一律忽略。要预览这些用 loadDocument(DbDoc 数据)或 renderEntitiesDirect(entities)(用当前文档上下文的完整渲染器,实体须来自当前文档)

3. 模式 2:loadDocument(含图层 / 块 / 完整数据)

import { Engine } from 'vjcad';

// loadDocument 接收 DbDoc 结构:可来自 Engine.currentDoc.toDb(),或手工拼装 DbDoc 字面量
const fullDoc = Engine.currentDoc.toDb();

// PreviewViewConfig 仅 5 键:backgroundColor/backgroundAlpha/interactive/defaultColor/resolution
// (showAxis、showUcsIcon 属于 MainViewConfig,PreviewView 不支持)
const preview = new PreviewView({
    backgroundColor: 0x1a242e,
    interactive: true
});
container.appendChild(preview);
await preview.onLoad();
await preview.loadDocument(fullDoc);          // 真正还原图层 / 颜色 / 字体
preview.zoomExtents();

loadDocument 与 addEntity 区别:

特性 addEntity loadDocument
数据形态 单个实体对象(仅线 / 圆 / 弧 / 椭圆 / 样条近似) 完整 vjcad 文档(含图层 / 字体 / 块,各类实体)
颜色 必须自己传或用默认 还原原图所有属性
字体 / 中文 默认字体 文档自带字体
用途 临时预览几条线 真实图纸缩略 / 别处加载的图

4. PreviewView 选项

// 真实签名:PreviewViewConfig——只有这 5 个键
interface PreviewViewConfig {
    backgroundColor?: number;       // 背景色,默认 0x1a242e
    backgroundAlpha?: number;       // 背景透明度 0-1,默认 1(设 0 可导出透明 PNG)
    interactive?: boolean;          // 是否允许鼠标交互(缩放 / 平移),默认 true
    defaultColor?: number;          // 实体默认绘制颜色,默认白色 0xffffff
    resolution?: number;            // canvas 像素比,默认 window.devicePixelRatio(离屏导出设 1)
}

⚠️ 上游文档把 showAxis/showUcsIcon/showFps/fontPath/fontName/fontKind 列进 PreviewView 选项——这些键在 PreviewViewConfig 里不存在,传了会被忽略(showUcsIcon 等是 MainViewConfig 的键,不是 PreviewView 的)。

5. 常用方法

class PreviewView extends LitElement {
    onLoad(): Promise<void>;
    addEntity(ent: EntityBase, color?: number): void;
    addEntities(ents: EntityBase[], color?: number): void;
    clear(): void;                                        // 清空所有实体
    loadDocument(dbDocument: any, blockName?: string): Promise<void>;
    zoomExtents(): void;
    setView(center: Point2D, zoom: number): void;         // 定点缩放
    get zoom(): number;                                   // 当前缩放 —— getter,写 preview.zoom,不要加 ()
    get viewCenter(): Point2D;                            // getter(返回副本)
    get document(): CadDocument | null;                   // getter:loadDocument 后的预览文档
    renderEntitiesDirect(entities: EntityBase[], backgroundGray?: number): void;
    toThumbnail(width?: number, height?: number, format?: 'png' | 'jpeg'): string;  // dataURL
    getEntityBounds(): BoundingBox | null;
    forceResize(): void;
}

⚠️ zoomToFit / zoomScale / pan / setBackground / captureScreenshot / destroy 都不是 PreviewView 的方法:缩放用 zoomExtents/setView,截图用 toThumbnail(同步返回 dataURL), 销毁用 preview.remove()(disconnectedCallback 负责清理)。

6. 在对话框里嵌入

class MySymbolPreviewDialog extends ModalDialogBase {
    static dialogTitle = '符号预览';

    async firstUpdated() {
        await super.firstUpdated();   // ★ 必须:基类在这里取 base-dialog,漏掉则 startDialog 立即返回、对话框一闪而过
        const host = this.shadowRoot.querySelector('#preview-host');
        this._preview = new PreviewView({ backgroundColor: 0x222, interactive: true });
        host.appendChild(this._preview);
        await this._preview.onLoad();
        await this._preview.loadDocument(this.symbolDoc);
        this._preview.zoomExtents();
    }

    renderContent() {
        return html`<div id="preview-host" style="width: 400px; height: 300px;"></div>`;
    }

    cancel() {
        this._preview?.remove();       // PreviewView 无 destroy();移除即触发 disconnectedCallback 清理
        super.cancel();
    }
}
customElements.define('my-symbol-preview-dialog', MySymbolPreviewDialog);   // 不注册 new 时抛 Illegal constructor

const dlg = new MySymbolPreviewDialog();
dlg.symbolDoc = someDbDoc;
await dlg.startDialog();

7. 中文字体

// PreviewViewConfig 没有字体字段——字体是全局的,经 wasm 服务加载:
const { getWebCadCoreService, Engine, PreviewView } = vjcad;
await getWebCadCoreService().loadFont('/fonts/simsun.ttf', '宋体', 'ttf');
// 或批量:loadFonts([{ path: '/fonts/simsun.ttf', name: '宋体', kind: 'ttf' }])

const preview = new PreviewView({ backgroundColor: 0x1a242e });
container.appendChild(preview);
await preview.onLoad();

// ⚠️ addEntity 不画文字(简化绘制器只认线/圆/弧/椭圆)。文字要走 loadDocument:
const doc = Engine.currentDoc.toDb();          // 或只含文字实体的 DbDoc
await preview.loadDocument(doc);
preview.zoomExtents();
// 或:已在当前文档里的 TextEnt 实例 → preview.renderEntitiesDirect([textEnt]);

不传字体时中文会显示为方框,只有 ASCII 字符正常。loadFont 返回 Promise<FontInfo | null>;fontKind 可选 'ttf' | 'woff' | 'otf' | 'shx'。

红旗

  • 必须 await preview.onLoad() 再 addEntity / loadDocument:未初始化时它们直接 throw Error('Graphics not initialized')(不是静默丢绘制)
  • 销毁页面 / 切换路由前要把元素 preview.remove()(触发 disconnectedCallback 清理),否则有 WebGL context 泄漏
  • loadDocument 接收 DbDoc 结构(currentDoc.toDb() 或手工拼装),**不能把 Engine.currentDoc 直接传进去(结构不同;可取 currentDoc.toDb() 的 DbDoc 结构)
  • 一个页面里 PreviewView 不要超过 ~5 个,每个都吃一个 WebGL 上下文

参考(官方文档 MCP)

  • 文档:vjcad/doc/ui/preview-view.md
  • 示例:
  • vjcad/example/ui/03previewview.js — 基础 PreviewView