我想了解更多關於自定義手勢識別器的知識,所以我正在閱讀Ray Wenderlich教程,我計劃修改它以便了解詳細信息以及我可以輕鬆更改的內容以瞭解如何每個作品都有效,但它是用Swift的先前版本編寫的。 Swift更新了大部分代碼,並且我能夠手動修復其餘部分,但我無法在屏幕上繪製觸摸手勢,並且沒有形狀被識別爲圓形,我希望它們都能與之綁定同樣的問題。該網站的代碼片段如下:Swift 3手勢識別器path.boundingBox是無限的
https://www.raywenderlich.com/104744/uigesturerecognizer-tutorial-creating-custom-recognizers
import UIKit
import UIKit.UIGestureRecognizerSubclass
class CircleGestureRecognizer: UIGestureRecognizer {
fileprivate var touchedPoints = [CGPoint]() // point history
var fitResult = CircleResult() // information about how circle-like is the path
var tolerance: CGFloat = 0.2 // circle wiggle room, lower is more circle like higher is oval or other
var isCircle = false
var path = CGMutablePath() // running CGPath - helps with drawing
override func touchesBegan(_ touches: (Set<UITouch>!), with event: UIEvent) {
if touches.count != 1 {
state = .failed
}
state = .began
let window = view?.window
if let touches = touches, let loc = touches.first?.location(in: window) {
//print("path 1 \(path.currentPoint)")
path.move(to: CGPoint(x: loc.x, y: loc.y)) // start the path
print("path 2 \(path.currentPoint)")
}
//super.touchesBegan(touches, with: event)
}
override func touchesMoved(_ touches: (Set<UITouch>!), with event: UIEvent) {
// 1
if state == .failed {
return
}
// 2
let window = view?.window
if let touches = touches, let loc = touches.first?.location(in: window) {
// 3
touchedPoints.append(loc)
print("path 3 \(path.currentPoint)")
path.move(to: CGPoint(x: loc.x, y: loc.y))
print("path 4 \(path.currentPoint)")
// 4
state = .changed
}
}
override func touchesEnded(_ touches: (Set<UITouch>!), with event: UIEvent) {
print("path 5 \(path.currentPoint)")
// now that the user has stopped touching, figure out if the path was a circle
fitResult = fitCircle(touchedPoints)
// make sure there are no points in the middle of the circle
let hasInside = anyPointsInTheMiddle()
let percentOverlap = calculateBoundingOverlap()
isCircle = fitResult.error <= tolerance && !hasInside && percentOverlap > (1-tolerance)
state = isCircle ? .ended : .failed
}
override func reset() {
//super.reset()
touchedPoints.removeAll(keepingCapacity: true)
path = CGMutablePath()
isCircle = false
state = .possible
}
fileprivate func anyPointsInTheMiddle() -> Bool {
// 1
let fitInnerRadius = fitResult.radius/sqrt(2) * tolerance
// 2
let innerBox = CGRect(
x: fitResult.center.x - fitInnerRadius,
y: fitResult.center.y - fitInnerRadius,
width: 2 * fitInnerRadius,
height: 2 * fitInnerRadius)
// 3
var hasInside = false
for point in touchedPoints {
if innerBox.contains(point) {
hasInside = true
break
}
}
//print(hasInside)
return hasInside
}
fileprivate func calculateBoundingOverlap() -> CGFloat {
// 1
let fitBoundingBox = CGRect(
x: fitResult.center.x - fitResult.radius,
y: fitResult.center.y - fitResult.radius,
width: 2 * fitResult.radius,
height: 2 * fitResult.radius)
let pathBoundingBox = path.boundingBox
// 2
let overlapRect = fitBoundingBox.intersection(pathBoundingBox)
// 3
let overlapRectArea = overlapRect.width * overlapRect.height
let circleBoxArea = fitBoundingBox.height * fitBoundingBox.width
let percentOverlap = overlapRectArea/circleBoxArea
print("Percent Overlap \(percentOverlap)")
print("pathBoundingBox \(pathBoundingBox)")
print("path 6 \(path.currentPoint)")
return percentOverlap
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
state = .cancelled // forward the cancel state
}
}
正如這段代碼應該比較邊框爲路徑,以一個盒子,將適合一個圓圈,並比較教程中所示重疊,但是當我打印pathBoundingBox的狀態是:「pathBoundingBox(inf,inf,0.0,0.0)」這可能是爲什麼percentOverlap是0.我以爲這是path.move(to:loc)loc是第一個觸摸位置,但移動文檔(to :)表示「此方法隱式結束當前子路徑(如果有)並將當前點設置爲point參數中的值。」所以我正在努力弄清楚爲什麼path.boundingBox是無限的...
正如我上面所述,這是一個大型項目,如鏈接到網站所示。我猶豫是否立即將它全部發布在這裏,我不確定它甚至會被允許,但是這是最好的選擇嗎? – Dominick