{"id":14968318,"url":"https://github.com/mgierlasinski/magicgradients","last_synced_at":"2025-05-14T18:04:41.166Z","repository":{"id":38375637,"uuid":"207535311","full_name":"mgierlasinski/MagicGradients","owner":"mgierlasinski","description":"Draw breathtaking backgrounds in your Xamarin.Forms application. It's a kind of magic.","archived":false,"fork":false,"pushed_at":"2025-01-02T09:01:01.000Z","size":52621,"stargazers_count":369,"open_issues_count":13,"forks_count":21,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-05-14T15:05:06.622Z","etag":null,"topics":["gradients","hacktoberfest","magic-gradients","skiasharp","xamarin","xamarin-forms"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mgierlasinski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-10T10:58:16.000Z","updated_at":"2024-12-02T11:38:13.000Z","dependencies_parsed_at":"2024-09-23T02:01:02.218Z","dependency_job_id":"592c73f4-90ae-465d-afec-5739ad775a38","html_url":"https://github.com/mgierlasinski/MagicGradients","commit_stats":{"total_commits":164,"total_committers":10,"mean_commits":16.4,"dds":0.2682926829268293,"last_synced_commit":"9ead8d6c58130ad54c43de149c946f7346142343"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgierlasinski%2FMagicGradients","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgierlasinski%2FMagicGradients/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgierlasinski%2FMagicGradients/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgierlasinski%2FMagicGradients/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mgierlasinski","download_url":"https://codeload.github.com/mgierlasinski/MagicGradients/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254198514,"owners_count":22030965,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gradients","hacktoberfest","magic-gradients","skiasharp","xamarin","xamarin-forms"],"created_at":"2024-09-24T13:39:42.316Z","updated_at":"2025-05-14T18:04:36.152Z","avatar_url":"https://github.com/mgierlasinski.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Magic Gradients\n\n![image](./Assets/Images/home_large.png)\n\n([this picture is draggable, check it out](https://my.spline.design/magicgradientsprod-1071ec2e781f07bf24ab0012e50089f9/))\n\nDraw breathtaking backgrounds in your Xamarin.Forms application today, from simple gradients to complex textures. It's a kind of magic :sparkles:\n\n| Supported platforms |\n|---|\n| :heavy_check_mark: Android |\n| :heavy_check_mark: iOS |\n| :heavy_check_mark: UWP |\n\n- Linear and radial gradients supported\n- Draw as many gradients as you want with single control, blend them together for unique effects\n- Supports [CSS gradients](https://www.scaler.com/topics/css/linear-gradient-css/), find your ideal background [somewhere on the web](https://www.gradientmagic.com/) and copy + paste into your app\n- Make your background alive with built-in XAML animations\n- Gradient'em all - paint gradient on any shape or text with clipping masks\n- Powered by [![Nuget](https://img.shields.io/badge/SkiaSharp-v1.68.1-blue)](https://www.nuget.org/packages/SkiaSharp/)\n\n| [Drawing gradient](#drawing-gradient) | [:art: Styling with CSS](#art-styling-with-css) | [:performing_arts: Masks](#performing_arts-masks) | [:clapper: Animations](#clapper-animations-preview) | [:joystick: Download](#joystick-play-with-magic-gradients) | \n| --- | --- | --- | --- | --- |\n\n## Installation \n\n`Magic Gradients` are available via NuGet:\n\n  [![Nuget](https://img.shields.io/nuget/vpre/MagicGradients)](https://www.nuget.org/packages/MagicGradients)\n\nInstall into shared project, no additional setup required.\n\nTo start using `Magic Gradients` in XAML import namespace:\n``` xml\n\u003cContentPage xmlns:magic=\"http://magic.com/schemas/gradients\" /\u003e\n```\n\n## Sample app\n\nIn `Magic Gradients` repository you can find [`Magic Playground`](https://github.com/mgierlasinski/MagicGradients/tree/master/samples/Playground) app for browsing and creating gradients visually. Android, iOS and UWP are supported.\n\n`Magic Playground` contains samples for all kinds of gradients, animations, masks and other features. It's the best place to start and see gradients in action.\n\n## :joystick: Play with Magic Gradients\n\nInstall `Magic Playground` on your device and see some cool backgrounds right now.\n\n[![Install link](https://img.shields.io/badge/Install%20on%20Android-3DDC84?style=for-the-badge\u0026logo=android\u0026logoColor=white)](https://install.appcenter.ms/users/marcin.gierlasinski/apps/magicplayground/distribution_groups/public)\n\n## Drawing gradient\n\nTo draw a gradient add `GradientView` control to your XAML page and create `LinearGradient` or `RadialGradient` as direct content.\n\n``` xml\n\u003cmagic:GradientView\u003e\n    \u003cmagic:LinearGradient\u003e\n        \u003cmagic:GradientStop Color=\"Red\" /\u003e\n        \u003cmagic:GradientStop Color=\"Yellow\" /\u003e\n    \u003c/magic:LinearGradient\u003e\n\u003c/magic:GradientView\u003e\n```\n\nIt is also possible to add collection of gradients. You can mix linear and radial gradients, use transparency in color definitions to get blend effect. \n\n``` xml\n\u003cmagic:GradientView\u003e\n    \u003cmagic:GradientCollection\u003e\n        \u003cmagic:LinearGradient Angle=\"45\"\u003e\n            \u003cmagic:GradientStop Color=\"Orange\" Offset=\"0\" /\u003e\n            \u003cmagic:GradientStop Color=\"#ff0000\" Offset=\"0.6\" /\u003e\n        \u003c/magic:LinearGradient\u003e\n        \u003cmagic:LinearGradient Angle=\"90\"\u003e\n            \u003cmagic:GradientStop Color=\"#33ff0000\" Offset=\"0.4\" /\u003e\n            \u003cmagic:GradientStop Color=\"#ff00ff00\" Offset=\"1\" /\u003e\n        \u003c/magic:LinearGradient\u003e\n    \u003c/magic:GradientCollection\u003e\n\u003c/magic:GradientView\u003e\n```\n\nYou can also build gradient in C# using `GradientBuilder` with Fluent API:\n\n``` c#\n var gradients = new GradientBuilder()\n    .AddLinearGradient(g =\u003e g\n        .Rotate(45)\n        .AddStop(Color.Red, Offset.Prop(0.2))\n        .AddStop(Color.Blue, Offset.Prop(0.4)))\n    .AddRadialGradient(g =\u003e g\n        .Circle().At(0.5, 0.5, o =\u003e o.Proportional())\n        .Radius(200, 200, o =\u003e o.Absolute())\n        .StretchTo(RadialGradientSize.FarthestSide)\n        .Repeat()\n        .AddStops(Color.Red, Color.Green, Color.Blue))\n    .AddCssGradient(\"linear-gradient(red, orange)\")\n    .Build();\n```\n\nTo apply gradient created in C#, you can use `ToSource()` extension method:\n\n``` c#\n var source = new GradientBuilder()\n    .AddLinearGradient(g =\u003e g\n        .Rotate(20)\n        .AddStops(Color.Red, Color.Green, Color.Blue))\n    .ToSource();\n\ngradientView.GradientSource = source;\n```\n\n\nVersion 1.3 introduced improved linear gradient rendering, turned on by default. If for some reason you prefer the old one, use attached property:\n\n``` xml\n\u003cmagic:GradientView magic:LinearGradient.UseLegacyShader=\"True\" /\u003e\n```\n\nFor complex backgrounds you can use GPU accelerated version `GradientView`:\n``` xml\n\u003cGradientGLView /\u003e\n```\n\n## Discover amazing backgounds\n\n![image](./Assets/Images/screens_large.png)\n\nBe sure to check out the `Gallery` in `Magic Playground` app. It contains over **1700+** samples :hear_no_evil: from [Gradient Magic](https://www.gradientmagic.com/), ready to use in any `Xamarin.Forms` app. Find your best, pick and copy over to your app.\n\n\u003cdiv\u003e\n\u003cimg src=\"./Assets/Gifs/playground_gallery_ios.gif\" height=\"500\" width=\"255\" /\u003e   \n\u003cimg src=\"./Assets/Gifs/playground_battle_test_ios.gif\" height=\"500\" width=\"255\" /\u003e  \n\u003cimg src=\"./Assets/Gifs/playground_build_gradient_ios.gif\" height=\"500\" width=\"255\" /\u003e \n\u003c/div\u003e\n\n## :art: Styling with CSS\n\n`Magic Gradients` supports following [CSS functions](https://www.w3schools.com/css/css3_gradients.asp): \n\n- Linear gradients: [`linear-gradient`](https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient), [`repeating-linear-gradient`](https://developer.mozilla.org/en-US/docs/Web/CSS/repeating-linear-gradient)\n- Radial gradients: [`radial-gradient`](https://developer.mozilla.org/en-US/docs/Web/CSS/radial-gradient), [`repeating-radial-gradient`](https://developer.mozilla.org/en-US/docs/Web/CSS/repeating-radial-gradient)\n\nCSS gradient can be embeded in XAML inline:\n\n``` xml\n\u003cmagic:GradientView\u003e\n    \u003cmagic:CssGradientSource\u003e\n        \u003cx:String\u003e\n            \u003c![CDATA[\n                linear-gradient(242deg, red, green, orange)\n            ]]\u003e\n        \u003c/x:String\u003e\n    \u003c/magic:CssGradientSource\u003e\n\u003c/magic:GradientView\u003e\n```\n\nOr even shorter using implicit conversion to `CssGradientSource`:\n\n``` xml\n\u003cmagic:GradientView GradientSource=\"linear-gradient(242deg, red, green, orange)\" /\u003e\n```\n\nStyling from CSS stylesheet is also possible:\n\n``` xml\n\u003cmagic:GradientView StyleClass=\"myGradient\" /\u003e\n```\n\n``` css\n.myGradient {\n    background: linear-gradient(90deg, rgb(235, 216, 9), rgb(202, 60, 134));\n}\n```\n\nCSS can be also set via C#:\n\n``` C#\ngradientView.GradientSource = CssGradientSource.Parse(\"linear-gradient(red, green, blue)\");\n```\n\n### Linear gradient function\n\n``` css\nlinear-gradient(direction | angle, color-stop1, color-stop2, ...);\n```\n\n| Value | Description |\n| ------| ----------- |\n| `direction` | Possible values: `to left`, `to right`, `to top`, `to bottom`, `to left top`, `to right bottom` etc. |\n| `angle` | In degrees (`135deg`) or proportional (`0.45turn`, range between 0-1) |\n\nEach color stop should contain color information and optionally position described in percents or pixels. Suppored color formats:\n\n- colors in RGB or HSL format: `rgb(red, green, blue)`, `rgba(red, green, blue, alpha)`, `hsl(hue, saturation, lightness)`, `hsla(hue, saturation, lightness, alpha)`\n- colors in hex: `#ff0000`\n- named colors: `red`, `green`, `blue`, `orange`, `pink`\n\n**Examples**\n\n``` css\nlinear-gradient(45deg, blue, red);\nlinear-gradient(to left top, #0000ff, #ff0000);\nlinear-gradient(blue, green 40%, red);\n```\n\n### Radial gradient function\n\n``` css\nradial-gradient(shape size at position, color-stop1, color-stop2, ...);\n```\n\n| Value | Description |\n| ------| ----------- |\n| `shape` | Possible values: `circle`, `ellipse` |\n| `size` | In pixels (`px`), proportional (`%`) or named sizes: `closest-side`, `closest-corner`, `farthest-side`, `farthest-corner` (default) |\n| `position` | In pixels (`px`), proportional (`%`) or named directions: `left`, `right`, `top`, `bottom`, `center` |\n\n**Examples**\n``` css\nradial-gradient(circle at top left, red, green);\nradial-gradient(circle 100px at 70% 20%, red, green);           // one radius for circle\nradial-gradient(ellipse closest-corner at 30% 80%, red, green);\nradial-gradient(ellipse 200px 300px at 50% 60%, red, green);    // two radiuses for ellipse\n```\n\n### Play with CSS\n\nYou can play around with CSS functions live in Magic Playground app, Hot Reload :fire: included.\n\n\u003cdiv\u003e\n\u003cimg src=\"./Assets/Gifs/css_add_only.gif\" height=\"480\" width=\"245\" /\u003e \n\u003cimg src=\"./Assets/Gifs/css_hot_reload.gif\" height=\"480\" width=\"245\" /\u003e \n\u003c/div\u003e\n\n## :performing_arts: Masks\n\n![image](./Assets/Images/masks.png)\n\nMasks can be used to clip `GradientView` into any shape or even text. Each mask type shares common properties:\n\n| Property | Values |     |\n| -------- | ------ | --- |\n| `ClipMode` | `Include`, `Exclude` | Draw shape or cut shape from the background. |\n| `Stretch` | `None`, `AspectFit`, `AspectFill`, `Fill` | Other than `None` will ignore shape size and match `GradientView` bounds. |\n| `IsActive` | `True`, `False` | If `False`, mask will be ignored. |\n\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"./Assets/Images/clip_mode_include.png\" height=\"150\" /\u003e\u0026nbsp;\n\u003cimg src=\"./Assets/Images/clip_mode_exclude.png\" height=\"150\" /\u003e\n\u003cbr /\u003e\n\u003cem\u003e\u003cb\u003eClipMode\u003c/b\u003e set to \u003cb\u003eInclude\u003c/b\u003e and \u003cb\u003eExclude\u003c/b\u003e\u003c/em\u003e\n\u003c/p\u003e\n\n### Rectangle\n\n\u003cimg src=\"./Assets/Images/mask_rectangle.png\" height=\"150\" /\u003e\n\nEnhances `GradientView` with custom sizing and rounded corners. To customize shape of the rectangle use properties:\n\n| Property | Values |     |\n| -------- | ------ | --- |\n| `Size` | `200,200`, `90%,90%`, `50%` | Uniform or two dimensions, pixels and percent supported. |\n| `Corners` | `20,20,30,30`, `10%,15%` | Direction from top left to bottom right clockwise, pixels and percent supported. |\n\nRounding corners of a `GradientView` scaled down to 90% of available space can be made like this:\n\n``` xml\n\u003cmagic:GradientView\u003e\n    \u003cmagic:GradientView.Mask\u003e\n        \u003cmagic:RectangleMask Size=\"90%\" Corners=\"50,0,50,0\" /\u003e\n    \u003c/magic:GradientView.Mask\u003e\n\u003c/magic:GradientView\u003e\n```\n\nOr even simplier with markup extension:\n\n``` xml\n\u003cmagic:GradientView Mask=\"{magic:Rectangle '90%', Corners='50,0,50,0'}\" /\u003e\n```\n\nEach corner can be defined separately. By defining different width and height you can have ellipse corner rather that circle:\n\n``` xml\n\u003cmagic:RectangleMask\u003e\n    \u003cmagic:RectangleMask.Corners\u003e\n        \u003cmagic:Corners TopLeft=\"100,40\" BottomRight=\"100,40\" /\u003e\n    \u003c/magic:RectangleMask.Corners\u003e\n\u003c/magic:RectangleMask\u003e\n```\n\n### Ellipse\n\n\u003cimg src=\"./Assets/Images/mask_ellipse.png\" height=\"150\" /\u003e\n\nDraws `GradientView` as oval shape. Use `Size` property for custom sizing.\n\n``` xml\n\u003cmagic:GradientView\u003e\n    \u003cmagic:GradientView.Mask\u003e\n        \u003cmagic:EllipseMask Size=\"90%\" /\u003e\n    \u003c/magic:GradientView.Mask\u003e\n\u003c/magic:GradientView\u003e\n```\n\nTo create `EllipseMask` inline, use markup extension:\n\n``` xml\n\u003cmagic:GradientView Mask=\"{magic:Ellipse '150,150'}\" /\u003e\n```\n\n### Path\n\n\u003cimg src=\"./Assets/Images/mask_path.png\" height=\"150\" /\u003e\n\nWith `PathMask` you can turn `GradientView` into any shape, just set `Data` property with any SVG path.\n\n``` xml\n\u003cmagic:GradientView\u003e\n    \u003cmagic:GradientView.Mask\u003e\n        \u003cmagic:PathMask Stretch=\"AspectFit\" \n                        Data=\"M 0 -100 L 58.8 90.9, -95.1 -30.9, 95.1 -30.9, -58.8 80.9 Z\" /\u003e\n    \u003c/magic:GradientView.Mask\u003e\n\u003c/magic:GradientView\u003e\n```\n\nTo create `PathMask` inline, use markup extension:\n\n``` xml\n\u003cmagic:GradientView Mask=\"{magic:Path '...svg path...', Stretch=AspectFit}\" /\u003e\n```\n\n### Text\n\n\u003cimg src=\"./Assets/Images/mask_text.png\" height=\"150\" /\u003e\n\nTo draw a text painted with gradient, use `TextMask` and set it's `Text` property.\nFor font customization use properties from `Label` control like: `FontFamily`, `FontSize`, `FontAttributes`.\n\n``` xml\n\u003cmagic:GradientView\u003e\n    \u003cmagic:GradientView.Mask\u003e\n        \u003cmagic:TextMask Text=\"Magic!\" FontSize=\"80\" FontAttributes=\"Bold,Italic\" /\u003e\n    \u003c/magic:GradientView.Mask\u003e\n\u003c/magic:GradientView\u003e\n```\n\nText can be positioned inside `GradientView` with `HorizontalTextAlignment` and `VerticalTextAlignment` just like with `Label`:\n\n```xml\n\u003cmagic:GradientView\u003e\n    \u003cmagic:GradientView.Mask\u003e\n        \u003cmasks:TextMask Text=\"Hello!\" \n                        HorizontalTextAlignment=\"Start\" \n                        VerticalTextAlignment=\"End\" /\u003e\n    \u003c/magic:GradientView.Mask\u003e\n\u003c/magic:GradientView\u003e\n```\n\nTo create `TextMask` inline, use markup extension:\n\n``` xml\n\u003cmagic:GradientView Mask=\"{magic:Text 'Magic!'}\" /\u003e\n```\n\n### Mask Collection\n\n\u003cimg src=\"./Assets/Images/mask_collection.png\" height=\"150\" /\u003e\n\nYou can combine multiple masks in one `GradientView` with `MaskCollection`:\n\n``` xml\n\u003cmagic:GradientView\u003e\n    \u003cmagic:GradientView.Mask\u003e\n        \u003cmagic:MaskCollection\u003e\n            \u003cmagic:EllipseMask Size=\"200,200\" /\u003e\n            \u003cmagic:PathMask ClipMode=\"Exclude\"\n                            Stretch=\"AspectFit\" \n                            Data=\"M 0 -100 L 58.8 90.9, -95.1 -30.9, 95.1 -30.9, -58.8 80.9 Z\"/\u003e\n        \u003c/magic:MaskCollection\u003e\n    \u003c/magic:GradientView.Mask\u003e\n\u003c/magic:GradientView\u003e\n```\n\n## :clapper: Animations (preview)\n\n`Magic Gradients` comes with built-in animation system. You can animate any element and property of the gradient. Each type of animation extends `Timeline` class with common properties:\n\n| Property | Values |     |\n| -------- | ------ | --- |\n| `Target` | `{x:Reference myGradient}` | Reference to animated element. |\n| `Duration` | `3000` | Length of single loop (in ms). |\n| `Delay` | `200` | Time before animations starts (in ms). |\n| `Easing` | `{x:Static Easing.SinInOut}` | Easing function. |            \n| `RepeatBehavior` | `1x`, `3x`, `Forever`  | How many times animation must be repeated. |\n| `AutoReverse` | `True`, `False` | If true, next loop will be animated backwards. |\n\nBe sure to check `Magic playground` app for sample animations:\n\n\u003cimg src=\"./Assets/Gifs/playground_animations_ios.gif\" height=\"500\" width=\"255\" /\u003e \n\n### Running animation\n\nAnimations can be run from `Behavior` or can be controlled by view model with `DataTrigger` and dedicated actions.\n\nTo run animation automatically, use `AnimateBehavior` and set `Animation` property:\n\n``` xml\n\u003cmagic:GradientView.Behaviors\u003e\n    \u003canim:AnimateBehavior\u003e\n        \u003canim:DoubleAnimation ... /\u003e\n    \u003c/anim:AnimateBehavior\u003e\n\u003c/magic:GradientView.Behaviors\u003e\n```\n\nRunning animation from view model can be done with dedicated `BeginAnimation` and `EndAnimation` actions inside `DataTrigger`. To avoid boilerplate XAML for setting `EnterActions` and `ExitActions`, you can use `AnimationTrigger` markup extension. Setup `Animation` property and set `IsRunning` that will turn animation on and off when value changes:\n\n``` xml\n\u003cmagic:GradientView.Triggers\u003e\n    \u003canim:AnimationTrigger IsRunning=\"{Binding IsRunning}\"\u003e\n         \u003canim:PointAnimation ... /\u003e\n    \u003c/anim:AnimationTrigger\u003e\n\u003c/magic:GradientView.Triggers\u003e\n```\n\n\u003e :warning: If you set **`RepeatBehavior`** to  **`Forever`**, make sure you stop every running animation by calling **`End()`** before you leave the page.\n\n### Property animations\n\nWith this type of animation you can animate single property between two values defined as `From` and `To`.\n\n| Property | Values |     |\n| -------- | -------| --- |\n| `TargetProperty` | `magic:GradientStop.Color` | Animated property with full namespace. |\n| `From` | Value matching `TargetProperty` type |  Value when animation starts. |\n| `To` | Value matching `TargetProperty` type | Value when animation ends. |\n\nAnimate color sample:\n\n``` xml\n\u003canim:ColorAnimation Target=\"{x:Reference AnimColor}\" \n                     TargetProperty=\"magic:GradientStop.Color\" \n                     From=\"Red\" To=\"Yellow\" \n                     Duration=\"3000\"\n                     RepeatBehavior=\"Forever\" \n                     AutoReverse=\"True\" /\u003e\n```\n\nBuilt-in property types:\n\n`ColorAnimation`, `DimensionsAnimation`, `DoubleAnimation`, `IntegerAnimation`, `OffsetAnimation`, `PointAnimation`, `ThicknessAnimation`\n\nFor custom types, see [Custom animation types](#custom-animation-types).\n\n### Storyboards\n\nWith `Storyboard` you can run multiple animations simultaneously in the same time period. Unlike standalone animation, `Duration` and `RepeatBehavior` is controlled by `Storyboard`. Each animation can start and end at different point of `Storyboard` timeline, this can be controlled by attached properties:\n\n| Attached property | Values |     |\n| ----------------- | ------ | --- |\n| `anim:Storyboard.BeginAt` | `from 0 to 1` | Start animation at given point of `Storyboard`. |\n| `anim:Storyboard.FinishAt` | `from 0 to 1` | End animation at given point of `Storyboard`. |\n\nBelow you can see an example of animating two colors of a gradient stop. First animation starts immediately and ends at `0.8` of `4 seconds` duration. Second animations starts at `0.3` and runs till the end of `Storyboard`.\n\n``` xml\n\u003canim:Storyboard Duration=\"4000\" RepeatBehavior=\"Forever\"\u003e\n    \u003canim:ColorAnimation Target=\"{x:Reference Color1}\" \n                         TargetProperty=\"magic:GradientStop.Color\" \n                         From=\"White\" To=\"Red\" \n                         anim:Storyboard.BeginAt=\"0\"\n                         anim:Storyboard.FinishAt=\"0.8\"\n                         AutoReverse=\"True\" /\u003e\n    \u003canim:ColorAnimation Target=\"{x:Reference Color2}\" \n                         TargetProperty=\"magic:GradientStop.Color\" \n                         From=\"LightGray\" To=\"DarkRed\" \n                         anim:Storyboard.BeginAt=\"0.3\"\n                         anim:Storyboard.FinishAt=\"1\"\n                         AutoReverse=\"True\" /\u003e\n\u003c/anim:Storyboard\u003e\n```\n\n### KeyFrame animations\n\n`AnimationUsingKeyFrames` lets you animate value of a property that changes multiple times over a period. Each `KeyFrame` object describes expected property value at given time:\n\n| Property | Values |     |\n| -------- | -------| --- |\n| `KeyTime` | Time in miliseconds. | Time when property must be at given `Value`. |\n| `Value` | Value proper for `KeyFrame` type. | `Value` of animated property at given `KeyTime`.\n| `Easing` | `{x:Static Easing.SinInOut}` | Easing function for non-linear interpolation between two key frames. |\n\nThere are several built-in animation types following naming convention `\u003cType\u003eAnimationUsingKeyFrames`, for example: `ColorAnimationUsingKeyFrames`. Supported types are: `Color`, `Dimensions`, `Double`, `Integer`, `Offset`, `Point`, `Thickness`. Each animation type has coresponding `KeyFrame` of the same type: `DoubleKeyFrame`, `ColorKeyFrame` etc.\n\nBelow you can see an example of moving radial circle between corners, at different times:\n\n``` xml\n\u003canim:PointAnimationUsingKeyFrames Target=\"{x:Reference Radial2}\" \n                                   TargetProperty=\"magic:RadialGradient.Center\" \n                                   RepeatBehavior=\"Forever\"\u003e\n    \u003canim:PointKeyFrame KeyTime=\"1000\" Value=\"0.9,0.1\" /\u003e\n    \u003canim:PointKeyFrame KeyTime=\"1500\" Value=\"0.9,0.9\" /\u003e\n    \u003canim:PointKeyFrame KeyTime=\"2500\" Value=\"0.1,0.9\" Easing=\"{x:Static Easing.SinInOut}\" /\u003e\n    \u003canim:PointKeyFrame KeyTime=\"3000\" Value=\"0.1,0.1\" /\u003e\n\u003c/anim:PointAnimationUsingKeyFrames\u003e\n```\n\n## Advanced features\n\n### Color positions\n\nSimilar to CSS, with Magic Gradient you can posion each color with proportional value or by absolute pixels.\n\n``` xml\n\u003cmagic:GradientView\u003e\n    \u003cmagic:LinearGradient\u003e\n        \u003cmagic:GradientStop Color=\"Red\" /\u003e\n        \u003cmagic:GradientStop Color=\"Yellow\" Offset=\"100px\" /\u003e\n        \u003cmagic:GradientStop Color=\"Green\" Offset=\"40%\" /\u003e\n        \u003cmagic:GradientStop Color=\"Blue\" Offset=\"0.8\" /\u003e\n    \u003c/magic:LinearGradient\u003e\n\u003c/magic:GradientView\u003e\n```\n\nOffset types:\n- `0.3`, `30%` - proportional, `Offset.Prop(0.3)` in code\n- `200px` - absolute, `Offset.Abs(200)` in code\n- leave blank - each undefined offset will be calculated like in CSS\n\n### Backgroud size and position\n\n`GradientView` let's you specify size of the background with `GradientSize` property:\n\n```xml\n\u003cGradientView GradientSource=\"...\" GradientSize=\"0.6,0.6\"\u003e\n\u003cGradientView GradientSource=\"...\" GradientSize=\"200px,200px\"\u003e\n```\n\nProportional and absolute values are supported. Size can also be set from CSS:\n\n``` css\n.myGradient {\n    background: ...;\n    background-size: 60px 60px;\n}\n```\n\nWhen size is set, gradient will be tiled to fill available space. You can change tile mode with `GradientRepeat` property. Supported values:\n- `Repeat`, `repeat`\n- `RepeatX`, `repeat-x`\n- `RepeatY`, `repeat-y`\n- `NoRepeat`, `no-repeat`\n\nRepeat mode can be set from CSS as well:\n\n``` css\n.myGradient {\n    background: ...;\n    background-size: 60px 60px;\n    background-repeat: repeat-x;\n}\n```\n\n### Custom animation types\n\n- create `ITweener` implementation\n\n``` C#\npublic class DoubleTweener : ITweener\u003cdouble\u003e\n{\n    public double Tween(double @from, double to, double progress)\n    {\n        return from + (to - from) * progress;\n    }\n}\n```\n\n- define animations\n\n``` C#\npublic class DoubleAnimation : PropertyAnimation\u003cdouble\u003e\n{\n    public override ITweener\u003cdouble\u003e Tweener { get; } = new DoubleTweener();\n}\n\npublic class DoubleAnimationUsingKeyFrames : PropertyAnimationUsingKeyFrames\u003cdouble\u003e\n{\n    public override ITweener\u003cdouble\u003e Tweener { get; } = new DoubleTweener();\n}\n\npublic class DoubleKeyFrame : KeyFrame\u003cdouble\u003e { }\n```\n\n# Articles\n- [Gradient Background for your Xamarin.Forms App - blog post](https://medium.com/@benetskyybogdan/gradient-background-for-your-xamarin-forms-app-6d7e46fba558)\n- [XF Shell Gradient Flyout with Magic Gradients - blog post](https://medium.com/@benetskyybogdan/xf-shell-gradient-flyout-with-magic-gradients-e9f0eb46bae0)\n- [How we extended Xamarin.Forms CSS to style GradientView - blog post](https://medium.com/@benetskyybogdan/xamarin-forms-custom-css-properties-d75872bea20e)\n- [Xamarin.Forms Gradient Background For All Pages in 1 minute - blog post](https://medium.com/@benetskyybogdan/xamarin-forms-gradient-background-for-all-pages-in-1-minute-9e172d986618)\n\n---\n\u003cdiv\u003eIcons made by \u003ca href=\"https://www.flaticon.com/authors/icongeek26\" title=\"Icongeek26\"\u003eIcongeek26\u003c/a\u003e from \u003ca href=\"https://www.flaticon.com/\" title=\"Flaticon\"\u003ewww.flaticon.com\u003c/a\u003e\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmgierlasinski%2Fmagicgradients","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmgierlasinski%2Fmagicgradients","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmgierlasinski%2Fmagicgradients/lists"}