【问题标题】:Scale items with iCarousel使用 iCarousel 缩放项目
【发布时间】:2013-10-22 09:31:00
【问题描述】:

我正在尝试使用 iCarousel 作为我的解决方案之一,我需要实现如下图

应该是这样的

iCarouselOptionFadeMin iCarouselOptionFadeMax iCarouselOptionFadeRange iCarouselOptionFadeMinAlpha 使用

- (CGFloat)carousel:(iCarousel *)carousel valueForOption:(iCarouselOption)option withDefault:(CGFloat)value

我试图创建一个完全一样的函数

- (CGFloat)alphaForItemWithOffset:(CGFloat)offset

我发现它可以使用offset 值来完成,但事情对我不起作用,任何人都可以帮助我实现这一目标吗?

谢谢。

【问题讨论】:

    标签: iphone ios objective-c icarousel scaletransform


    【解决方案1】:

    您可以通过委托方法中的iCarouseliCarouselTypeCustom 类型来做到这一点

    - (CATransform3D)carousel:(iCarousel *)carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform
    

    只需设置轮播的类型(例如在轮播的视图控制器的viewDidLoad中):

    self.carousel.type = iCarouselTypeCustom;
    

    并根据需要计算转换。我将物体放在双曲线上,并在它们远离中心时将它们缩小一点。我认为这与您的图像非常相似:

    - (CATransform3D)carousel:(iCarousel *)carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform
    {
        const CGFloat offsetFactor = [self carousel:carousel valueForOption:iCarouselOptionSpacing withDefault:1.0f]*carousel.itemWidth;
    
        //The larger these values, as the items move away from the center ...
    
        //... the faster they move to the back
        const CGFloat zFactor = 150.0f;
    
        //... the faster they move to the bottom of the screen
        const CGFloat normalFactor = 50.0f;
    
        //... the faster they shrink
        const CGFloat shrinkFactor = 3.0f;
    
        //hyperbola
        CGFloat f = sqrtf(offset*offset+1)-1;
    
        transform = CATransform3DTranslate(transform, offset*offsetFactor, f*normalFactor, f*(-zFactor));
        transform = CATransform3DScale(transform, 1/(f/shrinkFactor+1.0f), 1/(f/shrinkFactor+1.0f), 1.0);
        return transform;
    }
    

    结果:

    您可以根据自己的喜好调整浮点常量。

    要围绕一个圆圈移动项目,同时缩放它们,只需使用测角函数进行平移,然后旋转和缩放:

    - (CGFloat)carousel:(iCarousel *)carousel valueForOption:(iCarouselOption)option withDefault:(CGFloat)value
    {
        if (option == iCarouselOptionSpacing)
        {
            return value * 2.0f;
        }
        if(option == iCarouselOptionVisibleItems)
        {
            return 11;
        }
        if(option == iCarouselOptionWrap) return YES;
        return value;
    }
    
    - (CATransform3D)carousel:(iCarousel *)carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform
    {
        const CGFloat radius = [self carousel:carousel valueForOption:iCarouselOptionRadius withDefault:200.0];
        const CGFloat offsetFactor = [self carousel:carousel valueForOption:iCarouselOptionSpacing withDefault:1.0f]*carousel.itemWidth;
        const CGFloat angle = offset*offsetFactor/radius;
    
        //... the faster they shrink
        const CGFloat shrinkFactor = 2.0f;
        //hyperbola (now only for shrinking purposes)
        CGFloat f = sqrtf(offset*offset+1)-1;
    
    
        transform = CATransform3DTranslate(transform, radius*sinf(angle), radius*(1-cosf(angle)), 0.0);
        transform = CATransform3DRotate(transform, angle, 0, 0, 1);
        transform = CATransform3DScale(transform, 1/(f*shrinkFactor+1.0f), 1/(f*shrinkFactor+1.0f), 1.0);
        return transform;
    } 
    

    再一次,结果:

    您可以在carousel:valueForOption:withDefault:方法中调整间距和半径。

    享受吧! :)

    【讨论】:

    • 我正在尝试一些与这里不同的东西。你的解决方案对我来说非常有效。我得到了我想要的结果。
    • 嗨,假设我想把它做成一个垂直双曲线,我该怎么做呢?谢谢!
    • iCarousel 有一个属性vertical,它设置滚动手势的方向。此外,您需要在CATransform3DTranslate 中切换xy 参数以将项目沿y 轴移动。
    【解决方案2】:

    稍作修改并在 SWIFT 中复制粘贴 ;) - 非常适合我

    func carousel(carousel: iCarousel, valueForOption option: iCarouselOption, withDefault value: CGFloat) -> CGFloat {
        if option == iCarouselOption.Spacing {
            return value * 1.8
        }
        return value
    }
    
    func carousel(carousel: iCarousel, itemTransformForOffset offset: CGFloat, baseTransform transform: CATransform3D) -> CATransform3D {
        let offsetFactor = self.carousel(carousel, valueForOption: iCarouselOption.Spacing, withDefault: 1) * carousel.itemWidth
    
        let zFactor: CGFloat = 150
        let normalFactor: CGFloat = 0
        let shrinkFactor: CGFloat = 1
        let f = sqrt(offset*offset+1)-1
    
        var transform = CATransform3DTranslate(transform, offset*offsetFactor, f*normalFactor, f*(-zFactor));
        transform = CATransform3DScale(transform, 1/(f/shrinkFactor+1), 1/(f/shrinkFactor+1), 1);
        return transform;
    }
    

    【讨论】:

      【解决方案3】:

      我没有足够的声誉来发表评论,所以我必须再问一个问题作为回复:(

      @burax 是否可以在线性线上而不是双曲线上布局项目但保持调整大小?

      问候,很抱歉这样问

      编辑:通过随机尝试我实现了这个:

      - (CATransform3D)carousel:(iCarousel *)carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform
      {
      const CGFloat radius = [self carousel:carousel valueForOption:iCarouselOptionRadius withDefault:5050.0];
      const CGFloat offsetFactor = [self carousel:carousel valueForOption:iCarouselOptionSpacing withDefault:0.8f]*carousel.itemWidth;
      const CGFloat angle = offset*offsetFactor/radius;
      
      //... the faster they shrink
      const CGFloat shrinkFactor = 2.0f;
      //hyperbola (now only for shrinking purposes)
      CGFloat f = sqrtf(offset*offset+1)-1;
      
      
      transform = CATransform3DTranslate(transform, radius*sinf(angle), radius*(1-cosf(angle)), 0.0);
      transform = CATransform3DRotate(transform, angle, 0, 0, 1);
      transform = CATransform3DScale(transform, 1/(f*shrinkFactor+1.0f), 1/(f*shrinkFactor+1.0f), 1.0);
      return transform;
      }
      

      可能有更好的方法,但我对转换不熟悉 :)

      【讨论】:

      • 基本上您只需要保留 CATransform3DScale + 让 CATransform3DTranslate 在其 X 参数中将项目移动offset。或者,在stackoverflow.com/questions/19178267/… 上查看我的其他答案
      猜你喜欢
      • 1970-01-01
      • 2013-02-27
      • 1970-01-01
      • 1970-01-01
      • 2021-10-11
      • 2013-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多