Marquee Effect
Now left us to see the effect
我們可以看到跑马灯的效果,其实是由一条虚实线做循环移动组成的。
如果我们要做这个效果是要把什么地方绘制一个小横线,空一段,这样循环下去吗???那移动的动画又要怎样做呢!!好像变得无比复杂。
- 这个时候,我们就要用到CAShapeLayer这个特殊的Layer。
- 它有个属性lineDashPhase,我们要利用它做出虚实线。
上代码
[ self setFillColor: [ UIColor clearColor ].CGColor ];
[ self setStrokeColor: [ UIColor whiteColor ].CGColor ];
[ self setLineWidth: 2.F ];
[ self setLineJoin: kCALineJoinRound ];
[ self setLineDashPattern: @[@(10), @(5)] ];
先让填充色为无颜色,再者设置线段实线部分的颜色,设置lineDashPattern这个属性,第一个参数是设置实线的长度,第二个参数是填写虚线部分的长度[即空白的线段长度]。
那此时就是可以了吗?不行,要设置layer的path属性,最终绘制的虚实线,是根据path来绘制的。
上代码
- ( void ) SetAnimationPath
{
if ( self.superlayer == nil )
{
return;
}
UIWindow* aTopWindow = [[ UIApplication sharedApplication ].windows lastObject];
while ( aTopWindow.superview != nil )
{
UIView* aView = aTopWindow.superview;
aTopWindow = (UIWindow*)aView;
}
CALayer* aTopLayer = aTopWindow.layer;
CGRect aTopFrame = [ self convertRect: self.bounds toLayer: aTopLayer ];
CGRect aTopIntersection = CGRectIntersection(aTopFrame, aTopLayer.bounds);
CGRect aAnimationPath = [ self convertRect: aTopIntersection fromLayer: aTopLayer ];
CGMutablePathRef const aPath = CGPathCreateMutable();
CGPathAddRect(aPath, NULL, aAnimationPath);
self.path = aPath;
CGPathRelease(aPath);
}
为什么我不直接就根据 CAShapeLayer 这个实例的frame去设置path???
而是用通过顶级Layer去设置Path
其实是因为如果当path过大的时候[超过1024*1024],边的样式不是纯实线的时候,将需要很大的性能去计算,如果机子的性能支撑不住就会直接重启。所以我们就需要把path控制到只有整个设备屏幕的区域内,或略大于设备屏幕大小。这样就可以做出区域过大,依然正确显示的假象。
也因为这样,所以当CAShapeLayer移动的时候,需要不断设置frame,以获取当前区域path应该所在的位置
动画
/**
*
*
*/
- ( void ) OnStartAnimation
{
if ( [ self animationForKey: @"linePhase" ] )
{
[ self removeAnimationForKey: @"linePhase" ];
}
@autoreleasepool
{
self.hidden = NO;
CABasicAnimation* const aDashAnimation = [ CABasicAnimation animationWithKeyPath: @"lineDashPhase" ];
[ aDashAnimation setFromValue: @( 0.0F ) ];
[ aDashAnimation setToValue: @( 15 ) ];
[ aDashAnimation setDuration: 0.75F ];
[ aDashAnimation setRepeatCount: 100000 ];
[ self addAnimation: aDashAnimation
forKey: @"linePhase" ];
}
}
/**
*
*
*/
- ( void ) OnExitAnimation
{
if ( [ self animationForKey: @"linePhase" ] )
{
[ self removeAnimationForKey: @"linePhase" ];
}
}
其实动画就是设置lineDashPhase,那lineDashPhase是什么??其实就是虚线一开始绘制的位置,那动画如何设置能够无缝衔接。我们可以想象一下,就好比我们跑圈一样,如果设置动画起始刚好就是一圈的长度,那就能够无缝结合。那怎样判断一圈的定义长度,其实就是可以看我们的画的虚线长度,实线长度。就是上面我们设置的lineDashPattern,通过这个可以知道我们一圈的长度为15
好啦!!你也动手试试吧