本指南将帮助您在几分钟内完成 PosterKit 的安装和基础配置,快速体验海报编辑功能。
npm install poster-kit
根据您的项目框架选择对应的适配包:
React 项目
npm install @stencil/react-output-target
Vue 项目
npm install @stencil/vue-output-target
最简单的使用方式,适合快速验证功能:
<!DOCTYPE html>
<html>
<head>
<title>PosterKit Demo</title>
<script
type="module"
src="https://unpkg.com/poster-kit/dist/posterKit/posterKit.esm.js"
></script>
</head>
<body>
<div style="width: 800px; height: 600px;">
<kit-box width="1080" height="1920"></kit-box>
</div>
<script>
const kitBox = document.querySelector('kit-box');
// 添加文本卡片
kitBox.add({
id: 'text-1',
type: 'text',
text: '欢迎使用 PosterKit!',
x: 100,
y: 100,
width: 300,
height: 100,
fontSize: 32,
fontFamily: 'Arial',
color: '#333333',
fontWeight: 'bold',
fontStyle: 'normal',
decoration: 'none',
});
// 监听数据变化
kitBox.addEventListener('current-data-change', (e) => {
console.log('当前选中的卡片:', e.detail);
});
</script>
</body>
</html>
React 项目需要额外的配置来支持 Web Components:
import './App.css';
import type { CardData } from 'poster-kit';
import { KitBox } from 'poster-kit/dist/react/components.ts';
import { type ComponentRef, useRef, useState } from 'react';
const App = () => {
const kitBoxRef = useRef<ComponentRef<typeof KitBox> | null>(null);
const [currentData, setCurrentData] = useState<CardData | null>(null);
// 处理数据变化
function handleDataChange(data: CardData) {
console.log('数据变化:', data);
setCurrentData(data);
}
// 添加文本卡片
function addTextCard() {
kitBoxRef.current?.add({
id: Date.now().toString(),
type: 'text',
text: '新的文本内容',
x: Math.random() * 500,
y: Math.random() * 500,
width: 300,
height: 100,
fontSize: 24,
fontFamily: 'Arial, sans-serif',
color: '#333333',
fontWeight: 'normal',
fontStyle: 'normal',
decoration: 'none',
});
}
// 添加图片卡片
function addImageCard() {
const img = new Image();
img.crossOrigin = 'anonymous';
img.src = 'https://via.placeholder.com/300x200/4285f4/ffffff?text=Sample';
img.onload = () => {
kitBoxRef.current?.add({
id: Date.now().toString(),
type: 'image',
image: img,
x: Math.random() * 400,
y: Math.random() * 400,
width: 300,
height: 200,
});
};
}
// 生成海报
async function generatePoster() {
try {
const canvas = await kitBoxRef.current?.createPoster();
if (canvas) {
const url = canvas.toDataURL('image/png');
const link = document.createElement('a');
link.download = 'poster.png';
link.href = url;
link.click();
}
} catch (error) {
console.error('生成海报失败:', error);
}
}
return (
<div className="app">
<div className="editor-container">
<KitBox
ref={kitBoxRef}
width={1080}
height={1920}
onCurrentDataChange={(e) => handleDataChange(e.detail)}
/>
</div>
<div className="toolbar">
<button onClick={addTextCard}>添加文本</button>
<button onClick={addImageCard}>添加图片</button>
<button onClick={generatePoster}>生成海报</button>
</div>
{currentData && (
<div className="properties-panel">
<h3>属性面板</h3>
<p>选中元素 ID: {currentData.id}</p>
<p>类型: {currentData.type}</p>
<p>
位置: ({currentData.x}, {currentData.y})
</p>
<p>
尺寸: {currentData.width} × {currentData.height}
</p>
</div>
)}
</div>
);
};
export default App;
.app {
display: flex;
height: 100vh;
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.editor-container {
flex: 1;
padding: 20px;
background: #f5f5f5;
}
.toolbar {
width: 200px;
padding: 20px;
background: white;
border-left: 1px solid #e0e0e0;
display: flex;
flex-direction: column;
gap: 10px;
}
.toolbar button {
padding: 10px 15px;
border: 1px solid #ddd;
border-radius: 4px;
background: white;
cursor: pointer;
transition: background-color 0.2s;
}
.toolbar button:hover {
background: #f5f5f5;
}
.properties-panel {
width: 250px;
padding: 20px;
background: white;
border-left: 1px solid #e0e0e0;
overflow-y: auto;
}
.properties-panel h3 {
margin-top: 0;
color: #333;
}
.properties-panel p {
margin: 8px 0;
font-size: 14px;
color: #666;
}
参考我们的 React 完整示例,包含了图片列表、属性编辑面板等完整功能。
Vue 项目需要配置自定义元素识别:
import { defineConfig } from '@rsbuild/core';
import { pluginVue } from '@rsbuild/plugin-vue';
export default defineConfig({
plugins: [
pluginVue({
vueLoaderOptions: {
compilerOptions: {
// 告诉 Vue 将 kit- 开头的标签视为自定义元素
isCustomElement: (tag) => tag.startsWith('kit-'),
},
},
}),
],
});
// Vite 项目配置
// import { defineConfig } from 'vite'
// import vue from '@vitejs/plugin-vue'
//
// export default defineConfig({
// plugins: [
// vue({
// template: {
// compilerOptions: {
// isCustomElement: (tag) => tag.startsWith('kit-'),
// },
// },
// }),
// ],
// })
import { createApp } from 'vue';
import App from './App.vue';
import './index.css';
// 引入并注册 PosterKit 组件
import 'poster-kit/dist/vue/index.ts';
const app = createApp(App);
app.mount('#app');
<template>
<div class="app">
<div class="editor-container">
<kit-box
ref="kitBoxRef"
:width="1080"
:height="1920"
@current-data-change="handleDataChange"
/>
</div>
<div class="toolbar">
<button @click="addTextCard">添加文本</button>
<button @click="addImageCard">添加图片</button>
<button @click="generatePoster">生成海报</button>
</div>
<div v-if="currentData" class="properties-panel">
<h3>属性面板</h3>
<div class="property-item">
<label>ID:</label>
<span>{{ currentData.id }}</span>
</div>
<div class="property-item">
<label>类型:</label>
<span>{{ currentData.type }}</span>
</div>
<div class="property-item">
<label>位置:</label>
<span>({{ currentData.x }}, {{ currentData.y }})</span>
</div>
<div class="property-item">
<label>尺寸:</label>
<span>{{ currentData.width }} × {{ currentData.height }}</span>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import type { CardData } from 'poster-kit';
import { ref } from 'vue';
const kitBoxRef = ref<HTMLKitBoxElement | null>(null);
const currentData = ref<CardData | null>(null);
// 处理数据变化
function handleDataChange(e: CustomEvent<CardData>) {
console.log('数据变化:', e.detail);
currentData.value = e.detail;
}
// 添加文本卡片
function addTextCard() {
kitBoxRef.value?.add({
id: Date.now().toString(),
type: 'text',
text: '新的文本内容',
x: Math.random() * 500,
y: Math.random() * 500,
width: 300,
height: 100,
fontSize: 24,
fontFamily: 'Arial, sans-serif',
color: '#333333',
fontWeight: 'normal',
fontStyle: 'normal',
decoration: 'none',
});
}
// 添加图片卡片
function addImageCard() {
const img = new Image();
img.crossOrigin = 'anonymous';
img.src = 'https://via.placeholder.com/300x200/34a853/ffffff?text=Sample';
img.onload = () => {
kitBoxRef.value?.add({
id: Date.now().toString(),
type: 'image',
image: img,
x: Math.random() * 400,
y: Math.random() * 400,
width: 300,
height: 200,
});
};
}
// 生成海报
async function generatePoster() {
try {
const canvas = await kitBoxRef.value?.createPoster();
if (canvas) {
const url = canvas.toDataURL('image/png');
const link = document.createElement('a');
link.download = 'poster.png';
link.href = url;
link.click();
}
} catch (error) {
console.error('生成海报失败:', error);
}
}
</script>
<style scoped>
.app {
display: flex;
height: 100vh;
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.editor-container {
flex: 1;
padding: 20px;
background: #f5f5f5;
}
.toolbar {
width: 200px;
padding: 20px;
background: white;
border-left: 1px solid #e0e0e0;
display: flex;
flex-direction: column;
gap: 10px;
}
.toolbar button {
padding: 10px 15px;
border: 1px solid #ddd;
border-radius: 4px;
background: white;
cursor: pointer;
transition: background-color 0.2s;
}
.toolbar button:hover {
background: #f5f5f5;
}
.properties-panel {
width: 250px;
padding: 20px;
background: white;
border-left: 1px solid #e0e0e0;
}
.properties-panel h3 {
margin-top: 0;
color: #333;
}
.property-item {
display: flex;
justify-content: space-between;
margin: 8px 0;
font-size: 14px;
}
.property-item label {
color: #666;
font-weight: 500;
}
.property-item span {
color: #333;
}
</style>
参考我们的 Vue 完整示例,了解更多高级用法。
// 监听当前选中卡片变化
kitBox.addEventListener('current-data-change', (e) => {
const cardData = e.detail;
console.log('选中卡片:', cardData);
});
// 生成海报图片
const canvas = await kitBox.createPoster();
const imageUrl = canvas.toDataURL('image/png');
恭喜!您已经成功集成了 PosterKit。接下来可以: