带子视图的UIViews:缩放时计算位置

时间:2015-10-26 16:06:10

标签: ios swift core-graphics

我有一个视图,我使用Core Graphics绘制,在这个例子中是一个分段的圆圈。用户可以触摸圆圈以沿其圆周创建一个点;这将在UIView上创建一个包含圆形图形的子视图。

然后我实现了一个缩放缩放手势,使圆圈重绘为新的大小。我已经看到大多数捏缩放的实现使用transform属性,但我选择重绘,因为它是所有向量并给出了干净的结果。

我的问题是重新定位点视图。我根据父视图的比例计算这些点的所需位置:当它改变时,我更新了点视图的x / y坐标。然而,似乎存在一些精确问题:随着圆形尺寸的增加,这些点会漂移,因此它们不再适合在线上。这里有几个例子:

a black point on a green circle segment

这是圆圈100%的比例。注意黑点的完美定位。但是当你放大......

enter image description here

这一点离线了。

这是一些代码。我从捏手势的比例中推导出圆的新大小(我修改了一点来约束并减慢它以用于UI目的,所以这是deltaScale),然后像这样绘制它:

let currentSize = self.shape!.bounds.size

let newSize = CGSize(width: self.originalSize.width * deltaScale, height: self.originalSize.height * deltaScale)

self.shape?.frame.size = newSize
self.shape?.center = self.originalCentre!

self.shape?.shapeSize = newSize
self.shape?.setNeedsDisplay()

当捏拉缩放手势完成时,我计算因子:

let xScale = Double(newSize.width) / Double(currentSize.width)
let yScale = Double(newSize.height) / Double(currentSize.height)

self.points = self.points.map{(thisPoint) -> UIView in
       thisPoint.center = CGPoint(x: Double(thisPoint.center.x) * xScale, y: Double(thisPoint.center.y) * yScale)

       return thisPoint
}

(我使用的是CGFloats,但转而使用双打,希望能给我所需的精确度。唉。)

1 个答案:

答案 0 :(得分:2)

您正在累积舍入错误。这是反复执行的:

{
   "took": 2,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 2,
      "max_score": 0,
      "hits": []
   },
   "aggregations": {
      "paragraphs": {
         "doc_count": 3,
         "sentences": {
            "doc_count": 12,
            "Significants": {
               "doc_count": 12,
               "buckets": [
                  {
                     "key": "rund",
                     "doc_count": 4,
                     "score": 2.1794871794871793,
                     "bg_count": 4
                  },
                  {
                     "key": "ball",
                     "doc_count": 3,
                     "score": 1.5178571428571428,
                     "bg_count": 3
                  },
                  {
                     "key": "wm",
                     "doc_count": 3,
                     "score": 1.5178571428571428,
                     "bg_count": 3
                  },
                  {
                     "key": "fussball",
                     "doc_count": 3,
                     "score": 1.5178571428571428,
                     "bg_count": 3
                  }
               ]
            }
         }
      }
   }
}

以低于无限精度的任何形式重复任何形式'x = f(x)'的计算将导致漂移。

欺骗是在等号的两边都没有'thisPoint.center'。最好的方法是让thisPoint.center成为其他状态的纯函数。评论者建议存储所需的角度,这将很好地工作。然后你可以这样做:

thisPoint.center = f(thisPoint.someRadians),其中'f'从polar to rectangular coordinates转换,计算圆的比例。