跳转到内容

实例 API ​

通过 bind:this 获取的组件实例实现 PowerPointViewerApi:共享的跨绑定查看器约定,与 React ref 句柄和 Vue defineExpose 背后的约定相同,再加上 Svelte 绑定的编辑和导出方法。所有工具栏操作都有对应的实例方法,因此可以隐藏界面控件(showToolbar={false}、showThumbnails={false}),从自己的界面驱动查看器。

svelte
<script lang="ts">
	import { PowerPointViewer, type PowerPointViewerApi } from 'pptx-svelte-viewer';

	let { bytes }: { bytes: Uint8Array } = $props();
	let viewer = $state<PowerPointViewerApi>();
</script>

<PowerPointViewer source={bytes} bind:this={viewer} />

返回快照,而非 store

getter 方法(canUndo()、getZoom()、getSelectedElementIds() 等)返回普通快照,不是响应式 store。需要响应变化时,请使用组件属性中的回调属性,例如 onzoomchange、onselectionchange、ondirtychange。

序列化 ​

方法签名说明
getContent() => Promise<Uint8Array>将当前演示文稿序列化为 .pptx 字节,是 save() 的别名。
方法签名说明
goTo(index: number) => void跳转到从 0 开始的幻灯片索引,自动限制在有效范围内。
goPrev() => void转到上一张幻灯片。
goNext() => void转到下一张幻灯片。
getActiveSlideIndex() => number当前可见幻灯片的索引,从 0 开始。
setActiveSlideIndex(index: number) => voidgoTo 的别名。
getSlideCount() => number已加载演示文稿中的幻灯片数量。

缩放 ​

方法签名说明
getZoom() => number实际缩放比例,1 表示 100%。
setZoom(level: number) => void设置明确的缩放比例,自动限制在有效范围内。
zoomIn() => void放大一级。
zoomOut() => void缩小一级。
zoomReset() => void重置为 100%。

模式与放映 ​

方法签名说明
getMode() => ViewerMode当前模式:'preview' | 'edit' | 'present' | 'master'。
setMode(mode: ViewerMode) => void切换模式。'present' 通过真实的 Fullscreen API 进入全屏放映,其他模式会退出全屏。'edit' 和 'master' 表示启用编辑。
ts
viewer?.setMode('present'); // start presenting; Esc exits

访问与操作幻灯片 ​

方法签名说明
getSlides() => readonly PptxSlide[]完整的幻灯片数组,返回包含完整类型信息的快照。
getSlide(index: number) => PptxSlide | undefined按从 0 开始的索引获取单张幻灯片。
getActiveSlide() => PptxSlide | undefined当前活动幻灯片。
addSlide(afterIndex?: number) => void在给定索引之后添加空白幻灯片,未指定时添加到末尾。
deleteSlides(indexes: number[]) => void按索引删除幻灯片,至少保留一张。
duplicateSlides(indexes: number[]) => void复制给定索引的幻灯片。
moveSlide(fromIndex: number, toIndex: number) => void将幻灯片移动到新位置。
toggleHideSlides(indexes: number[]) => void切换指定幻灯片的隐藏标记。
isDirty() => boolean文档是否存在未保存修改。

访问与操作元素 ​

方法签名说明
getElements(slideIndex?: number) => readonly PptxElement[]某张幻灯片上的元素,默认使用当前幻灯片。
getElementById(id: string, slideIndex?: number) => PptxElement | undefined按 ID 获取单个元素。
updateElement(id: string, updates: Partial<PptxElement>) => void部分更新元素属性,例如 { x: 100, width: 300 }。
updateElements(updates: readonly ElementUpdate[], options?: ElementUpdateOptions) => Promise<void>跨页批量更新元素,整批修改占用一个撤销步骤。
deleteElements(ids: string[]) => void按 ID 从当前幻灯片中删除元素。
duplicateElement(id: string) => string | undefined复制元素,返回新元素的 ID。

插入元素 ​

addElement(element: PptxElement): string | undefined 将元素的防御性副本追加到当前可编辑幻灯片,选中它并返回新 ID。坐标保持不变,组合内的后代也会获得新 ID。未提交的文本通过已有编辑流程确认,正常更新未保存状态和撤销重做历史。同步编辑可能共用一条历史记录,但所有插入都会保留。加载期间、加载失败后、没有当前幻灯片时,以及只读、受保护、预览、放映、模板或母版编辑模式下,返回 undefined。

请使用自包含模型,或来自当前文档的模型。以下示例要求组件已加载且处于编辑模式:

ts
import { createImageElement } from 'pptx-viewer-core';

const image = createImageElement(pngDataUrl, { x: 40, y: 40, width: 160, height: 90 });
const insertedId = viewer?.addElement(image);

此方法不会安装剪贴板监听器、请求远程 URL、决定图片尺寸或导入其他文档的关系。宿主自己的粘贴处理器可以读取图片后调用它。对于新的 data URL 图片,使用上面的工厂函数即可,不要编造 imagePath,因为该字段表示归档中已有的部件。

加载本地图片 ​

此包还导出 createImageElementFromFile(file, canvasSize, signal?)。传入本地 File 或 Blob、以像素为单位的幻灯片尺寸,以及可选的 AbortSignal:

ts
import { createImageElementFromFile } from 'pptx-svelte-viewer';

const image = await createImageElementFromFile(file, canvasSize, signal);

此函数保留图片字节,返回居中且等比例缩小至幻灯片范围内的 ImagePptxElement,不会放大小图。图片或尺寸无效、读取或解码失败、取消操作或缺少浏览器 API 时,返回 null。此辅助函数只会在调用时使用浏览器 API;解码需要这些 API。

它只构造元素,不会修改文档、历史记录、选择状态或剪贴板。await 后,必须确认仍是同一文档和当前目标幻灯片,且仍有编辑权限,然后将非空结果传给 addElement。放弃目标时应取消等待中的操作。仅凭幻灯片 ID 不能确认文档身份;浏览器解码成功也不保证所有图片格式在 PowerPoint 中均能正确保存并重新打开。此函数不会自动安装粘贴监听器。

选择 ​

方法签名说明
getSelectedElementIds() => string[]当前选中元素的 ID。
selectElements(ids: string[]) => void通过代码选择元素。
clearSelection() => void清空选区。
getSelectedElementId() => string | null选中的顶层元素 ID,未选中时为 null。

编辑 ​

设置 editable 时启用,参见快速上手 > 编辑。

方法签名说明
undo() => void撤销上一次提交的编辑。
redo() => void重做上一次撤销的编辑。
canUndo() => boolean是否存在可撤销步骤,返回快照,不具备响应性。
canRedo() => boolean是否存在可重做步骤。
deleteSelected() => void删除选中元素,未选中时不执行操作。
save(format?: PptxSaveFormat) => Promise<Uint8Array>将编辑后的幻灯片序列化为字节('pptx' | 'ppsx' | 'pptm')。
downloadAs(format: PptxSaveFormat, fileName?: string) => Promise<void>保存并以指定格式触发浏览器下载。
downloadPptx(fileName?: string) => Promise<void>保存并以默认名称下载 .pptx。
packageForSharing(fileName?: string) => Promise<void>组装并下载共享包。

启用编辑时可使用以下键盘快捷键:Ctrl / Cmd+Z 撤销,Ctrl / Cmd+Shift+Z 重做,Delete / Backspace 删除,Ctrl / Cmd+D 复制,方向键微移(配合 Shift 使用更大步长),Escape 取消选择。

导出与打印 ​

方法签名说明
exportSlidePng(index?: number) => Promise<void>将幻灯片导出为 PNG 并下载,默认使用当前幻灯片。
copySlideAsImage(index?: number) => Promise<void>将幻灯片作为 PNG 图片复制到系统剪贴板。
exportPdf(options?: ExportPdfOptions) => Promise<void>下载多页 PDF,每页一张幻灯片。
exportGif(options?: ExportGifOptions) => Promise<void>下载动态 GIF。
exportVideo(options?: ExportVideoOptions) => Promise<void>下载 WebM 视频。
print(options?: PrintOptions) => Promise<boolean>打开浏览器打印对话框,支持幻灯片、讲义、备注和大纲。

选项结构、处理流程和独立 SVG 导出函数请参见导出与打印。

示例:外部控件 ​

svelte
<script lang="ts">
	import { PowerPointViewer, type PowerPointViewerApi } from 'pptx-svelte-viewer';

	let { bytes }: { bytes: Uint8Array } = $props();
	let viewer = $state<PowerPointViewerApi>();
	let current = $state(0);
	let count = $state(0);
</script>

<PowerPointViewer
	source={bytes}
	showToolbar={false}
	showThumbnails={false}
	bind:this={viewer}
	onload={({ slideCount }) => (count = slideCount)}
	onslidechange={(index) => (current = index)}
/>

<div>
	<button onclick={() => viewer?.goPrev()}>Prev</button>
	<span>Slide {current + 1} of {count}</span>
	<button onclick={() => viewer?.goNext()}>Next</button>
	<button onclick={() => viewer?.setMode('present')}>Present</button>
</div>

底层构建模块 ​

pptx-svelte-viewer/viewer 入口还导出查看器内部不依赖框架的状态辅助接口:ViewerState、PresentationLoader、clampSlideIndex、fitScale、resolveNavigationKey、zoomInPercent、zoomOutPercent,供宿主基于相同基础能力构建自定义界面。这些接口比组件 API 更底层,常规嵌入场景无需使用。

pptx-svelte-viewer/internals:幻灯片过渡辅助函数 ​

pptx-viewer-shared(所有绑定共用的框架无关逻辑)是一个私有的、未发布的工作区包:它从不发布到 npm,因此该 monorepo 之外的代码无法直接 import 它。宿主如果搭建了自己的放映界面(自定义舞台,而非完整的 PowerPointViewer),仍然需要用到过渡解析器/关键帧和叠加层组件,因此它们改从 pptx-svelte-viewer/internals 子路径重新导出:

ts
import {
	resolveSlideTransition,
	resolveTransitionDurationMs,
	SLIDE_TRANSITION_KEYFRAMES,
	PresentationTransitionOverlay,
} from 'pptx-svelte-viewer/internals';

resolveSlideTransition 将 PptxSlideTransition 映射为退出层/进入层的 CSS animation 简写属性;resolveTransitionDurationMs 计算其有效时长(毫秒),会考虑手动设置的时长、旧版 spd 取值和 PowerPoint 自身的默认值;SLIDE_TRANSITION_KEYFRAMES(别名 SLIDE_TRANSITION_KEYFRAMES_CSS)是这些动画名称所引用的 @keyframes 代码块,只需通过 <style> 元素注入一次。同时导出的还有:getSlideTransitionAnimations、getCinematicTransitionAnimations、getP14TransitionAnimations(经典/影院级/特效三类子解析函数)、CINEMATIC_TRANSITION_KEYFRAMES / P14_TRANSITION_KEYFRAMES_ALL(它们各自的关键帧子代码块)、resolveDirection / resolveDirection8 / resolveOrientation / resolveWheelSpokeCount,以及辅助常量(RANDOM_ELIGIBLE_TYPES、INSTANT、DEFAULT_TRANSITION_DURATION_MS、DEFAULT_MORPH_DURATION_MS、TRANSITION_SPEED_DURATION_MS、EASE、WHEEL_SPOKE_COUNTS),以及 PresentationTransitionOverlay 组件本身。

和其他绑定的 internals 入口一样,这里不受语义化版本兼容保证约束:只有当精选的 pptx-svelte-viewer / pptx-svelte-viewer/viewer 导出确实无法满足需求时才使用,并在依赖它时锁定精确版本。

可打开的文件类型 ​

包根入口重新导出统一的文件类型判断,避免宿主的拖放区域、<input accept> 和加载器各自使用不同规则。手写 endsWith 容易逐渐不一致:本仓库的演示应用曾使用 .pptx,.ppt,.json,导致拖入 .pptm 被拒绝,而组件内部的文件 > 打开却可以正常读取。

ts
import {
	PPTX_OPEN_ACCEPT,
	PRESENTATION_OPEN_EXTENSIONS,
	isSupportedPresentationFile,
	isLegacyBinaryPresentation,
	presentationBaseName,
	savedPresentationFileName,
	type SavedPresentationFormat,
} from 'pptx-svelte-viewer';
导出项类型说明
PPTX_OPEN_ACCEPTstring可直接用于 <input type="file" accept>:.pptx,.ppsx,.pptm,.potx,.ppt,.json。
PRESENTATION_OPEN_EXTENSIONSreadonly string[]未拼接的同一扩展名列表,供拖放区域自行判断。
isSupportedPresentationFile(name?: string | null) => boolean根据选择或拖入的文件名进行快速预筛选,只检查扩展名,最终格式由加载器检测。
isLegacyBinaryPresentation(name?: string | null) => boolean判断是否属于 PowerPoint 97-2003 二进制格式(.ppt、.pps、.pot),这些格式可读取,不属于此保存接口的输出。
presentationBaseName(name?: string | null, fallback?: string) => string去除目录和可加载扩展名,得到文件主名,例如 decks/report.ppt 变为 report。
savedPresentationFileName(name?: string | null, format?: SavedPresentationFormat) => string生成保存副本时提供的文件名,例如 report.ppt 变为 report.pptx。
SavedPresentationFormat'pptx' | 'ppsx' | 'pptm'此保存路径可生成的格式,不包含二进制 .ppt,输出始终为 OpenXML。

“另存为”时应使用 savedPresentationFileName。此路径输出的是 OpenXML 包,如果保留旧版源扩展名,会得到扩展名为 .ppt、内容却是 ZIP 的文件,PowerPoint 会拒绝打开。

基于 Apache-2.0 许可证发布