bookcover-3d-web
通过提供书籍封面设计,创建书籍的3D图像。部分 封套 一代系统。
npm install bookcover-3d-web

这是一个WebGL 3D图书渲染器,没有外部图形依赖。
import {Book3DRenderer, generate} from 'bookcover-3d-web'
import type {BookFaces, CoverType, GenerateOptions} from 'bookcover-3d-web'
两个导出都采用相同的SVG面输入并产生相同类型的输出。这个
区别在于生命周期: generate 创建和销毁的一次性帮助器是
渲染器内部,while Book3DRenderer 保持WebGL上下文存活,这样你就可以
低成本地重新渲染(例如,鼠标拖动),而无需重新加载纹理。
使用 generate 用于静态导出。使用 Book3DRenderer 交互式预览。
generate(svgs, options?): Promise<Uint8Array>
创建一个渲染器,加载svg,渲染一次,返回PNG字节,然后清理。
import {generate} from 'bookcover-3d-web'
const png = await generate(
{front: frontSvg, back: backSvg, spine: spineSvg},
{cover_type: 'paperback', azimuth: -30, width: 800, height: 600},
)
interface BookFaces {
front: string // SVG string
back: string // SVG string
spine?: string // SVG string (optional — depth_mm used if absent)
}
interface GenerateOptions {
cover_type?: 'paperback'|'paperback_coil'|'paperback_wire'|'paperback_stitch'|'hardcover'|'hardcover_jacket'
azimuth?: number // horizontal camera angle in degrees (default: -30)
elevation?: number // vertical camera angle in degrees (default: 20)
roll?: number // clockwise rotation in degrees (default: 0)
width?: number // canvas width in pixels (default: 800)
height?: number // canvas height in pixels (default: 600)
}
Book3DRenderer
用于交互式使用的持久渲染器。svg加载一次;呼叫 render() 反复
使用不同的角度而不需要每次重新加载纹理。
import {Book3DRenderer} from 'bookcover-3d-web'
// Create once
const renderer = new Book3DRenderer(800, 600)
// Load SVGs and build geometry (do this when the cover changes)
await renderer.load({front: frontSvg, back: backSvg, spine: spineSvg}, 'paperback')
// Render at any angle — fast, no texture reload
renderer.render(-30, 20) // azimuth, elevation
// Export the current frame
const png = await renderer.to_png()
// Free GPU resources when done
renderer.destroy()
完整的API
const renderer = new Book3DRenderer(width?, height?)
// Load cover face SVGs and build 3D geometry
await renderer.load(svgs: BookFaces, cover_type?: CoverType, depth_mm?: number)
// Render at camera angles (all in degrees)
renderer.render(azimuth?, elevation?, zoom?, roll?, light_az?, light_el?, ambient?, exposure?)
// Resize without recreating WebGL context
renderer.resize(width, height)
// Get projected width/height ratio at default viewing angle
renderer.get_projected_aspect(): number
// Composite onto a background photo
await renderer.composite_photo(background: ImageBitmap, options?: PhotoCompositeOptions)
// Export current frame
await renderer.snapshot(): Promise<ImageBitmap>
await renderer.to_png(): Promise<Uint8Array>
// Free GPU resources
renderer.destroy()
照片合成
composite_photo 以一定的角度渲染书籍,并在a上进行合成
背景图像,带有由光线方向派生的阴影。它返回一个
ImageBitmap 在背景的原生分辨率。

图库介绍了一组背景照片 BACKGROUNDS (仅限元数据)
jpg本身并没有捆绑在npm包中;他们住在回购区
资产树
供您与其他静态资产一起托管)。每个条目都有一个 id (识别
加载哪个图像)和预先调整的相机/照明选项,使书看起来
在那个场景里很自然。对象直接传递背景条目 options 论点-它
扩展 PhotoCompositeOptions.
import {Book3DRenderer, BACKGROUNDS} from 'bookcover-3d-web'
import type {Background} from 'bookcover-3d-web'
// Find the background you want
const bg: Background = BACKGROUNDS.find(b => b.id === 'coffee_table')!
// Load the image however you serve your assets
const img = await fetch(`/assets/3d/backgrounds/${bg.id}.jpg`)
const blob = await img.blob()
const bitmap = await createImageBitmap(blob)
// Render the book, then composite — pass the background entry as options
await renderer.load({front: frontSvg, back: backSvg, spine: spineSvg})
const result = await renderer.composite_photo(bitmap, bg)
// result is an ImageBitmap at the background's native resolution
可用的背景id: table_with_book, wood, coffee_table, table_with_laptop,
table_side.
您还可以通过传递一个plain来合成您自己的图像 PhotoCompositeOptions
对象(所有字段都是可选的-默认情况下给出一个平面开销透视图):
interface PhotoCompositeOptions {
azimuth?: number // horizontal camera angle in degrees (default: -15)
elevation?: number // vertical camera angle in degrees (default: 35)
zoom?: number
roll?: number // clockwise rotation in degrees (default: 0)
book_scale?: number // book width as fraction of background width (default: 0.55)
offset_x?: number // position offset as fraction of background width (0 = centred)
offset_y?: number // position offset as fraction of background height (0 = centred)
light_az?: number // light horizontal angle in degrees
light_el?: number // light vertical angle in degrees
ambient?: number // ambient light level 0–1
}