10

シナリオ:

Sのセットを持っていCGPathます。それらはほとんど単なる線です (つまり、閉じた形状ではありません)。UIViewそれらはの draw メソッドで画面に描画されます。

ユーザーがいずれかのパスの近くをタップしたかどうかを確認するにはどうすればよいですか?

これが私が働いていたものです:

UIGraphincsBeginImageContext(CGPathGetBoundingBox(path));
CGContextRef g = UIGraphicsGetCurrentContext();
CGContextAddPath(g,path);
CGContextSetLineWidth(g,15);
CGContextReplacePathWithStrokedPath(g);
CGPath clickArea = CGContextCopyPath(g);  //Not documented
UIGraphicsEndImageContext();

私がやっていることは、私が必要とする機能を持っているので、画像コンテキストを作成することです. 次に、パスをコンテキストに追加し、線幅を 15 に設定します。この時点でパスをなぞると、クリックを見つけるために内部をチェックできるクリック領域が作成されます。そのため、パスをストローク パスに変換するようにコンテキストに指示し、そのパスを別の CGPath にコピーして、ストローク パスを取得します。後で確認できます。

if (CGPathContainsPoint(clickArea,NULL,point,NO)) { ...

それはすべてうまく機能しましたが、CGContextCopyPath文書化されていないため、明らかな理由で使用するのは悪い考えのように思えました。またCGContext、この目的のためだけに を作成することについては、ある種の不器用さもあります。

それで、誰かアイデアはありますか?ユーザーが の任意の領域の近く (この場合は 15 ピクセル以内) をタップしたかどうかを確認するにはどうすればよいCGPathですか?

4

3 に答える 3

23

iOS 5.0以降では、これは次のコマンドを使用してより簡単に実行できますCGPathCreateCopyByStrokingPath

CGPathRef strokedPath = CGPathCreateCopyByStrokingPath(path, NULL, 15,
    kCGLineCapRound, kCGLineJoinRound, 1);
BOOL pointIsNearPath = CGPathContainsPoint(strokedPath, NULL, point, NO);
CGPathRelease(strokedPath);

if (pointIsNearPath) ...
于 2012-10-19T17:25:28.420 に答える
2

さて、私は答えを見つけました。CGPathApply を使用します。

clickArea = CGPathCreateMutable();
CGPathApply(path,clickArea,&createClickArea);

void createClickArea (void *info, const CGPathElement *elem) {
  CGPathElementType type = elem->type;
  CGMutablePathRef path = (CGMutablePathRef)info;
  static CGPoint last;
  static CGPoint subpathStart;
  switch (type) {
    case kCGPathElementAddCurveToPoint:
    case kCGPathElementAddQuadCurveToPoint:
      break;
    case kCGPathElmentCloseSubpath:
    case kCGPathElementMoveToPoint: {
      CGPoint p = type == kCGPathElementAddLineToPoint ? elem->points[0] : subpathStart;
      if (CGPointEqualToPoint(p,last)) {
        return;
      }
      CGFloat rad = atan2(p.y - last.y, p.x - last.x);
      CGFloat xOff = CLICK_DIST * cos(rad);
      CGFloat yOff = CLICK_DIST * sin(rad);
      CGPoint a = CGPointMake(last.x - xOff, last.y - yOff);
      CGPoint b = CGPointMake(p.x + xOff, p.y + yOff);
      rad += M_PI_2;
      xOff = CLICK_DIST * cos(rad);
      yOff = CLICK_DIST * sin(rad);
      CGPathMoveToPoint(path, NULL, a.x - xOff, a.y - yOff);
      CGPathAddLineToPoint(path, NULL, a.x + xOff, a.y + yOff);
      CGPathAddLineToPoint(path, NULL, b.x + xOff, b.y + yOff);
      CGPathAddLineToPoint(path, NULL, b.x - xOff, b.y - yOff);
      CGPathCloseSubpath(path);
      last = p;
      break; }
    case kCGPathElementMoveToPoint:
      subpathStart = last = elem->points[0];
      break;
  }
}

基本的には、ReplacePathWithStrokedPath の独自のメソッドですが、現時点では行でのみ機能します。

于 2009-07-17T22:34:26.857 に答える