canvas image模糊失真

2021-09-02  本文已影响0人  Shiki_思清

知识点:

  1. pixelRatio拿到当前机型设备的像素比(dpr)

  2. canvas.width 和 canvas.height 是画布本体宽高

  3. https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Transformations
    scale(x, y)来增减图形(ctx)在 canvas 中的像素数目,对形状,位图进行缩小或者放大。默认情况下,canvas 的 1 个单位为 1 个像素

  4. style或CSS设置的 width 和height ,是画布进行拉伸挤压后展示出来的宽高

关系

  1. 像素比(dpr)越大,说明该设备高清,如果图片不扩大像素比,那就一定会失真
  2. 先将canvas.width=imgWidth*dpr 画布本体宽高放大 像素比(dpr) 倍数,为图片提供足够的空间
  3. 再将ctx.scale(dpr, dpr) 将画布上的 每一个单位 通过该方法将 像素数目 放大dpr倍
  4. 展示出来的宽高还是需要按照设备宽高来比例设置<canvas style={{ width: imgWidth, height: imgHeight }} />
  5. 最后在画布上绘制图片,宽高也同样以设备的宽高来比例设置

// 1. 首次加载先拿到图片的尺寸
useEffect(() => {
      // 2. 先拿到图片大小, 来初始化canvas大小
      Taro.getImageInfo({ src: initUrl }).then((res) => {
        const { width, height } = res  // 3. 图片大小
        const devide = width / height   // 4. 真实图片宽高比
        const ww = Taro.getSystemInfoSync().screenWidth   // 5. 屏幕宽
        const hh = Math.round(ww / devide)  // 6. 等比高

        console.log('width', width, ww);
        
        dispatch({ type: 'setPaperRect', payload: [ww, hh] })

        // 首次
        resetCanvasAndDrawImage(ww, hh, initUrl).then(() => {
          pushDrawStack('common')
        })
      })
    }, [])

// 7. 调用方法,渲染canvas
const resetCanvasAndDrawImage = (ww: number, hh: number, url: string) => {
      // canvas需要等到宽高确定之后才能开始画图, 此时dom已经渲染完成
      return new Promise<void>((resolve) => {
        const query = Taro.createSelectorQuery()
        query.select('#paper_canvas')
          .fields({ node: true, size: true })
          .exec((res) => {
            // 8. 初始化canvas 2d
            const canvas = res[0].node
            const ctx = canvas.getContext('2d')
            // 9. 重要,拿到像素比
            const dpr = Taro.getSystemInfoSync().pixelRatio
            // 10. 根据像素比放大canvas本体,为后面绘图提供更大空间
            canvas.width = ww * dpr
            canvas.height = hh * dpr
            // 11. 放大每个单位像素比
            ctx.scale(dpr, dpr)
            // 12. canvas展示出来的宽高,还是按照上面获得的比例宽高设置
            setCanvasW(ww)
            setCanvasH(hh)

            // 保存 canvas 指针 
            stateSync.current.ctx = ctx
            stateSync.current.canvas = canvas

            // 渲染图片
            const image = canvas.createImage()
            image.onload = () => {
              // 13. 开始绘图图片,图片的展示宽高,与canvas的展示宽高一致就好
              ctx.drawImage(image, 0, 0, ww, hh)
              resolve()
            }
            image.src = url
          })
      })
    }


<Canvas
          type='2d'
          id='paper_canvas'
          style={{ width: canvasW, height: canvasH }}
        />
上一篇下一篇

猜你喜欢

热点阅读