视觉示例集
这些图片来自仓库中的示例用例。先用它们确认你需要的功能,再按照相应指南使用当前代码。





低调的角落签名
Section titled “低调的角落签名”await Marker.markText({ backgroundImage: { src: photo }, watermarkTexts: [ { text: '© Acme Studio', position: { position: Position.bottomRight, X: 20, Y: 20 }, style: { color: '#FFFFFFB3', fontSizeRatio: 0.022 }, }, ], saveFormat: ImageFormat.jpg, quality: 92,});清晰的二维码水印
Section titled “清晰的二维码水印”await Marker.markImage({ backgroundImage: { src: photo }, watermarkImages: [ { src: qrCode, position: { position: Position.bottomLeft, X: 24, Y: 24 }, scale: 0.5, trimTransparentPadding: true, }, ], saveFormat: ImageFormat.png,});铺满图片的保护水印
Section titled “铺满图片的保护水印”结合半透明填充、对比色描边、旋转和错行排列,可以让水印保持清晰,同时尽量保留照片内容。
await Marker.markText({ backgroundImage: { src: photo }, watermarkTexts: [ { text: 'CONFIDENTIAL', layout: { type: 'tile', gapX: '8%', gapY: '7%', offsetX: '-2%', stagger: true, }, style: { color: '#FFFFFF88', fontSizeRatio: 0.024, rotate: -24, strokeStyle: { color: '#0F172A88', width: 2 }, }, }, ], saveFormat: ImageFormat.jpg, quality: 92,});同一份 layout 也可以用于 watermarkImages 中的图片,或传给 Marker.mark 的图片图层。
位于文字标签下方的 Logo
Section titled “位于文字标签下方的 Logo”使用 Marker.mark 时,后面的图层会绘制在前面的图层之上。
await Marker.mark({ backgroundImage: { src: photo }, watermarks: [ { type: 'image', src: logo, position: { position: Position.center }, alpha: 0.8, }, { type: 'text', text: 'APPROVED', position: { position: Position.center }, style: { color: '#FFFFFF', fontSize: 32, bold: true }, }, ], saveFormat: ImageFormat.png,});与照片自然融合的水印
Section titled “与照片自然融合的水印”multiply 会保留 Logo 的深色细节并透出底图,screen 适合浅色文字;两者仍会与图层的 alpha 一起生效。
await Marker.mark({ backgroundImage: { src: photo }, watermarks: [ { type: 'image', src: logo, blendMode: 'multiply', position: { position: Position.center }, scale: 0.7, alpha: 0.85, }, { type: 'text', text: 'SCREEN LIGHT', blendMode: 'screen', position: { position: Position.bottomCenter, Y: 32 }, style: { color: '#FFE9B8', fontSize: 36, bold: true }, }, ], saveFormat: ImageFormat.png,});一套配方处理整批图片
Section titled “一套配方处理整批图片”createRecipe 会保存有序图层和导出设置。文字模板可以读取每张图片的变量,以及内置的 index 和 filename;visibleWhen 只在条件匹配时保留对应图层。即使 Web 任务完成顺序不同,批量结果也始终与输入顺序一致。
const recipe = Marker.createRecipe({ schemaVersion: 1, watermarks: [ { type: 'text', text: '© {{studio}} · {{filename}} · #{{index}}', position: { position: Position.bottomRight, X: 24, Y: 24 }, style: { color: '#FFFFFF', fontSize: 28, bold: true }, }, { type: 'image', src: logo, visibleWhen: { variable: 'showLogo', equals: true }, position: { position: Position.topRight, X: 24, Y: 24 }, scale: 0.25, }, ], saveFormat: ImageFormat.jpg, quality: 90,});
const controller = new AbortController();const results = await recipe.applyMany( photos.map((src, index) => ({ backgroundImage: { src }, filename: `photo-${index + 1}`, variables: { studio: 'Acme Studio', showLogo: index % 2 === 0 }, })), { concurrency: 2, signal: controller.signal, onProgress({ settled, total, failed }) { console.log(`${settled}/${total},${failed} 个失败`); }, });
const savedRecipe = JSON.stringify(recipe.toJSON());缺少模板变量或变量值不合法时,只会拒绝对应输入。调用 controller.abort() 后不会再派发新任务;已经开始渲染的图片仍会正常结束。单张图片失败会记录为 rejected,不会中断其他任务。
浏览器批量处理本地文件时,可以显式返回二进制结果:
const webRecipe = Marker.createRecipe(recipeOptions, { resultType: 'blob' });const blob = await webRecipe.apply({ backgroundImage: { src: file } });SDK 不会自动创建 Object URL。只有在界面需要预览时,才由调用方创建并及时释放。
如需免安装体验 Web SDK,请打开在线体验。如需使用原生交互控件和查看架构状态面板,请运行 React Native 示例或 Expo 示例。