奇怪的画布在Opera中旋转

时间:2012-10-11 21:31:30

标签: javascript canvas html5-canvas opera

我用画布写了简单的简单绘图:

var angle = 20
var k = Math.sin(Math.PI / 180 * angle)
var scaleY = 0.5
var radius = 55
var pushBy = {x: 60, y: 60}

var drawArc = function (context) {
  context.setTransform(1, -k, 0, scaleY, pushBy.x, pushBy.y)
  context.beginPath()
  context.arc(0, 0, radius, 0, Math.PI * 2)
  context.stroke()
}

var canvas = $('canvas')
var context = canvas.getContext('2d')

drawArc(context)

实际上,它完全符合我的需要:它绘制了一个旋转了20度的扁平椭圆,但......不是在Opera中。我也尝试过明确的rotate,它也不起作用。在Chrome和FF中一切都还可以。 难道我做错了什么?有没有解决方法?

2 个答案:

答案 0 :(得分:2)

它看起来像Opera中的一个错误。如果您查看我的http://jsfiddle.net/a6anq/5/,Chrome和Opera中的网格都已正确翻译,但椭圆形不是。看起来Opera在运行arc()时没有考虑变换。

答案 1 :(得分:1)

我的第一种方法是使用arcTo()绘制四个弧,我错误地认为它是通用的解决方法=) 这是代码

var drawArcWith4ArcTo = function (context) {
  context.setTransform(1, -k, 0, scaleY, pushBy.x, pushBy.y)
  context.beginPath()
  context.moveTo(-radius, 0)
  context.lineTo(-radius, 0)
  context.arcTo(-radius, radius, 0, radius, radius)
  context.arcTo(radius, radius, radius, 0, radius)
  context.arcTo(radius, -radius, 0, -radius, radius)
  context.arcTo(-radius, -radius, -radius, 0, radius)
  context.stroke()
}

但由于两个原因,它在Opera中不起作用:

  • Opera的arcTo()需要稍微不同的点作为参数=)
  • 它仍然不会将转换矩阵应用于生成的路径。

所以我被迫使用4个贝塞尔曲线绘制圆形的解决方法:

var drawArcWith4BezierCurves = function () {
  var kappa = 4 * (Math.sqrt(2) - 1) / 3

  return function (context) {
    context.setTransform(1, -k, 0, scaleY, pushBy.x, pushBy.y)
    context.beginPath()
    context.moveTo(-radius, 0)
    context.bezierCurveTo(
      -radius, radius * kappa,
      -radius * kappa, radius,
      0, radius
    )
    context.bezierCurveTo(
      radius * kappa, radius,
      radius, radius * kappa,
      radius, 0
    )
    context.bezierCurveTo(
      radius, -radius * kappa,
      radius * kappa, -radius,
      0, -radius
    )
    context.bezierCurveTo(
      -radius * kappa, -radius,
      -radius, -radius * kappa,
      -radius, 0
    )
    context.stroke()
  }
}

if (Prototype.Browser.Opera)
  drawArc = drawArcWith4BezierCurves()

两个注释:

  • 得到的路径是近似值,而不是绝对的圆圈(怀疑你是否会注意到这个=)
  • 该示例使用了一些Prototype.js,但很容易猜到我的意思。