Canvas 生成海报并下载

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 (
    
  )
}

export default PosterCanvas

感谢浏览,欢迎评论指正,转载请标明出处。

你可能感兴趣的:(Canvas 生成海报并下载)