Canvas 生成图片模糊的解决方案

发布于 2023-05-12 08:46:21 字数 3636 浏览 64 评论 0

说明:本文省略部分非关键代码,麻烦自己补全。

一般情况,在高清屏的设备下,任何绘制 canvas 中的图像、文字、线条、形状都可能会出现模糊的问题。可通过引入 GitHub 中的 hidpi-canvas 有效地解决。

  1. 首先去 GitHub 下载 hidpi-canvas.js 文件;
  2. 在项目中引入 hidpi-canvas.js 文件;
  3. 调用 getPixelRatio() 函数,得到 ratio 值;
  4. drawImage() 中,将 widthheight 乘以 ratio
  5. 效果如下,但抱歉,没做对比图!

在部分 iOS 设备中,可能会存在 image.onload 失效的问题,会导致无法将图片画到 canvas 中。引起该现象的原因可能是:

1、iOS 中存在 image.onload 失效的问题(注意:image.onload 执行的前提是图片正常加载完成,如果稍微出错,就会执行 image.onerror 而不是 image.onload);
2、如果 image.src 是 base64 格式文件,不要设置 image.crossOrigin = "anonymous",可能会出现 image.onload 无法执行的问题,从而无法正常画图。

关于 onload 失效的问题,看 Stack Overflow 这个解答,可能收获挺多的:IPhone img onload fails

<!-- html -->
<div onclick="makeCanvasToPhoto()" style="width: 100px; padding: 10px 30px; background: #eee; text-align: center;">生成图片</div>
<canvas style="margin: 50px auto;"></canvas>
<!-- 引入js -->
<script type="text/javascript" src="canvas.js"></script>
<script type="text/javascript" src="hidpi-canvas.min.js"></script>
// canvas.js 文件
function makeCanvasToPhoto() {
  const canvas = document.getElementById('canvasBox')
  const context = canvas.getContext('2d')
  const ratio = getPixelRatio(context) // 关键代码
  canvas.width = 300 * ratio // 画布宽度
  canvas.height = 300 * ratio // 画布高度
  const divWidth = 300 * ratio // 用于内容居中
  const divHeight = 300 * ratio // 用于内容居中

  // 画矩形
  context.beginPath()
  context.fillStyle = '#abcdef'
  context.fillRect(0, 0, divWidth, divHeight)
  context.closePath()

  // 图片
  context.beginPath()
  const imgObj = new Image()
  imgObj.crossOrigin = 'anonymous' // 在iOS 9设备中,如果src是base64格式,设置了crossOrigin 属性,会导致无法执行image.onload 而执行image.onerror 函数
  imgObj.src = 'http://img0.imgtn.bdimg.com/it/u=458129248,1588126214&fm=26&gp=0.jpg'
  imgObj.onload = function () {
    const imgWidth = '150'
    const imgHeight = '150'
    context.drawImage(this, 50, 50, imgWidth * ratio, imgHeight * ratio)
  }
  context.closePath()

  // 文本
  context.beginPath()
  context.font = '32px bold'
  context.fillStyle = '#1a1a1a'
  context.textAlign = 'center'
  context.textBaseline = 'middle'
  context.fillText('文本', 50, 240)
  context.closePath()

  context.drawImage(canvas, 0, 0, divWidth, divHeight)
  const base64Obj = canvas.toDataURL('image/png', 1)
  console.log(base64Obj)
}

function getPixelRatio(context) {
  const backingStore =
    context.backingStorePixelRatio ||
    context.webkitBackingStorePixelRatio ||
    context.mozBackingStorePixelRatio ||
    context.msBackingStorePixelRatio ||
    context.oBackingStorePixelRatio ||
    context.backingStorePixelRatio ||
    1
  return (window.devicePixelRatio || 1) / backingStore
}

效果如图:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

星軌x

暂无简介

0 文章
0 评论
22 人气
更多

推荐作者

亽野灬性zι浪

文章 0 评论 0

少年亿悲伤

文章 0 评论 0

南七夏

文章 0 评论 0

qq_EJoXxu

文章 0 评论 0

17780639550

文章 0 评论 0

萌逼全场

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文