canvas旋转问题?

问题描述

我在canvas中有多个图片需要旋转一定的角度 但是使用rotate()方法好像是让画布进行旋转,怎么才能让图片旋转

相关代码

ctx.save()
ctx.beginPath()
ctx.rect(item.x * this.backWidth / 375 / 2, item.y * this.backWidth / 375 / 2, item.width * this.backWidth / 375 / 2, item.height * this.backWidth / 375 / 2)
ctx.scale(item.sc, item.sc)
ctx.clip()
if (item.angle != 0) {
    ctx.translate(item.imgx + item.imgw * this.backWidth / 375 / 2 / 2, item.imgy + item.imgh * this.backWidth / 375 / 2 / 2)//图片中心点
    ctx.rotate(item.angle)//旋转角度
    }
ctx.drawImage(item.pic, (item.x + (item.imgx - 0)) * this.backWidth / 375 / 2, (item.y + (item.imgy - 0)) * this.backWidth /375 / 2, item.imgw * this.backWidth / 375 / 2, item.imgh * this.backWidth / 375 / 2)
ctx.translate(0, 0)
ctx.closePath()




阅读 2.5k
3 个回答

多个图片,每个图片有自己的旋转和缩放的话,就把旋转缩放代码放在 save()restore() 中间,确保每次都是初始的绘制状态,才能正确旋转缩放。
这里给个封装好的函数,可以做类似 css 的 translaterotatescale 变换,支持设置变换原点,你可以改一下属性名直接使用

const drawImage = (ctx, img, srcX, srcY, srcW, srcH, x, y, w, h, ox, oy, sx, sy, angle) => {
  ctx.save()
  ctx.translate(x + ox, y + oy)
  ctx.rotate(angle)
  ctx.scale(sx, sy)
  ctx.drawImage(img, srcX, srcY, srcW, srcH, -ox, -oy, w, h)
  ctx.restore()
}

const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')

const drawItem = ({
  img, srcX = 0, srcY = 0,
  srcW = img.naturalWidth, srcH = img.naturalHeight,
  x = 0, y = 0, w = srcW, h = srcH,
  tx = 0, ty = 0, ox = 0.5, oy = 0.5, sx = 1, sy = 1, angle = 0
}) => {
  // tx ty: translate; ox oy: origin; sx sy: scale
  // tx ox sx 默认以 w 为单位,ty oy sy 默认以 h 为单位,可用 '0.5w' '0.5h', '10p' 指定单位
  // angle 默认以 deg 为单位,可用 '45deg' '1rad' '0.5turn' 指定单位
  const parse = (v, d) => parseFloat(v) * ({ w, h, p: 1 }[v.match?.(/[whp]/i)?.[0].toLowerCase()] ?? d);
  [tx, ox, sx] = [tx, ox, sx].map(v => parse(v, w));
  [ty, oy, sy] = [ty, oy, sy].map(v => parse(v, h));
  angle = parseFloat(angle) * ({ deg: Math.PI / 180, rad: 1, turn: Math.PI * 2 }[angle.match?.(/[a-z]+/i)?.[0].toLowerCase() ?? 'deg'])
  drawImage(ctx, img, srcX, srcY, srcW, srcH, x + tx, y + ty, w, h, ox, oy, sx / w, sy / h, angle)
}

drawItem({ img, angle: 90 })

使用例子

8740305a-5269-45fc-8ac3-de8764549832.gif

Pen: https://codepen.io/mannix-zho...

旋转画布之后,重新绘制即可。

一般来说多图会采用分层的方式来处理,如果你没有分层我不知道你绘制的结果符合预期不。

当然,你也可以根据像素点自己做旋转,但是不如重新 drawImage 。

ctx.save()
ctx.rotate(-10 * Math.PI / 180)
ctx.drawImage(img,10,10)
ctx.restore()

ctx.save()
ctx.translate(c.width / 2, c.height / 2)
ctx.rotate(10 * Math.PI / 180)
ctx.drawImage(img,0,0)
ctx.restore()

ctx.save保存当前绘制环境,画完一张图片后用ctx.resotre来恢复之前的环境,这样就可以对每一张图片进行单独操作了,下面的例子是分别对图片进行正/逆时针旋转

image.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏