我需要放置一条线,当有人在这些点之间点击时连接网格中的每两个点,这样它们就可以连接起来。我设法创建了点网格:
func drawPointGrid() {
let points: CGFloat = 5
let cellWidth = bounds.width / points
let cellHeight = bounds.height / points
for i in 0..<Int(points) {
for j in 0..<Int(points) {
let circleX: CGFloat = ((CGFloat(i) + 0.5) * cellWidth)
let circleY: CGFloat = ((CGFloat(j) + 0.5) * cellHeight)
let centerCirclePath = UIBezierPath(ovalIn: CGRect(x: circleX, y: circleY, width: diameter, height: diameter))
let customlayer = CAShapeLayer()
customlayer.path = centerCirclePath.cgPath
customlayer.fillColor = UIColor.black.cgColor
layer.addSublayer(customlayer)
}
}
}
我设法在 View 上画线,但只有当我单击起点并再次单击终点时,才能创建线,但我需要在水平和垂直的每 2 个点之间创建这条线当用户在它们之间点击时:
override func draw(_ rect: CGRect) {
drawPointGrid()
tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(showMoreActions))
tapGestureRecognizer.numberOfTapsRequired = 1
addGestureRecognizer(tapGestureRecognizer)
}
// draw line from point to point that are clicked
var firstPoint: CGPoint?
var secondPoint: CGPoint?
func showMoreActions(touch: UITapGestureRecognizer) {
let touchPoint = touch.location(in: self)
guard let _ = firstPoint else {
firstPoint = touchPoint
return
}
guard let _ = secondPoint else {
secondPoint = touchPoint
addLine(start: firstPoint!,end: secondPoint!)
firstPoint = nil
secondPoint = nil
return
}
}
func addLine(start: CGPoint,end:CGPoint) {
let line = CAShapeLayer()
let linePath = UIBezierPath()
linePath.move(to: start)
linePath.addLine(to: end)
line.path = linePath.cgPath
line.strokeColor = UIColor.black.cgColor
line.lineWidth = 2
line.lineJoin = kCALineJoinRound
layer.addSublayer(line)
}
最佳答案
我编写了一个名为 findEndPoints
的函数,它可以在 View 中给定一个 touchPoint
的情况下找到正确线端点的 CGPoint
坐标。我将大部分工作作为 Double
类型完成,这样就不必担心它与 CGFloat
之间的转换。
我还将 touchGestureRecognizer 的设置移动到从 init
调用的 setup
例程,因为您只想执行一次并 draw
可以多次调用。
class DotsView: UIView {
let diameter = CGFloat(5)
func setup() {
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(showMoreActions))
tapGestureRecognizer.numberOfTapsRequired = 1
addGestureRecognizer(tapGestureRecognizer)
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
override func draw(_ rect: CGRect) {
drawPointGrid()
}
// draw line between points
func showMoreActions(touch: UITapGestureRecognizer) {
let touchPoint = touch.location(in: self)
let (start, end) = findEndPoints(touchPt: touchPoint)
addLine(start: start, end: end)
}
func addLine(start: CGPoint,end:CGPoint) {
let line = CAShapeLayer()
let linePath = UIBezierPath()
linePath.move(to: start)
linePath.addLine(to: end)
line.path = linePath.cgPath
line.strokeColor = UIColor.black.cgColor
line.lineWidth = 2
line.lineJoin = kCALineJoinRound
layer.addSublayer(line)
}
func drawPointGrid() {
let points: CGFloat = 5
let diameter: CGFloat = 5
let cellWidth = bounds.width / points
let cellHeight = bounds.height / points
for i in 0..<Int(points) {
for j in 0..<Int(points) {
let circleX: CGFloat = ((CGFloat(i) + 0.5) * cellWidth)
let circleY: CGFloat = ((CGFloat(j) + 0.5) * cellHeight)
let centerCirclePath = UIBezierPath(ovalIn: CGRect(x: circleX, y: circleY, width: diameter, height: diameter))
let customlayer = CAShapeLayer()
customlayer.path = centerCirclePath.cgPath
customlayer.fillColor = UIColor.black.cgColor
layer.addSublayer(customlayer)
}
}
}
func findEndPoints(touchPt: CGPoint) -> (pt1: CGPoint, pt2: CGPoint) {
let points = 5.0
let cellWidth = Double(bounds.width) / points
let cellHeight = Double(bounds.height) / points
// convert touch point to grid coordinates
let gridX = Double(touchPt.x) / cellWidth - 0.5
let gridY = Double(touchPt.y) / cellHeight - 0.5
// snap to nearest point in the grid
let snapX = round(gridX)
let snapY = round(gridY)
// find distance from touch to snap point
let distX = abs(gridX - snapX)
let distY = abs(gridY - snapY)
// start second point on top of first
var secondX = snapX
var secondY = snapY
if distX < distY {
// this is a vertical line
if secondY > gridY {
secondY -= 1
} else {
secondY += 1
}
} else {
// this is a horizontal line
if secondX > gridX {
secondX -= 1
} else {
secondX += 1
}
}
let halfdot = Double(diameter) / 2
// convert line points to view coordinates
let pt1 = CGPoint(x: (snapX + 0.5) * cellWidth + halfdot, y: (snapY + 0.5) * cellHeight + halfdot)
let pt2 = CGPoint(x: (secondX + 0.5) * cellWidth + halfdot, y: (secondY + 0.5) * cellHeight + halfdot)
return (pt1, pt2)
}
}
关于swift - 用线连接网格中的点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44614090/