Skip to main content

Book Cover Editor

A book cover is a classic "edit a flat design + show it on a 3D book mockup in real-time" scenario. The idea:

  1. Use the editor for the flat design (title, author, background image)
  2. Watch the canvas, re-export a dataURL whenever it changes
  3. Overlay the dataURL on a static 3D book mockup image for a WYSIWYG experience

Canvas

import { createStore } from '@ydesign/react-editor';
import Workspace from '@ydesign/react-editor/canvas/workspace';
import '@ydesign/react-editor/style.css';

const store = createStore({ key: 'YOUR_API_KEY' });

// Typical book cover: 210 × 297 mm @ 300 dpi
store.setSize({ width: 2480, height: 3508 });

store.addElement({
type: 'Image',
src: 'https://images.unsplash.com/photo-1543002588-bfa74002ed7e?w=2480',
left: 0,
top: 0,
width: 2480,
height: 3508,
});

store.addElement({
type: 'Textbox',
text: 'A Great Book',
left: 200,
top: 600,
width: 2080,
fontSize: 240,
fontFamily: 'AlibabaPuHuiTi_2_115_Black',
fill: '#ffffff',
textAlign: 'center',
});

Live preview

Use MobX reaction to regenerate a dataURL with 500ms throttle:

import { useEffect, useState } from 'react';
import { reaction } from 'mobx';
import Workspace from '@ydesign/react-editor/canvas/workspace';

export default function BookCoverApp({ store }) {
const [preview, setPreview] = useState<string | null>(null);

useEffect(() => {
const dispose = reaction(
() => store.toJSON(),
async () => {
const dataUrl = await store.toDataURL({ multiplier: 0.3, format: 'jpeg' });
setPreview(dataUrl);
},
{ delay: 500 },
);
return dispose;
}, [store]);

return (
<div style={{ display: 'flex', height: '100vh' }}>
<div style={{ flex: 1 }}>
<Workspace store={store} />
</div>

<div style={{ width: 400, padding: 24, background: '#f5f5f5' }}>
<div style={{ position: 'relative', width: 280, margin: '0 auto' }}>
<img src="/img/book-mockup.png" style={{ width: '100%' }} />
{preview && (
<img
src={preview}
style={{
position: 'absolute',
top: '6%',
left: '28%',
width: '60%',
height: '88%',
objectFit: 'cover',
transform: 'perspective(800px) rotateY(-18deg)',
transformOrigin: 'left center',
}}
/>
)}
</div>
</div>
</div>
);
}

Key points

  • multiplier: 0.3: preview doesn't need to be full-res; smaller = faster
  • reaction({ delay: 500 }): throttle to avoid 60-per-second regeneration during drags
  • CSS transform: cheap pseudo-3D. Need a real 3D book? Use Three.js or CSS 3D textures

Next steps

  • Multiple preview angles: flat / opened / closed, switchable in the UI
  • Print-ready export: switch to multiplier: 2 to generate the real high-res file for the press

See also