Масштабируйте элементы с iCarousel

Я пытался использовать iCarousel для одного из своих решений, мне нужно добиться чего-то вроде изображения ниже введите описание изображения здесь

Это должно быть именно так

iCarouselOptionFadeMin iCarouselOptionFadeMax iCarouselOptionFadeRange iCarouselOptionFadeMinAlpha работает с использованием

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

Я попытался создать функцию точно так же, как

- (CGFloat)alphaForItemWithOffset:(CGFloat)offset

Я обнаружил, что это можно сделать, используя значения offset, но у меня ничего не работает, может ли кто-нибудь помочь мне в этом?

Спасибо.


person iphonic    schedule 22.10.2013    source источник


Ответы (3)


Вы можете сделать это с помощью типа 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;
}

и результат: result

вы можете настроить константы float по своему вкусу.

Для перемещения элементов по кругу при их масштабировании просто используйте гониометрические функции для перемещения, затем вращайте и масштабируйте:

- (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;
} 

и снова результат: result2

вы можете настроить интервал и радиус в методе carousel:valueForOption:withDefault:.

Наслаждаться! :)

person burax    schedule 22.10.2013
comment
Я пробовал что-то отличное от того, что здесь. и ваше решение отлично сработало для меня. Я получил желаемый результат. - person Karthik; 10.12.2013
comment
Привет, предположим, я хочу сделать вертикальную гиперболу, как мне это сделать? Спасибо! - person Gabriel Lim; 10.02.2014
comment
iCarousel имеет свойство vertical, которое устанавливает направление жестов прокрутки. Кроме того, вам нужно переключить параметры x и y в CATransform3DTranslate, чтобы вместо этого перемещать элементы вдоль оси Y. - person burax; 10.02.2014

Немного изменен и в 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;
}
person Appygix    schedule 19.08.2016

У меня недостаточно репутации, чтобы комментировать, поэтому я должен задать дополнительный вопрос в качестве ответа :(

@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;
}

возможно, есть лучший способ, но я новичок в преобразованиях :)

person ergunkocak    schedule 09.07.2015
comment
По сути, вам нужно оставить только CATransform3DScale + заставить CATransform3DTranslate перемещать элементы на offset в своем параметре X. Кроме того, проверьте мой другой ответ на stackoverflow.com/questions/19178267/ - person burax; 10.07.2015