Irgendwelche Ideen, wie Apple die Animation "Folie zum Entsperren" implementiert hat (auch "Folie zum Ausschalten" ist ein weiteres identisches Beispiel)?
Ich habe über eine Art Animationsmaske nachgedacht - aber die Maskierung ist auf dem iPhone OS aus Leistungsgründen nicht verfügbar.
Gibt es einen privaten API-Effekt (wie SuckEffect), den sie möglicherweise verwendet haben? Ein Spotlight-Effekt? Eine Kernanimationssache?
Edit: Es ist definitiv keine Serie von Standbildern. Ich habe Beispiele gesehen, wie man einen Plist-Wert oder etwas bearbeitet und die Zeichenfolge auf iphone mit Jailbreak anpasst.
ios
objective-c
cocoa-touch
core-animation
Gabriel.Massana
quelle
quelle
Antworten:
Dies kann einfach mithilfe der Kernanimation erfolgen, bei der eine Maskenebene auf der Ebene animiert wird, auf der der Text angezeigt wird.
Versuchen Sie, diese in jeder Ebene UIViewController (können Sie mit einem neuen Xcode - Projekt starten , basierend auf der View-basierte Anwendung Projektvorlage) oder mein Xcode - Projekt greifen hier :
Beachten Sie, dass die
CALayer.mask
Eigenschaft nur in iPhone OS 3.0 und höher verfügbar ist.- (void)viewDidLoad { self.view.layer.backgroundColor = [[UIColor blackColor] CGColor]; UIImage *textImage = [UIImage imageNamed:@"SlideToUnlock.png"]; CGFloat textWidth = textImage.size.width; CGFloat textHeight = textImage.size.height; CALayer *textLayer = [CALayer layer]; textLayer.contents = (id)[textImage CGImage]; textLayer.frame = CGRectMake(10.0f, 215.0f, textWidth, textHeight); CALayer *maskLayer = [CALayer layer]; // Mask image ends with 0.15 opacity on both sides. Set the background color of the layer // to the same value so the layer can extend the mask image. maskLayer.backgroundColor = [[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.15f] CGColor]; maskLayer.contents = (id)[[UIImage imageNamed:@"Mask.png"] CGImage]; // Center the mask image on twice the width of the text layer, so it starts to the left // of the text layer and moves to its right when we translate it by width. maskLayer.contentsGravity = kCAGravityCenter; maskLayer.frame = CGRectMake(-textWidth, 0.0f, textWidth * 2, textHeight); // Animate the mask layer's horizontal position CABasicAnimation *maskAnim = [CABasicAnimation animationWithKeyPath:@"position.x"]; maskAnim.byValue = [NSNumber numberWithFloat:textWidth]; maskAnim.repeatCount = HUGE_VALF; maskAnim.duration = 1.0f; [maskLayer addAnimation:maskAnim forKey:@"slideAnim"]; textLayer.mask = maskLayer; [self.view.layer addSublayer:textLayer]; [super viewDidLoad]; }
Die von diesem Code verwendeten Bilder sind:
quelle
UIImage
aus einemUILabel
(oder einer anderenUIView
) erstellt:UIGraphicsBeginImageContext(_label); [[_label layer] renderInContext:UIGraphicsGetCurrentContext()]; UIImage *textImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
Noch eine andere Lösung, die eine Ebenenmaske verwendet, aber stattdessen den Farbverlauf von Hand zeichnet und keine Bilder benötigt. Ansicht ist die Ansicht mit der Animation, Transparenz ist ein Gleitkommawert von 0 bis 1, der den Transparenzbetrag definiert (1 = keine Transparenz, die sinnlos ist), und gradientWidth ist die gewünschte Breite des Verlaufs.
CAGradientLayer *gradientMask = [CAGradientLayer layer]; gradientMask.frame = view.bounds; CGFloat gradientSize = gradientWidth / view.frame.size.width; UIColor *gradient = [UIColor colorWithWhite:1.0f alpha:transparency]; NSArray *startLocations = @[[NSNumber numberWithFloat:0.0f], [NSNumber numberWithFloat:(gradientSize / 2)], [NSNumber numberWithFloat:gradientSize]]; NSArray *endLocations = @[[NSNumber numberWithFloat:(1.0f - gradientSize)], [NSNumber numberWithFloat:(1.0f -(gradientSize / 2))], [NSNumber numberWithFloat:1.0f]]; CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"locations"]; gradientMask.colors = @[(id)gradient.CGColor, (id)[UIColor whiteColor].CGColor, (id)gradient.CGColor]; gradientMask.locations = startLocations; gradientMask.startPoint = CGPointMake(0 - (gradientSize * 2), .5); gradientMask.endPoint = CGPointMake(1 + gradientSize, .5); view.layer.mask = gradientMask; animation.fromValue = startLocations; animation.toValue = endLocations; animation.repeatCount = HUGE_VALF; animation.duration = 3.0f; [gradientMask addAnimation:animation forKey:@"animateGradient"];
SCHNELLE VERSION:
let transparency:CGFloat = 0.5 let gradientWidth: CGFloat = 40 let gradientMask = CAGradientLayer() gradientMask.frame = swipeView.bounds let gradientSize = gradientWidth/swipeView.frame.size.width let gradient = UIColor(white: 1, alpha: transparency) let startLocations = [0, gradientSize/2, gradientSize] let endLocations = [(1 - gradientSize), (1 - gradientSize/2), 1] let animation = CABasicAnimation(keyPath: "locations") gradientMask.colors = [gradient.CGColor, UIColor.whiteColor().CGColor, gradient.CGColor] gradientMask.locations = startLocations gradientMask.startPoint = CGPointMake(0 - (gradientSize*2), 0.5) gradientMask.endPoint = CGPointMake(1 + gradientSize, 0.5) swipeView.layer.mask = gradientMask animation.fromValue = startLocations animation.toValue = endLocations animation.repeatCount = HUGE animation.duration = 3 gradientMask.addAnimation(animation, forKey: "animateGradient")
Swift 3
fileprivate func addGradientMaskToView(view:UIView, transparency:CGFloat = 0.5, gradientWidth:CGFloat = 40.0) { let gradientMask = CAGradientLayer() gradientMask.frame = view.bounds let gradientSize = gradientWidth/view.frame.size.width let gradientColor = UIColor(white: 1, alpha: transparency) let startLocations = [0, gradientSize/2, gradientSize] let endLocations = [(1 - gradientSize), (1 - gradientSize/2), 1] let animation = CABasicAnimation(keyPath: "locations") gradientMask.colors = [gradientColor.cgColor, UIColor.white.cgColor, gradientColor.cgColor] gradientMask.locations = startLocations as [NSNumber]? gradientMask.startPoint = CGPoint(x:0 - (gradientSize * 2), y: 0.5) gradientMask.endPoint = CGPoint(x:1 + gradientSize, y: 0.5) view.layer.mask = gradientMask animation.fromValue = startLocations animation.toValue = endLocations animation.repeatCount = HUGE animation.duration = 3 gradientMask.add(animation, forKey: nil) }
quelle
[view removeFromSuperview]
bevor du eine Maske auflegst und[superview addSubview:view]
danach? Scheint ohne zu funktionieren, kann es sein, dass mir etwas fehlt?Im
kCGTextClip
Zeichenmodus können Sie den Beschneidungspfad festlegen und dann mit einem Farbverlauf füllen.// Get Context CGContextRef context = UIGraphicsGetCurrentContext(); // Set Font CGContextSelectFont(context, "Helvetica", 24.0, kCGEncodingMacRoman); // Set Text Matrix CGAffineTransform xform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0); CGContextSetTextMatrix(context, xform); // Set Drawing Mode to set clipping path CGContextSetTextDrawingMode (context, kCGTextClip); // Draw Text CGContextShowTextAtPoint (context, 0, 20, "Gradient", strlen("Gradient")); // Calculate Text width CGPoint textEnd = CGContextGetTextPosition(context); // Generate Gradient locations & colors size_t num_locations = 3; CGFloat locations[3] = { 0.3, 0.5, 0.6 }; CGFloat components[12] = { 1.0, 1.0, 1.0, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5, }; // Load Colorspace CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); // Create Gradient CGGradientRef gradient = CGGradientCreateWithColorComponents (colorspace, components, locations, num_locations); // Draw Gradient (using clipping path CGContextDrawLinearGradient (context, gradient, rect.origin, textEnd, 0); // Cleanup (exercise for reader)
Richten Sie einen NSTimer ein und variieren Sie die Werte an den Standorten, oder verwenden Sie CoreAnimation, um dasselbe zu tun.
quelle
GoreAnimation
am Ende liebenkCGEncodingFontSpecific
stattdessen verwendenIch habe den oben von Pascal bereitgestellten Code als Kategorie für UILabel hinzugefügt, damit Sie jedes UILabel auf diese Weise animieren können. Hier ist der Code. Einige Parameter müssen möglicherweise für Ihre Hintergrundfarben usw. geändert werden. Es wird dasselbe Maskenbild verwendet, das Pascal in seine Antwort eingebettet hat.
//UILabel+FSHighlightAnimationAdditions.m #import "UILabel+FSHighlightAnimationAdditions.h" #import <UIKit/UIKit.h> #import <QuartzCore/QuartzCore.h> @implementation UILabel (FSHighlightAnimationAdditions) - (void)setTextWithChangeAnimation:(NSString*)text { NSLog(@"value changing"); self.text = text; CALayer *maskLayer = [CALayer layer]; // Mask image ends with 0.15 opacity on both sides. Set the background color of the layer // to the same value so the layer can extend the mask image. maskLayer.backgroundColor = [[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.15f] CGColor]; maskLayer.contents = (id)[[UIImage imageNamed:@"Mask.png"] CGImage]; // Center the mask image on twice the width of the text layer, so it starts to the left // of the text layer and moves to its right when we translate it by width. maskLayer.contentsGravity = kCAGravityCenter; maskLayer.frame = CGRectMake(self.frame.size.width * -1, 0.0f, self.frame.size.width * 2, self.frame.size.height); // Animate the mask layer's horizontal position CABasicAnimation *maskAnim = [CABasicAnimation animationWithKeyPath:@"position.x"]; maskAnim.byValue = [NSNumber numberWithFloat:self.frame.size.width]; maskAnim.repeatCount = 1e100f; maskAnim.duration = 2.0f; [maskLayer addAnimation:maskAnim forKey:@"slideAnim"]; self.layer.mask = maskLayer; } @end //UILabel+FSHighlightAnimationAdditions.h #import <Foundation/Foundation.h> @interface UILabel (FSHighlightAnimationAdditions) - (void)setTextWithChangeAnimation:(NSString*)text; @end
quelle
FLT_MAX
statt1e100f
.nicht so frisch ... aber vielleicht ist es nützlich
#define MM_TEXT_TO_DISPLAY @"default" #define MM_FONT [UIFont systemFontOfSize:MM_FONT_SIZE] #define MM_FONT_SIZE 25 #define MM_FONT_COLOR [[UIColor darkGrayColor] colorWithAlphaComponent:0.75f]; #define MM_SHADOW_ENABLED NO #define MM_SHADOW_COLOR [UIColor grayColor] #define MM_SHADOW_OFFSET CGSizeMake(-1,-1) #define MM_CONTENT_EDGE_INSETS_TOP 0 #define MM_CONTENT_EDGE_INSETS_LEFT 10 #define MM_CONTENT_EDGE_INSETS_BOTTON 0 #define MM_CONTENT_EDGE_INSETS_RIGHT 10 #define MM_CONTENT_EDGE_INSETS UIEdgeInsetsMake(MM_CONTENT_EDGE_INSETS_TOP, MM_CONTENT_EDGE_INSETS_LEFT, MM_CONTENT_EDGE_INSETS_BOTTON, MM_CONTENT_EDGE_INSETS_RIGHT) #define MM_TEXT_ALIGNMENT UITextAlignmentCenter #define MM_BACKGROUND_COLOR [UIColor clearColor] #define MM_TIMER_INTERVAL 0.05f #define MM_HORIZONTAL_SPAN 5 @interface MMAnimatedGradientLabel : UILabel { NSString *textToDisplay; int text_length; CGGradientRef gradient; int current_position_x; NSTimer *timer; CGPoint alignment; CGGlyph *_glyphs; } - (id)initWithString:(NSString *)_string; - (void)startAnimation; - (void)toggle; - (BOOL)isAnimating; @end #define RGB_COMPONENTS(r, g, b, a) (r) / 255.0f, (g) / 255.0f, (b) / 255.0f, (a) @interface MMAnimatedGradientLabel (Private) - (CGRect)calculateFrame; @end @implementation MMAnimatedGradientLabel // Missing in standard headers. extern void CGFontGetGlyphsForUnichars(CGFontRef, const UniChar[], const CGGlyph[], size_t); - (id)init { textToDisplay = MM_TEXT_TO_DISPLAY; return [self initWithFrame:[self calculateFrame]]; } - (id)initWithString:(NSString *)_string { textToDisplay = _string; return [self initWithFrame:[self calculateFrame]]; } -(id)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { // set default values // self.textAlignment = MM_TEXT_ALIGNMENT; self.backgroundColor = MM_BACKGROUND_COLOR; self.font = MM_FONT; self.text = textToDisplay; self.textColor = MM_FONT_COLOR; if (MM_SHADOW_ENABLED) { self.shadowColor = MM_SHADOW_COLOR; self.shadowOffset = MM_SHADOW_OFFSET; } text_length = -1; CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); CGFloat colors[] = { RGB_COMPONENTS(255.0, 255.0, 255.0, 0.00), // RGB_COMPONENTS(255.0, 255.0, 255.0, 0.15), RGB_COMPONENTS(255.0, 255.0, 255.0, 0.95), // RGB_COMPONENTS(255.0, 255.0, 255.0, 0.15), RGB_COMPONENTS(255.0, 255.0, 255.0, 0.00) }; gradient = CGGradientCreateWithColorComponents(rgb, colors, NULL, sizeof(colors)/(sizeof(colors[0])*4)); CGColorSpaceRelease(rgb); current_position_x = -(frame.size.width/2);// - MM_CONTENT_EDGE_INSETS.left - MM_CONTENT_EDGE_INSETS.right); } return self; } - (CGRect)calculateFrame { CGSize size = [textToDisplay sizeWithFont:MM_FONT]; NSLog(@"size: %f, %f", size.width, size.height); return CGRectMake(0, 0, size.width + MM_CONTENT_EDGE_INSETS.left + MM_CONTENT_EDGE_INSETS.right, size.height + MM_CONTENT_EDGE_INSETS.top + MM_CONTENT_EDGE_INSETS.bottom); } - (void)tick:(NSTimer*)theTimer { if (current_position_x < self.frame.size.width) current_position_x = current_position_x + MM_HORIZONTAL_SPAN; else current_position_x = -(self.frame.size.width/2); // - MM_CONTENT_EDGE_INSETS.left - MM_CONTENT_EDGE_INSETS.right); [self setNeedsDisplay]; } - (void)startAnimation { timer = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:MM_TIMER_INTERVAL target:self selector:@selector(tick:) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; } - (void)toggle { if (!timer) { timer = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:MM_TIMER_INTERVAL target:self selector:@selector(tick:) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; } else { [timer invalidate]; [timer release]; timer = nil; current_position_x = -(self.frame.size.width/2); [self setNeedsDisplay]; } } - (BOOL)isAnimating { if (timer) return YES; else return NO; } - (void)drawRect:(CGRect)rect { CGContextRef ctx = UIGraphicsGetCurrentContext(); // Get drawing font. CGFontRef font = CGFontCreateWithFontName((CFStringRef)[[self font] fontName]); CGContextSetFont(ctx, font); CGContextSetFontSize(ctx, [[self font] pointSize]); // Calculate text drawing point only first time // if (text_length == -1) { // Transform text characters to unicode glyphs. text_length = [[self text] length]; unichar chars[text_length]; [[self text] getCharacters:chars range:NSMakeRange(0, text_length)]; _glyphs = malloc(sizeof(CGGlyph) * text_length); for (int i=0; i<text_length;i ++) _glyphs[i] = chars[i] - 29; // Measure text dimensions. CGContextSetTextDrawingMode(ctx, kCGTextInvisible); CGContextSetTextPosition(ctx, 0, 0); CGContextShowGlyphs(ctx, _glyphs, text_length); CGPoint textEnd = CGContextGetTextPosition(ctx); // Calculate text drawing point. CGPoint anchor = CGPointMake(textEnd.x * (-0.5), [[self font] pointSize] * (-0.25)); CGPoint p = CGPointApplyAffineTransform(anchor, CGAffineTransformMake(1, 0, 0, -1, 0, 1)); if ([self textAlignment] == UITextAlignmentCenter) alignment.x = [self bounds].size.width * 0.5 + p.x; else if ([self textAlignment] == UITextAlignmentLeft) alignment.x = 0; else alignment.x = [self bounds].size.width - textEnd.x; alignment.y = [self bounds].size.height * 0.5 + p.y; } // Flip back mirrored text. CGContextSetTextMatrix(ctx, CGAffineTransformMakeScale(1, -1)); // Draw shadow. CGContextSaveGState(ctx); CGContextSetTextDrawingMode(ctx, kCGTextFill); CGContextSetFillColorWithColor(ctx, [[self textColor] CGColor]); CGContextSetShadowWithColor(ctx, [self shadowOffset], 0, [[self shadowColor] CGColor]); CGContextShowGlyphsAtPoint(ctx, alignment.x, alignment.y, _glyphs, text_length); CGContextRestoreGState(ctx); // Draw text clipping path. CGContextSetTextDrawingMode(ctx, kCGTextClip); CGContextShowGlyphsAtPoint(ctx, alignment.x, alignment.y, _glyphs, text_length); // Restore text mirroring. CGContextSetTextMatrix(ctx, CGAffineTransformIdentity); if ([self isAnimating]) { // Fill text clipping path with gradient. CGPoint start = CGPointMake(rect.origin.x + current_position_x, rect.origin.y); CGPoint end = CGPointMake(rect.size.width/3*2 + current_position_x, rect.origin.y); CGContextDrawLinearGradient(ctx, gradient, start, end, 0); } } - (void) dealloc { free(_glyphs); [timer invalidate]; [timer release]; CGGradientRelease(gradient); [super dealloc]; }
quelle
Vielen Dank an rpetrich für das Rezept für den Schnittverlauf. Ich bin ein Neuling in der Entwicklung von iPhone und Kakao, daher war ich sehr glücklich, es zu finden.
Ich habe eine anständig aussehende Folie implementiert, um UIViewController mit der Methode von rpetrich abzubrechen. Sie können das Xcode-Projekt meiner Implementierung hier herunterladen .
Meine Implementierung verwendet einen sich wiederholenden NSTimer. Ich konnte nicht herausfinden, wie ich mithilfe der Core- (oder Gore-) Animation die Hervorhebung durch die Grafik-Engine des iPhones kontinuierlich verschieben kann. Ich denke, dass dies unter OS X mit CALayer-Maskenebenen möglich ist, aber Maskenebenen werden unter iPhone OS nicht unterstützt.
Wenn ich mit dem Schieberegler "Slide to Unlock" von Apple auf dem Startbildschirm meines iPhones spiele, wird die Animation gelegentlich eingefroren. Daher denke ich, dass Apple möglicherweise auch einen Timer verwendet.
Wenn jemand herausfinden kann, wie eine nicht auf Timern basierende Implementierung mit CA oder OpenGL durchgeführt wird, würde ich es gerne sehen.
Danke für die Hilfe!
quelle
Ich weiß, ich bin etwas spät mit der Antwort, aber Facebook hat eine großartige Bibliothek Shimmer , die genau diesen Effekt implementiert.
quelle
Ich habe das Beste aus den oben genannten Lösungen genommen und eine saubere Methode entwickelt, die alles für Sie erledigt:
- (void)createSlideToUnlockViewWithText:(NSString *)text { UILabel *label = [[UILabel alloc] init]; label.text = text; [label sizeToFit]; label.textColor = [UIColor whiteColor]; //Create an image from the label UIGraphicsBeginImageContextWithOptions(label.bounds.size, NO, 0.0); [[label layer] renderInContext:UIGraphicsGetCurrentContext()]; UIImage *textImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); CGFloat textWidth = textImage.size.width; CGFloat textHeight = textImage.size.height; CALayer *textLayer = [CALayer layer]; textLayer.contents = (id)[textImage CGImage]; textLayer.frame = CGRectMake(self.view.frame.size.width / 2 - textWidth / 2, self.view.frame.size.height / 2 - textHeight / 2, textWidth, textHeight); UIImage *maskImage = [UIImage imageNamed:@"Mask.png"]; CALayer *maskLayer = [CALayer layer]; maskLayer.backgroundColor = [[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.15] CGColor]; maskLayer.contents = (id)maskImage.CGImage; maskLayer.contentsGravity = kCAGravityCenter; maskLayer.frame = CGRectMake(-textWidth - maskImage.size.width, 0.0, (textWidth * 2) + maskImage.size.width, textHeight); CABasicAnimation *maskAnimation = [CABasicAnimation animationWithKeyPath:@"position.x"]; maskAnimation.byValue = [NSNumber numberWithFloat:textWidth + maskImage.size.width]; maskAnimation.repeatCount = HUGE_VALF; maskAnimation.duration = 2.0; maskAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; [maskLayer addAnimation:maskAnimation forKey:@"slideAnimation"]; textLayer.mask = maskLayer; self.slideToUnlockLayer = textLayer; [self.view.layer addSublayer:self.slideToUnlockLayer]; }
quelle
Zunächst ein RIESIGES Dankeschön an Marcio für seine Lösung. Dies funktionierte fast perfekt, ersparte mir stundenlange Mühe und sorgte in meiner App für Furore. Mein Chef hat es geliebt. Ich schulde dir Bier. Oder mehrere.
Eine kleine Korrektur nur für iPhone 4. Ich meine die Hardware selbst, nicht nur iOS 4. Sie haben die Systemschriftart auf dem iPhone 4 von Helvetica (iPhone 3Gs und darunter) in Helvetic Neue geändert. Dies führte dazu, dass die Übersetzung, die Sie von Zeichen zu Glyphen ausführen, um genau 4 Punkte verschoben wurde. Zum Beispiel würde die Zeichenfolge "fg" als "bc" erscheinen. Ich habe dies behoben, indem ich die Schriftart explizit auf "Helvetica" gesetzt habe, anstatt "systemFontofSize" zu verwenden. Jetzt funktioniert es wie ein Zauber.
Nochmals vielen Dank!
quelle
Ich habe ein Mini-Projekt auf GitHub hochgeladen, das bei der Animation "Folie zum Entsperren" hilft.
https://github.com/GabrielMassana/GM_FSHighlightAnimationAdditions
Das Projekt hat LTR-, RTL-, Up-to-Down- und Down-to-Up-Animationen und basiert auf den folgenden Beiträgen:
Pascal Bourque: https://stackoverflow.com/a/2778232/1381708
cberkley: https://stackoverflow.com/a/5710097/1381708
Prost
quelle
Vielleicht ist es nur eine gerenderte Animation - Sie wissen, eine Reihe von Standbildern, die nacheinander abgespielt werden. Nicht unbedingt ein dynamischer Effekt.
Update: Egal, das von DrJokepu veröffentlichte Video hat bewiesen, dass es dynamisch generiert wird.
quelle
Ein Beispiel finden Sie hier https://github.com/jhurray/AnimatedLabelExample
quelle
Hier ist eine SwiftUI-Version:
struct Shimmer: AnimatableModifier { private let gradient: Gradient init(sideColor: Color = Color(white: 0.25), middleColor: Color = .white) { gradient = Gradient(colors: [sideColor, middleColor, sideColor]) } @State private var position: CGFloat = 0 var animatableData: CGFloat { get { position } set { position = newValue } } func body(content: Content) -> some View { content .overlay(LinearGradient( gradient: gradient, startPoint: .init(x: position - 0.2 * (1 - position), y: 0.5), endPoint: .init(x: position + 0.2 * position, y: 0.5))) .mask(content) .onAppear { withAnimation(Animation .linear(duration: 2) .delay(1) .repeatForever(autoreverses: false)) { position = 1 } } } }
Verwenden Sie es so:
Text("slide to unlock") .modifier(Shimmer())
quelle