我只是Swift的初学者,但我试图在我的一个项目中实现这个特殊功能(单词搜索拼图):用平移手势选择多个单元格。我的每个单元格都包含一个包含单个字符的标签。我希望通过平移手势获取用户想要选择的所有字母。目前,我通过计算从每个细胞的中心到经过点a(触摸开始)和b(触摸结束)的线的距离并且仅考虑足够接近该线的细胞来实现此目的。这大部分时间都可以正常工作,但它仍然容易出错,并且肯定会导致用户不满意。你能建议一种更简单的方法吗?
感谢。
一些代码:
func getGridInfo(){
for i in 0...numberOfCells-1{
let indPath = IndexPath(row:i, section:0);
let cell = collectionView?.cellForItem(at: indPath) as? CustomCell;
let frameRect = collectionView?.convert((cell?.frame)!, to: self.view);
coordinates[i] = (cell?.label.text, frameRect?.midX, frameRect?.midY) as? (String, CGFloat, CGFloat);
}
}
@objc func handlePan(touch: UIPanGestureRecognizer){
let touchPoint = touch.location(in: self.view)
switch touch.state{
case .began:
if let line = curLine{
line.removeFromSuperlayer();
}
firstPoint = touchPoint;
case .ended:
secondPoint = touchPoint;
guard let fP = firstPoint,
let sP = secondPoint else {
print("Something went wrong..");
return;
}
let word = getCloseLetters(start:fP, end:sP);
if (words.contains(word) || words.contains(String(word.reversed()))){
playSound(soundUrl: correctUrlSoundFx);
foundWordsLabel.text = word;
foundWordsLabel.textColor = UIColor.green;
// to do: update score
}else{
playSound(soundUrl: incorrectUrlSoundFx);
let attributedString = NSMutableAttributedString(string:word);
attributedString.addAttribute(NSAttributedStringKey.strikethroughStyle, value:2, range: NSMakeRange(0, attributedString.length));
foundWordsLabel.attributedText = attributedString;
foundWordsLabel.textColor = UIColor.red;
}
curLine = addLine(fromPoint: firstPoint!, toPoint: secondPoint!, width:20);
default:
return;
}
func getCloseLetters(start:CGPoint, end:CGPoint) -> String{
var letters = "";
for i in 0...numberOfCells-1{
let tuple = coordinates[i]!;
let x = tuple.1;
let y = tuple.2;
if (checkIfPointIsCloseOrOnTheLine(start: start, end: end, aPoint: CGPoint(x:x,y:y)) == true){
letters += tuple.0;
}
}
return letters;
}
func distanceFromPoint(p: CGPoint, v: CGPoint, w: CGPoint) -> CGFloat {
let pv_dx = p.x - v.x;
let pv_dy = p.y - v.y;
let wv_dx = w.x - v.x;
let wv_dy = w.y - v.y;
let dot = pv_dx * wv_dx + pv_dy * wv_dy;
let len_sq = wv_dx * wv_dx + wv_dy * wv_dy;
let param = dot / len_sq;
var int_x, int_y: CGFloat;
if param < 0 || (v.x == w.x && v.y == w.y) {
int_x = v.x;
int_y = v.y;
} else if param > 1 {
int_x = w.x;
int_y = w.y;
} else {
int_x = v.x + param * wv_dx;
int_y = v.y + param * wv_dy;
}
let dx = p.x - int_x;
let dy = p.y - int_y;
return sqrt(dx * dx + dy * dy);
}
func checkIfPointIsCloseOrOnTheLine(start:CGPoint, end:CGPoint, aPoint:CGPoint, tollerance:CGFloat = 15) -> Bool{
let barHeight = self.navigationController?.navigationBar.frame.size.height;
let newStartPoint = CGPoint(x:start.x, y:start.y - barHeight!);
let newEndPoint = CGPoint(x:end.x, y:end.y - barHeight!);
let distance = distanceFromPoint(p:aPoint, v:newStartPoint, w:newEndPoint);
if distance > tollerance{
return false;
}
return true;
}