AI 互動行銷頁實戰 — 目標九宮格 — 第 07 章
學完:讓使用者用一句話修改 AI 背景;改文字換配色零成本即時重繪;服務掛掉時漏斗照樣走得完。
核心觀念
迭代有兩種,成本差一千倍:
改背景 = 重新生圖,快則數十秒、慢則兩三分鐘,扣一次額度;
改文字、換配色 = canvas 重繪,不到 0.1 秒,免費。
// 原始 prompt 照舊:風格詞、構圖約束、「不准畫字」鐵律一個字都沒少
let prompt = imagePrompt(req.goal, req.subGoals, preset.words, req.orientation);
// 差異一:使用者那句話「追加」在後面,不是取代
if (req.editInstruction) {
prompt += `\nRevision request from the user (apply it to the previous design): ${req.editInstruction}`;
}
const payload = { prompt,
size: req.orientation === 'portrait' ? '1024x1536' : '1536x1024' };
// 差異二:上一張背景圖放進參考圖欄位(純 base64,去掉 data: 前綴)
if (req.referenceImagesBase64?.length)
payload.reference_images_base64 = req.referenceImagesBase64;
只送「亮一點」三個字,模型就失去風格與構圖的所有上下文,生出來的是另一張不相干的圖。
// main.js:editInstruction 有值 = 修改模式
if (editInstruction && bgRecord) {
referenceImagesBase64.push(
await blobToBase64(await resizeImageBlob(bgRecord.blob, 1280)),
);
}
function rerenderWallpaper() {
renderWallpaper(wallCanvas, {
bgBitmap, // 背景不變,不重新生圖
cells: state.cells,
actions: state.actions,
styleId: state.wallpaper.styleId,
orientation: state.wallpaper.orientation,
mode: wallpaperMode,
});
}
上一章「背景與文字解耦」的紅利在這裡兌現。成品直接把規則講給使用者聽:「不滿意可以輸入修改指示重生背景;改文字或換風格則即時重繪、不用重生。」把貴的路和免費的路明白標出來,使用者自然把額度花在刀口上。
本章真正想教的行銷頁設計觀
生圖服務在排隊、金鑰沒設、額度用完——大多數網站回一句「請稍後再試」,等於送客。
但我們手上握著一份完整的生圖 prompt,它不是只有自家後端能用。
function buildPortablePrompt(goal, subGoals, styleId, orientation) {
let p = imagePrompt(goal, subGoals, presetById(styleId).words, orientation);
// API 參數換成人話:外面的工具不吃 size: '1024x1536' 這種參數
p += orientation === 'portrait'
? '\nAspect ratio 2:3, vertical phone wallpaper.'
: '\nAspect ratio 3:2, horizontal desktop wallpaper.';
return p;
}
copyBtn.addEventListener('click', async () => {
await navigator.clipboard.writeText(buildPortablePrompt(/* ... */));
showMsg(bgMsgEl, '已複製。貼到 ChatGPT 或 Gemini 生成,' +
'生好的圖用下方「匯入背景圖」帶回來。', 'ok');
});
前端的 imagePrompt 模板與 Worker 端逐字同步。clipboard 在非 https 或 file:// 可能不可用——降級路徑自己也要有降級:備一個唯讀 textarea。
importInput.addEventListener('change', async () => {
const file = importInput.files[0];
if (!file) return;
try {
bgBitmap = await createImageBitmap(file);
// 跟 AI 生成的背景同等對待:存 IndexedDB,標記來源是手動匯入
bgRecord = { blob: file, meta: { source: 'manual' },
createdAt: new Date().toISOString() };
bgRecord.id = await idbPut('wallpapers', bgRecord);
rerenderWallpaper(); // cover 裁切吃任何比例,直接重繪
} catch {
showMsg(bgMsgEl, '這張圖讀不進來,請換一張(支援一般圖片格式)。');
}
});
不用檢查長寬比——上一章的 coverRect 本來就吃任何比例。匯入的圖走完全相同的後續流程,連「修改背景」都能接著用(它會成為下一輪的參考圖)。
下一章:防刷與額度——你的金鑰背後是真鈔。Turnstile 人機驗證加四層防線,讓共用額度撐得住公開上線。
對照成品:app/(故意不設金鑰走一次降級路徑) · demos/03-wallpaper/← → 翻頁