import { useEffect } from 'react'
import { Poster } from '@/types/poster'
type Props = {
canvasId: string
poster: Poster
}
const DESIGN_WIDTH = 350 // 设计稿宽
const DESIGN_HEIGHT = 500 // 设计稿高
// 图片 宽高坐标 (百分比)
const PHOTO_X = 145 / DESIGN_WIDTH
const PHOTO_Y = 155 / DESIGN_HEIGHT
const PHOTO_WIDTH = 60 / DESIGN_WIDTH
const PHOTO_HEIGHT = 75 / DESIGN_HEIGHT
// 文字 大小坐标 (百分比)
const NAME_FONTSIZE = 12
const NAME_X = 0.5 // 居中
const NAME_Y = 260 / DESIGN_HEIGHT
// 背景图片真实宽高
const REAL_WIDTH = 1724
const REAL_HEIGHT = 2551
const CERT_RATIO = REAL_WIDTH / REAL_HEIGHT
const dpr = REAL_WIDTH / DESIGN_WIDTH // 缩放比例
const RENDER_WIDTH = 315 // 页面展示宽
const RENDER_HEIGHT = Math.floor(RENDER_WIDTH / CERT_RATIO) // 页展示高
const PosterCanvas = ({ poster, canvasId }: Props) => {
useEffect(() => {
drawPoster()
}, [])
const drawPoster = () => {
const canvas = document.getElementById(canvasId) as HTMLCanvasElement
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
// canvas 宽高要设置图片的真实宽高,否则会模糊
canvas.width = REAL_WIDTH
canvas.height = REAL_HEIGHT
// 背景
// const background = document.getElementById('background') as HTMLImageElement
const background = new Image()
background.src = require('./background.jpg')
background.crossOrigin = 'anonymous'
background.onload = () => {
ctx.drawImage(background, 0, 0, REAL_WIDTH, REAL_HEIGHT)
// 姓名
ctx.fillStyle = '#000000'
ctx.font = `bold ${NAME_FONTSIZE * dpr}px 黑体`
ctx.textAlign = 'center'
ctx.fillText(poster.name, NAME_X * REAL_WIDTH, NAME_Y * REAL_HEIGHT)
// 头像
const photo = new Image()
photo.src = poster.photo
photo.crossOrigin = 'anonymous'
photo.onload = () => {
ctx.drawImage(
photo,
PHOTO_X * REAL_WIDTH,
PHOTO_Y * REAL_HEIGHT,
PHOTO_WIDTH * REAL_WIDTH,
PHOTO_HEIGHT * REAL_HEIGHT,
)
}
}
}
// 点击下载
const handleDownload = () => {
try {
const canvas = document.getElementById(canvasId) as HTMLCanvasElement
const data = canvas?.toDataURL('image/jpeg', 0.92) // 若 toDataURL 报错,一般是因为图片跨域了
data && saveFile(data, 'png', '证书')
} catch (error) {
console.error(error)
}
}
// 保存图片
const saveFile = (fileData: string, fileType: 'jpeg' | 'png' = 'jpeg', fileName: string = 'download') => {
let saveLink = document.createElement('a')
// download file name
saveLink.download = fileName + '.' + fileType
// download file data
saveLink.href = fileData
// start download
saveLink.click()
}
if (!poster) return null
return (
<canvas
id={canvasId}
style={{
width: RENDER_WIDTH,
height: RENDER_HEIGHT,
}}
/>
)
}
export default PosterCanvas
感谢浏览,欢迎评论指正,转载请标明出处。