使用 iCarousel 缩放项目
Posted
技术标签:
【中文标题】使用 iCarousel 缩放项目【英文标题】:Scale items with 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
值来完成,但事情对我不起作用,任何人都可以帮助我实现这一目标吗?
谢谢。
【问题讨论】:
【参考方案1】:您可以通过委托方法中的iCarousel
的iCarouselTypeCustom
类型来做到这一点
- (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
中切换x
和y
参数以将项目沿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
。或者,在***.com/questions/19178267/… 上查看我的其他答案以上是关于使用 iCarousel 缩放项目的主要内容,如果未能解决你的问题,请参考以下文章
IOS如何让iCarousel像UIScrollView页面一样滚动
在 iOS 的 icarousel 中使用 AsyncImageView 的问题