diff --git a/Assets/Images/clip_mode_exclude.png b/Assets/Images/clip_mode_exclude.png new file mode 100644 index 00000000..6e1b63a2 Binary files /dev/null and b/Assets/Images/clip_mode_exclude.png differ diff --git a/Assets/Images/clip_mode_include.png b/Assets/Images/clip_mode_include.png new file mode 100644 index 00000000..e88f3958 Binary files /dev/null and b/Assets/Images/clip_mode_include.png differ diff --git a/Assets/Images/mask_collection.png b/Assets/Images/mask_collection.png new file mode 100644 index 00000000..449c6c3d Binary files /dev/null and b/Assets/Images/mask_collection.png differ diff --git a/Assets/Images/mask_ellipse.png b/Assets/Images/mask_ellipse.png new file mode 100644 index 00000000..b703f84f Binary files /dev/null and b/Assets/Images/mask_ellipse.png differ diff --git a/Assets/Images/mask_path.png b/Assets/Images/mask_path.png new file mode 100644 index 00000000..667e5335 Binary files /dev/null and b/Assets/Images/mask_path.png differ diff --git a/Assets/Images/mask_rectangle.png b/Assets/Images/mask_rectangle.png new file mode 100644 index 00000000..f52a6039 Binary files /dev/null and b/Assets/Images/mask_rectangle.png differ diff --git a/Assets/Images/mask_text.png b/Assets/Images/mask_text.png new file mode 100644 index 00000000..643fa389 Binary files /dev/null and b/Assets/Images/mask_text.png differ diff --git a/Assets/Images/masks.png b/Assets/Images/masks.png new file mode 100644 index 00000000..d4130854 Binary files /dev/null and b/Assets/Images/masks.png differ diff --git a/MagicGradients.Toolkit/Initializer.cs b/MagicGradients.Toolkit/Initializer.cs new file mode 100644 index 00000000..c950b96a --- /dev/null +++ b/MagicGradients.Toolkit/Initializer.cs @@ -0,0 +1,10 @@ +namespace MagicGradients.Toolkit +{ + public static class Initializer + { + public static void Init() + { + + } + } +} diff --git a/MagicGradients/MagicGradients.csproj b/MagicGradients/MagicGradients.csproj index 2b404a95..7a76e9f5 100644 --- a/MagicGradients/MagicGradients.csproj +++ b/MagicGradients/MagicGradients.csproj @@ -3,7 +3,7 @@ netstandard2.0 8.0 - 1.2.0 + 1.3.0 Marcin Gierlasiński, Bohdan Benetskyi and Contributors Magic Gradients Draw breathtaking backgrounds in your Xamarin.Forms application. It's a kind of magic. Powered by SkiaSharp. diff --git a/MagicGradients/Masks/TextMask.cs b/MagicGradients/Masks/TextMask.cs index ecab788c..48aeb19c 100644 --- a/MagicGradients/Masks/TextMask.cs +++ b/MagicGradients/Masks/TextMask.cs @@ -50,13 +50,13 @@ public override void Clip(RenderContext context) if (!IsActive) return; - using var textPaint = GetTextPaint(); + using var textPaint = GetTextPaint(context); using var textPath = textPaint.GetTextPath(Text, 0, 0); ClipPath(context, textPath); } - private SKPaint GetTextPaint() + private SKPaint GetTextPaint(RenderContext context) { var isBold = (FontAttributes & FontAttributes.Bold) == FontAttributes.Bold; var isItalic = (FontAttributes & FontAttributes.Italic) == FontAttributes.Italic; @@ -68,7 +68,7 @@ private SKPaint GetTextPaint() return new SKPaint { - TextSize = (float)FontSize, + TextSize = (float)(FontSize * context.PixelScaling), Typeface = SKTypeface.FromFamilyName(FontFamily, fontStyle), IsAntialias = true }; diff --git a/Playground/Playground/App.xaml.cs b/Playground/Playground/App.xaml.cs index 0f8b7af1..2f4d07b8 100644 --- a/Playground/Playground/App.xaml.cs +++ b/Playground/Playground/App.xaml.cs @@ -6,21 +6,15 @@ public partial class App : Application { public App() { - Device.SetFlags(new[] - { - "Shapes_Experimental", - "Expander_Experimental", - "Shell_UWP_Experimental" - }); + Device.SetFlags(new[] { "Shell_UWP_Experimental" }); InitializeComponent(); + MagicGradients.Toolkit.Initializer.Init(); Sharpnado.Shades.Initializer.Initialize(false); Sharpnado.Tabs.Initializer.Initialize(false, false); - AppSetup.RegisterTypes(); - AppSetup.RegisterViewModels(); - AppSetup.Initialize(); + AppSetup.ConfigureAndRun(); MainPage = new AppShell(); } diff --git a/Playground/Playground/AppSetup.cs b/Playground/Playground/AppSetup.cs index f36ba47b..635c1523 100644 --- a/Playground/Playground/AppSetup.cs +++ b/Playground/Playground/AppSetup.cs @@ -20,6 +20,14 @@ public static class AppSetup { public static Container IoC { get; } = new Container(); + public static void ConfigureAndRun() + { + RegisterTypes(); + RegisterViewModels(); + RegisterRoutes(); + Initialize(); + } + public static void RegisterTypes() { IoC.Register(); diff --git a/Playground/Playground/AppShell.xaml.cs b/Playground/Playground/AppShell.xaml.cs index 8cdfddb9..2eb24871 100644 --- a/Playground/Playground/AppShell.xaml.cs +++ b/Playground/Playground/AppShell.xaml.cs @@ -7,8 +7,6 @@ public partial class AppShell : Shell public AppShell() { InitializeComponent(); - - AppSetup.RegisterRoutes(); } } } diff --git a/Playground/Playground/Features/Masks/MasksPage.xaml b/Playground/Playground/Features/Masks/MasksPage.xaml index 465fb5db..5af9cce7 100644 --- a/Playground/Playground/Features/Masks/MasksPage.xaml +++ b/Playground/Playground/Features/Masks/MasksPage.xaml @@ -34,7 +34,7 @@ - + diff --git a/README.md b/README.md index 259725e3..29659a03 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,13 @@ Draw breathtaking backgrounds in your Xamarin.Forms application today, from simp - Linear and radial gradients supported - Draw as many gradients as you want with single control, blend them together for unique effects - Supports CSS gradients, find your ideal background [somewhere on the web](https://www.gradientmagic.com/) and copy + paste into your app -- Make your background alive with built-in XAML animations :hear_no_evil: +- Make your background alive with built-in XAML animations +- Gradient'em all - paint gradient on any shape or text with clipping masks - Powered by [![Nuget](https://img.shields.io/badge/SkiaSharp-v1.68.1-blue)](https://www.nuget.org/packages/SkiaSharp/) +| [Drawing gradient](#drawing-gradient) | [:art: Styling with CSS](#art-styling-with-css) | [:performing_arts: Masks](#performing_arts-masks) | [:clapper: Animations](#clapper-animations-preview) | +| --- | --- | --- | --- | + ## Installation `Magic Gradients` are available via NuGet: @@ -26,6 +30,17 @@ Draw breathtaking backgrounds in your Xamarin.Forms application today, from simp Install into shared project, no additional setup required. +To start using `Magic Gradients` in XAML import namespace: +``` xml + +``` + +## Sample app + +In `Magic Gradients` repository you can find [`Magic Playground`](https://github.com/mgierlasinski/MagicGradients/tree/master/Playground) app for browsing and creating gradients visually. Android, iOS and UWP are supported. + +`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. + ## Drawing gradient To draw a gradient add `GradientView` control to your XAML page and create `LinearGradient` or `RadialGradient` as direct content. @@ -86,13 +101,23 @@ To apply gradient created in C#, you can use `ToSource()` extension method: gradientView.GradientSource = source; ``` + +Version 1.3 introduced improved linear gradient rendering, turned on by default. If for some reason you prefer the old one, use attached property: + +``` xml + +``` + +For complex backgrounds you can use GPU accelerated version `GradientView`: +``` xml + +``` + ## Discover amazing backgounds ![image](./Assets/Images/screens_large.png) -In `Magic Gradients` repository you can find `Magic Playground`, a `Xamarin.Forms` app for browsing and creating gradients visually. Android, iOS and UWP are supported. - -Be sure to check out the `Gallery`. 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. +Be 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.
@@ -100,9 +125,14 @@ Be sure to check out the `Gallery`. It contains over **1700+** samples :hear_no_
-## Styling with CSS +## :art: Styling with CSS -Magic Gradients supports [CSS functions](https://www.w3schools.com/css/css3_gradients.asp). CSS gradient can be embeded in XAML inline: +`Magic Gradients` supports following [CSS functions](https://www.w3schools.com/css/css3_gradients.asp): + +- 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) +- 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) + +CSS gradient can be embeded in XAML inline: ``` xml @@ -134,13 +164,14 @@ CSS can be also set via C#: gradientView.GradientSource = CssGradientSource.Parse("linear-gradient(red, green, blue)"); ``` -### Linear gradient functions +### Linear gradient function + -**CSS Syntax** ``` css linear-gradient(direction | angle, color-stop1, color-stop2, ...); ``` @@ -156,15 +187,24 @@ Each color stop should contain color information and optionally position describ - colors in hex: `#ff0000` - named colors: `red`, `green`, `blue`, `orange`, `pink` -### Radial gradient functions +**Examples** + +``` css +linear-gradient(45deg, blue, red); +linear-gradient(to left top, #0000ff, #ff0000); +linear-gradient(blue, green 40%, red); +``` +### Radial gradient function + + -**CSS Syntax** ``` css -radial-gradient(shape size at position, start-color, ..., last-color); +radial-gradient(shape size at position, color-stop1, color-stop2, ...); ``` | Value | Description | @@ -190,26 +230,150 @@ You can play around with CSS functions live in Magic Playground app, Hot Reload - -## Animations (preview) +Each corner can be defined separately. By defining different width and height you can have ellipse corner rather that circle: ``` xml -xmlns:anim="clr-namespace:MagicGradients.Animation;assembly=MagicGradients" + + + + + ``` -| Timeline property | Values | | -| ----------------- | ---- | --- | +### Ellipse + + + +Draws `GradientView` as oval shape. Use `Size` property for custom sizing. + +``` xml + + + + + +``` + +To create `EllipseMask` inline, use markup extension: + +``` xml + +``` + +### Path + + + +With `PathMask` you can turn `GradientView` into any shape, just set `Data` property with any SVG path. + +``` xml + + + + + +``` + +To create `PathMask` inline, use markup extension: + +``` xml + +``` + +### Text + + + +To draw a text painted with gradient, use `TextMask` and set it's `Text` property. +For font customization use properties from `Label` control like: `FontFamily`, `FontSize`, `FontAttributes`. + +``` xml + + + + + +``` + +To create `TextMask` inline, use markup extension: + +``` xml + +``` + +### Mask Collection + + + +You can combine multiple masks in one `GradientView` with `MaskCollection`: + +``` xml + + + + + + + + +``` + +## :clapper: Animations (preview) + +`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: + +| Property | Values | | +| -------- | ------ | --- | | `Target` | `{x:Reference myGradient}` | Reference to animated element. | | `Duration` | `3000` | Length of single loop (in ms). | | `Delay` | `200` | Time before animations starts (in ms). | @@ -217,39 +381,42 @@ xmlns:anim="clr-namespace:MagicGradients.Animation;assembly=MagicGradients" | `RepeatBehavior` | `1x`, `3x`, `Forever` | How many times animation must be repeated. | | `AutoReverse` | `True`, `False` | If true, next loop will be animated backwards. | +Be sure to check `Magic playground` app for sample animations: ### Running animation -Run automatically: +Animations can be run from `Behavior` or can be controlled by view model with `DataTrigger` and dedicated actions. + +To run animation automatically, use `AnimateBehavior` and set `Animation` property: ``` xml - + - + ``` -Control animation from view model: +Running 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: ``` xml - + - + ``` -`AnimateTrigger` is a `MarkupExtension`. It's shorter way of creating `DataTrigger` with `BeginAnimation` and `EndAnimation` as `EnterActions` and `ExitActions`. +> :warning: If you set **`RepeatBehavior`** to **`Forever`**, make sure you stop every running animation by calling **`End()`** before you leave the page. ### Property animations With this type of animation you can animate single property between two values defined as `From` and `To`. -| Properties | Value | | -| ---------- | ------| --- | +| Property | Values | | +| -------- | -------| --- | | `TargetProperty` | `magic:GradientStop.Color` | Animated property with full namespace. | | `From` | Value matching `TargetProperty` type | Value when animation starts. | | `To` | Value matching `TargetProperty` type | Value when animation ends. | @@ -269,16 +436,18 @@ Built-in property types: `ColorAnimation`, `DimensionsAnimation`, `DoubleAnimation`, `IntegerAnimation`, `OffsetAnimation`, `PointAnimation`, `ThicknessAnimation` -For custom types, see Custom animation types. +For custom types, see [Custom animation types](#custom-animation-types). ### Storyboards -| Attached properties | Values | | -| ------------------- | ------ | -- | +With `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: + +| Attached property | Values | | +| ----------------- | ------ | --- | | `anim:Storyboard.BeginAt` | `from 0 to 1` | Start animation at given point of `Storyboard`. | | `anim:Storyboard.FinishAt` | `from 0 to 1` | End animation at given point of `Storyboard`. | -Animate two colors at different times: +Below 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`. ``` xml @@ -299,14 +468,17 @@ Animate two colors at different times: ### KeyFrame animations -`AnimationUsingKeyFrames` +`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: + +| Property | Values | | +| -------- | -------| --- | +| `KeyTime` | Time in miliseconds. | Time when property must be at given `Value`. | +| `Value` | Value proper for `KeyFrame` type. | `Value` of animated property at given `KeyTime`. +| `Easing` | `{x:Static Easing.SinInOut}` | Easing function for non-linear interpolation between two key frames. | -`KeyFrame` properties: -- `KeyTime` - time when value is applied to animated target -- `Value` - of type `` -- `Easing` - easing function +There are several built-in animation types following naming convention `AnimationUsingKeyFrames`, 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. -Move radial circle between corners, at different times: +Below you can see an example of moving radial circle between corners, at different times: ``` xml