PosterRender 是什么
PosterRender
是一种专注于生成高质量海报图像的技术或工具
,常用于生成静态图片
,特别是适合用于营销、宣传和展示的图形设计
。它通常用于在服务端或客户端渲染复杂的图像
,包括文字、图形、图标、背景等,生成可供下载或直接使用的最终图片格式(如 PNG 或 JPEG)。
PosterRender 用来做什么
- 营销海报生成:
用于快速生成电商平台的商品促销海报、活动宣传海报等。 - 用户内容分享:
在社交媒体上分享的内容卡片、个人成就海报(如运动记录、学习记录等)。 - 模版化设计:
通过可配置的模板,快速生成批量的海报,适合规模化需求。 - 动态内容渲染:
根据用户数据动态生成个性化的海报,如公众号文章分享页、个人二维码推广图等。
PosterRender 的优点
- 高效性:
能快速生成高质量的图像,特别适合批量任务。 - 灵活性:
支持高度定制化设计,可以通过模板调整文字、颜色、布局等细节。 - 跨平台支持:
可以在服务端或客户端完成渲染,适合多种技术栈(如 Node.js、Python、前端浏览器)。 - 自动化:
可结合动态数据生成个性化内容,减少人工设计成本。 - 高质量输出:
支持高清图片输出,满足打印与显示需求。
PosterRender 的缺点
- 复杂性:
对于初学者来说,模板配置与设计可能存在一定学习成本。 - 性能依赖:
如果在服务端渲染,生成大量高分辨率图片可能消耗较多的计算资源;如果在客户端渲染,可能受限于设备性能。 - 开发成本:
自定义模板和动态渲染的实现需要一定的开发工作量。 - 实时性限制:
对于需要实时生成大量图片的场景(如高并发访问),可能需要额外优化或使用缓存机制。
PosterRender实例
- 实例是结合
taro+react
实现微信小程序分享商品 - 通过样式增加遮照,设置z-index 浮在页面上
- PosterRender list进行x,y轴坐标布局
// 父组件代码
import type { QrcodeRenderRef } from '@/components/Qrcode/QrcodeRender';
import QrcodeRender from '@/components/Qrcode/QrcodeRender';
const ref = useRef<QrcodeRenderRef>(null);
<QrcodeRender ref={ref} />
// 子组件代码
import type { ForwardRefRenderFunction } from 'react';
import { forwardRef, useCallback, useImperativeHandle, useRef, useState } from 'react';
import type { PosterRenderRef } from '@poster-render/taro-react';
import { PosterRender } from '@poster-render/taro-react';
import { View } from '@tarojs/components';
import Taro, { pxTransform } from '@tarojs/taro';
import classNames from 'classnames';
import { getRoutineCode } from '@/services/promotion';
import styles from './styles.modules.less';
//设置海报的宽度和高度
const SIZE = {
width: 315,
height: 365
};
export interface QrcodeRenderRef {
// 子组件暴露给父组件的方法
open: () => Promise<void>;
}
const QrcodeRender: ForwardRefRenderFunction<QrcodeRenderRef> = (_, ref) => {
const posterRender = useRef<PosterRenderRef>(null);
// const [qrcode, setQrcode] = useState('');
const [rendered, setRendered] = useState(false);
const [visible, setVisible] = useState(false);
const [data, setData] = useState<Promotion.CodeInfo>();
// 请求接口 获取要渲染的数据
const handleShow = useCallback(async () => {
Taro.showToast({
title: '正在生成',
icon: 'loading',
mask: true
});
const res = await getRoutineCode();
if (res?.status !== 200) {
Taro.showToast({
title: '生成失败,请重试',
icon: 'none'
});
return;
}
setData(res?.data);
setVisible(true);
}, []);
useImperativeHandle(
ref,
() => ({
open: async () => {
handleShow().then().catch();
}
}),
[handleShow]
);
const onRender = useCallback(async () => {
Taro.hideLoading();
setRendered(true);
}, []);
const handleHide = useCallback(async () => {
setVisible(false);
setRendered(false);
}, []);
const handleSave = useCallback(() => {
posterRender.current?.savePosterToPhoto();
}, []);
return (
<>
<View
catchMove
className={classNames({
[styles.qrcodeWrap]: true,
[styles.qrcodeWrapShow]: rendered
})}
>
<View className={styles.masker} onClick={handleHide} />
<View className={styles.container}>
<View className={styles.containerBox}>
{visible && (
<PosterRender
disableRerender
ref={posterRender}
canvasId="taro-poster-render"
renderType="image"
canvasWidth={SIZE.width}
canvasHeight={SIZE.height}
debug={false}
style={{
width: pxTransform(SIZE.width),
height: pxTransform(SIZE.height)
}}
showMenuByLongpress
onRender={onRender}
onLongTap={handleSave}
onRenderFail={(err) => console.error('onRenderFail', err?.message)}
onSave={(url) => {
console.warn('onSave', url);
Taro.showToast({
title: '保存成功',
icon: 'none',
duration: 2000
});
}}
onSaveFail={(err) => console.error('onSaveFail', err?.message)}
list={[
{
type: 'rect',
x: 0,
y: 0,
width: SIZE.width,
height: SIZE.height,
backgroundColor: '#fff',
borderWidth: 7,
radius: 16,
borderColor: '#00C8C8'
},
{
type: 'image',
width: 240,
height: 240,
backgroundColor: '#333333',
src: `${data?.url}`,
x: 37,
y: 47,
radius: 120,
mode: 'cover'
},
{
type: 'text',
x: (tw) => (SIZE.width - tw) * 0.5,
y: 310,
text: '长按识别或扫描二维码识别',
fontSize: 14,
color: '#999999',
width: (tw) => tw,
height: 19,
lineHeight: 19
}
]}
/>
)}
<View className={styles.desc}>扫描该二维码与您绑定推广关系</View>
<View onClick={handleSave} className={styles.close}>
保存图片
</View>
</View>
</View>
</View>
</>
);
};
export default forwardRef(QrcodeRender);
// styles.modules.css 代码
}
.qrcodeWrap {
position: fixed;
top: -100%;
left: -200%;
z-index: -1;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.qrcodeWrapShow {
top: 0;
left: 0;
z-index: 9999999999;
}
.masker {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
}
.container {
width: 100vw;
height: 100vh;
}
.containerBox {
position: relative;
top: 50%;
width: 315px;
//height: 503px;
margin: 0 auto;
transform: translateY(-50%);
}
.desc {
margin-top: 35px;
color: #fff;
font-weight: 400;
font-size: 14px;
font-style: normal;
line-height: normal;
text-align: center;
}
.close {
position: absolute;
left: 50%;
display: flex;
align-items: center;
justify-content: center;
width: 249px;
height: 40px;
margin-top: 30px;
color: #fff;
font-weight: 500;
font-size: 18px;
background-color: @primary-color;
border-radius: 249px * 0.5;
transform: translateX(-50%);
}