【问题标题】:Reposition/resize UIBezierPath重新定位/调整 UIBezierPath 的大小
【发布时间】:2013-12-22 10:00:27
【问题描述】:

我有一个可拖动的视图,上面有一个遮罩层。遮罩层上有一个 UIBezierPath ,它使视图上的一个区域透明/透明(我想要的效果)。我的最终目标是通过传递基于我的视图和另一个矩形的交集计算的 CGRect 来更改路径的位置和大小(不是遮罩层!)(基本上我想隐藏相交的区域)。

1)我如何创建我的蒙版和路径(在我的视图上创建一个透明矩形):

self.maskLayer = [CAShapeLayer layer];
self.maskLayer.frame = self.contentView.bounds;

//default path rect
CGRect const rect = CGRectMake(CGRectGetMidX(self.contentView.bounds) ,
                                     CGRectGetMidY(self.contentView.bounds),
                                     50,50);


path = [UIBezierPath bezierPathWithRect:rect];

[path appendPath:[UIBezierPath bezierPathWithRect:self.contentView.frame]];

self.maskLayer.path = path.CGPath;

self.maskLayer.fillRule = kCAFillRuleEvenOdd;

self.contentView.layer.mask = self.maskLayer;

2) 我的问题是我找不到仅调整路径大小/重新定位的方法。我在网上搜索,但没有找到任何解决方案。

此代码不起作用,但这是我能想到的:

//runs while the view is being dragged(using UIPanGestureRecognizer)
-(void)move{
 CGRect intersectedRect = CGRectIntersection(self.frame, self.productView.frame);
 path = [UIBezierPath bezierPathWithRect:intersectedRect];
[path appendPath:[UIBezierPath bezierPathWithRect:intersectedRect]];
[self.maskLayer setNeedsDisplay];
 }

如何在我的移动功能中仅操作遮罩层的路径? 谢谢!

【问题讨论】:

  • 第二个sn-p中的path变量是从哪里得到的?你在哪里设置蒙版层的路径?为什么要将相同的矩形附加到路径?
  • 我使用第一个 sn-p 中的相同路径变量,一个全局路径变量。我在第一个 sn-p 上设置了路径(self.maskLayer.path = path.CGPath;)我将 self.contentView.frame 附加到路径,抱歉是类型错误。
  • 是的,但我看不到您在 move 方法中分配更新路径的位置。
  • -(void)move{ CGRect intersectedRect = CGRectIntersection(self.frame, self.productView.frame);路径 = [UIBezierPath bezierPathWithRect:intersectedRect]; [路径 appendPath:[UIBezierPath bezierPathWithRect:self.contentView.frame]]; self.maskLayer.path = path.CGPath; self.maskLayer.fillRule = kCAFillRuleEvenOdd; self.contentView.layer.mask = self.maskLayer; }
  • 现在它正在更新,但在 10 秒后。你知道为什么会这样吗?

标签: ios iphone ios7 mask uibezierpath


【解决方案1】:
// example path
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 100, 100) cornerRadius:4];

// scale it
CGFloat scale = 0.9;
[path applyTransform:CGAffineTransformMakeScale(scale, scale)];

// move it
CGSize translation = CGSizeMake(10, 5);
[path applyTransform:CGAffineTransformMakeTranslation(translation.width,
                                                      translation.height)];

// apply it
self.myLayer.path = path;

【讨论】:

    【解决方案2】:

    Swift 版本

    这是@hfossli 的 Swift 代码:

    // example path
    let path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 100, height: 100), cornerRadius: 4)
    
    // scale it
    let scale = CGFloat(0.9)
    path.applyTransform(CGAffineTransformMakeScale(scale, scale))
    
    // move it
    let translation = CGSize(width: 10, height: 5)
    path.applyTransform(CGAffineTransformMakeTranslation(translation.width,
        translation.height))
    
    // apply it
    self.myLayer.path = path
    

    更新

    我在实际实践中发现,我只是在创建 UIBezierPath 时使用不同的初始值,而不是稍后对其进行转换。我想这取决于目的。

    【讨论】:

      【解决方案3】:

      Swift 3 扩展(如果需要,可以使用 factorX、factorY 进行修改):

      extension UIBezierPath
      {
          
          func scaleAroundCenter(factor: CGFloat)
          {
              let beforeCenter = self.bounds.getCenter()
              
              // SCALE path by factor
              let scaleTransform = CGAffineTransform(scaleX: factor, y: factor)
              self.apply(scaleTransform)
              
              let afterCenter = self.bounds.getCenter()
              let diff = CGPoint(
                  x: beforeCenter.x - afterCenter.x,
                  y: beforeCenter.y - afterCenter.y)
              
              let translateTransform = CGAffineTransform(translationX: diff.x, y: diff.y)
              self.apply(translateTransform)
          }
      

      SWIFT 5 更新

      extension UIBezierPath {
      
          func scaleAroundCenter(factor: CGFloat) {
              let beforeCenter = CGPoint(x: self.bounds.midX, y: self.bounds.midY)
      
              // SCALE path by factor
              let scaleTransform = CGAffineTransform(scaleX: factor, y: factor)
              self.apply(scaleTransform)
      
              let afterCenter = CGPoint(x: self.bounds.midX, y: self.bounds.midY)
              let diff = CGPoint( x: beforeCenter.x - afterCenter.x, y: beforeCenter.y - afterCenter.y)
      
              let translateTransform = CGAffineTransform(translationX: diff.x, y: diff.y)
              self.apply(translateTransform)
          }
      
      }
      

      【讨论】:

      • 我不确定这是否解决了 OP 的问题,但它确实解决了我的问题 :-)
      【解决方案4】:

      您需要在 move 方法中将更新后的路径分配给 self.maskLayer.path

      【讨论】:

        【解决方案5】:

        Swift 3 或更高版本

        func move(path: UIBezierPath, fromPoint: CGPoint, toPoint: CGPoint) {
            let moveX = toPoint.x - fromPoint.x
            let moveY = toPoint.y - fromPoint.y
            path.apply(CGAffineTransform(translationX: moveX, y: moveY))
        }
        
        func scale(path: UIBezierPath, fromSize: CGSize, toSize: CGSize) {
            if fromSize.width == 0 || fromSize.height == 0 {
                return
            }
            let scaleWidth = toSize.width / fromSize.width
            let scaleHeight = toSize.height / fromSize.height
            path.apply(CGAffineTransform(scaleX: scaleWidth, y: scaleHeight))
        }
        

        【讨论】:

        • 我如何使用 swift4?
        • 就我而言,它在 swift 5 中工作
        【解决方案6】:

        斯威夫特 4

        func tableView(_ tableView: UITableView, dragPreviewParametersForRowAt indexPath: IndexPath) -> UIDragPreviewParameters? {
            let cell = tableView.cellForRow(at: indexPath) as! ItemTableViewCell
        
            let previewParameters = UIDragPreviewParameters()
            let path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: cell.frame.width, height: cell.frame.height), cornerRadius: 4)
            let scale = CGFloat(0.85)
            path.apply(CGAffineTransform(scaleX: scale, y: scale))
            let translation = CGSize(width: 10, height: 5)
            path.apply(CGAffineTransform(translationX: translation.width, y: translation.height))
            previewParameters.visiblePath = path
            return previewParameters
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-14
          • 2019-11-13
          • 2022-11-19
          相关资源
          最近更新 更多