iCarousel
iCarousel copied to clipboard
Custom carousel with centred item bigger
Hi guys,
I'm trying to achieve the functionality described in the attached image. So I want to have the standard item size like the small items, but only the centred one to become bigger.
For that, I'm using a iCarouselTypeCustom type for the carousel. I used this transformation but now I'm stuck.
- (CATransform3D)carousel:(iCarousel *)_carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform { CGFloat distance = 30; CGFloat z = - fminf(1.0f, fabs(offset)) * distance; return CATransform3DTranslate(transform, offset * _carousel.itemWidth, 0.0f, z); }
I've created a custom transform that is pretty close to what you want:
- (CATransform3D)carousel:(iCarousel *)carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform {
CGFloat dx = carousel.itemWidth * offset;
CGFloat dy = carousel.itemWidth * -0.95f;
CGFloat dz = carousel.itemWidth * -3.0f;
CGFloat o = ABS(offset);
if (o < 1.0) {
dy *= o;
dz *= o;
}
transform = CATransform3DTranslate(transform, dx, dy, dz);
return transform;
}
I think that you'll need to increase the scale of the center item as well as the spacing. I'll upload an alternative transform shortly.
Here you go. Adjust the two constants to change the effect. Note that it actually shrinks the side items instead of expanding the center item - this prevents it from getting pixelated.
- (CATransform3D)carousel:(iCarousel *)carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform
{
const CGFloat centerItemZoom = 1.5;
const CGFloat centerItemSpacing = 1.23;
CGFloat spacing = [self carousel:carousel valueForOption:iCarouselOptionSpacing withDefault:1.0f];
CGFloat absClampedOffset = MIN(1.0, fabs(offset));
CGFloat clampedOffset = MIN(1.0, MAX(-1.0, offset));
CGFloat scaleFactor = 1.0 + absClampedOffset * (1.0/centerItemZoom - 1.0);
offset = (scaleFactor * offset + scaleFactor * (centerItemSpacing - 1.0) * clampedOffset) * carousel.itemWidth * spacing;
if (carousel.vertical)
{
transform = CATransform3DTranslate(transform, 0.0f, offset, -absClampedOffset);
}
else
{
transform = CATransform3DTranslate(transform, offset, 0.0f, -absClampedOffset);
}
transform = CATransform3DScale(transform, scaleFactor, scaleFactor, 1.0f);
return transform;
}
Hi,
Is it possible to make always the first one or the left one to be the selected carousel index. Means the first one to be bigger.
Here is the version for horizontal in swift 3, for c/p:
func carousel(_ carousel: iCarousel, itemTransformForOffset offset: CGFloat, baseTransform transform: CATransform3D) -> CATransform3D {
let centerItemZoom: CGFloat = 1.1
let centerItemSpacing: CGFloat = 1.23
let spacing: CGFloat = self.carousel(iCarouselView, valueFor: .spacing, withDefault: 0.90)
let absClampedOffset = min(1.0, fabs(offset))
let clampedOffset = min(1.0, max(-1.0, offset))
let scaleFactor = 1.0 + absClampedOffset * (1.0/centerItemZoom - 1.0)
let offset = (scaleFactor * offset + scaleFactor * (centerItemSpacing - 1.0) * clampedOffset) * carousel.itemWidth * spacing
var transform = CATransform3DTranslate(transform, offset, 0.0, -absClampedOffset)
transform = CATransform3DScale(transform, scaleFactor, scaleFactor, 1.0)
return transform;
}
Hi, it seems like this code has a problem with autolayout. My first item is ok on all devices, but second, third, ... are not ok on every device except iPhone 6. Has anyone had similar experience? When I set to linear and not custom, everything works perfectly.
hi @nicklockwood, could you help explain centerItemSpacing
from above code meaning? Example how can I set exactly spacing in pixel?
Hello! Does anyone know how I can cycle custom type?