canvas image模糊失真
2021-09-02 本文已影响0人
Shiki_思清
知识点:
-
pixelRatio拿到当前机型设备的像素比(dpr)
-
canvas.width 和 canvas.height 是画布本体宽高
-
https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Transformations
用scale(x, y)
来增减图形(ctx)在 canvas 中的像素数目,对形状,位图进行缩小或者放大。默认情况下,canvas 的 1 个单位为 1 个像素 -
style或CSS设置的 width 和height ,是画布进行拉伸挤压后展示出来的宽高
关系
- 像素比(dpr)越大,说明该设备高清,如果图片不扩大像素比,那就一定会失真
- 先将canvas.width=imgWidth*dpr 画布本体宽高放大 像素比(dpr) 倍数,为图片提供足够的空间
- 再将ctx.scale(dpr, dpr) 将画布上的 每一个单位 通过该方法将 像素数目 放大dpr倍
- 展示出来的宽高还是需要按照设备宽高来比例设置
<canvas style={{ width: imgWidth, height: imgHeight }} />
- 最后在画布上绘制图片,宽高也同样以设备的宽高来比例设置
// 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 }}
/>