private async void MainPage_Loaded(object sender, RoutedEventArgs e) { _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; _generator = CompositionMaskFactory.GetCompositionMaskGenerator(_compositor); _backdropBrush = _compositor.CreateBackdropBrush(); //Create the visual _visual = _compositor.CreateSpriteVisual(); _visual.Size = new Vector2(400, 400); _visual.Offset = new Vector3(200, 0, 0); // Create the combined geometry var ellipse1 = CanvasGeometry.CreateEllipse(_generator.Device, 200, 200, 150, 75); var ellipse2 = CanvasGeometry.CreateEllipse(_generator.Device, 200, 200, 75, 150); _combinedGeometry = ellipse1.CombineWith(ellipse2, Matrix3x2.Identity, CanvasGeometryCombine.Union); // Create the CompositionMask _compositionMask = await _generator.CreateMaskAsync(_visual.Size.ToSize(), _combinedGeometry); // Create SurfaceBrush from CompositionMask var mask = _compositor.CreateSurfaceBrush(_compositionMask.Surface); var source1 = _compositor.CreateColorBrush(Colors.Blue); // Create mask brush var maskBrush = _compositor.CreateMaskBrush(); maskBrush.Mask = mask; maskBrush.Source = source1; _visual.Brush = maskBrush; ElementCompositionPreview.SetElementChildVisual(CanvasCtrl, _visual); var container = _compositor.CreateContainerVisual(); container.Size = new Vector2(1000, 1000); // Background visual var bgVisual = _compositor.CreateSpriteVisual(); bgVisual.Size = new Vector2(200, 200); bgVisual.Offset = new Vector3(300, 100, 0); bgVisual.Brush = source1; container.Children.InsertAtTop(bgVisual); // Animated Visual _animatedVisual = _compositor.CreateSpriteVisual(); _animatedVisual.Size = new Vector2(400, 400); _animatedVisual.Offset = new Vector3(200, 0, 0); // Create the Excluded geometry _outerGeometry = CanvasGeometry.CreateRectangle(_generator.Device, 0, 0, 400, 400); var excludedGeometry = _outerGeometry.CombineWith(_combinedGeometry, Matrix3x2.Identity, CanvasGeometryCombine.Exclude); // Create the CompositionMask _animatedCompositionMask = await _generator.CreateMaskAsync(_animatedVisual.Size.ToSize(), excludedGeometry); //// Create SurfaceBrush from CompositionMask //var animatedMask = _compositor.CreateSurfaceBrush(_animatedCompositionMask.Surface); //var source2 = _compositor.CreateColorBrush(Colors.Red); //// Create mask brush //var animatedMaskBrush = _compositor.CreateMaskBrush(); //animatedMaskBrush.Mask = animatedMask; //animatedMaskBrush.Source = source2; _animatedVisual.Brush = _compositor.CreateMaskedBackdropBrush(_animatedCompositionMask, Color.FromArgb(240, 232, 232, 232), 20f, _backdropBrush); container.Children.InsertAtTop(_animatedVisual); ElementCompositionPreview.SetElementChildVisual(AnimatedCanvasCtrl, container); }
/// <summary> /// Creates a custom shaped Effect Brush using BackdropBrush and a Mask /// </summary> /// <param name="compositor">Compositor</param> /// <param name="mask">ICompositionMask</param> /// <param name="blendColor">Color to blend in the BackdropBrush</param> /// <param name="blurAmount">Blur Amount of the Backdrop Brush</param> /// <param name="backdropBrush">Backdrop Brush (optional). If not provided, then compositor creates it.</param> /// <returns>CompositionEffectBrush</returns> public static CompositionEffectBrush CreateMaskedBackdropBrush(this Compositor compositor, ICompositionMask mask, Color blendColor, float blurAmount, CompositionBackdropBrush backdropBrush = null) { // Blur Effect var blurEffect = new GaussianBlurEffect() { Name = "Blur", BlurAmount = blurAmount, BorderMode = EffectBorderMode.Hard, Optimization = EffectOptimization.Balanced, Source = new CompositionEffectSourceParameter("backdrop"), }; // Blend Effect var blendEffect = new BlendEffect { Foreground = new ColorSourceEffect { Name = "Color", Color = blendColor }, Background = blurEffect, Mode = BlendEffectMode.Multiply }; // Composite Effect var effect = new CompositeEffect { Mode = CanvasComposite.DestinationIn, Sources = { blendEffect, new CompositionEffectSourceParameter("mask") } }; // Create Effect Factory var factory = compositor.CreateEffectFactory(effect, new[] { "Blur.BlurAmount", "Color.Color" }); // Create Effect Brush var brush = factory.CreateBrush(); // Set the BackDropBrush // If no backdrop brush is provided, create one brush.SetSourceParameter("backdrop", backdropBrush ?? compositor.CreateBackdropBrush()); // Set the Mask // Create SurfaceBrush from CompositionMask var maskBrush = compositor.CreateSurfaceBrush(mask.Surface); brush.SetSourceParameter("mask", maskBrush); return(brush); }
private async void OnLoaded(object sender, RoutedEventArgs e) { _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; _generator = CompositionGeneratorFactory.GetCompositionGenerator(_compositor); _backdropBrush = _compositor.CreateBackdropBrush(); _width = 300f; _height = 300f; // Create the combined geometry var ellipse1 = CanvasGeometry.CreateEllipse(_generator.Device, _width / 2, _height / 2, 0.45f * _width, 0.225f * _height); var ellipse2 = CanvasGeometry.CreateEllipse(_generator.Device, _width / 2, _height / 2, 0.225f * _width, 0.45f * _height); _combinedGeometry = ellipse1.CombineWith(ellipse2, Matrix3x2.Identity, CanvasGeometryCombine.Union); // Create the container to host the visuals var container1 = _compositor.CreateContainerVisual(); container1.Size = new Vector2(CompositionGrid1.ActualWidth.Single(), CompositionGrid1.ActualHeight.Single()); // Background Visual _bgVisual1 = _compositor.CreateSpriteVisual(); _bgVisual1.Size = new Vector2(_width * 0.45f, _height * 0.45f); _bgVisual1.Offset = new Vector3(((CompositionGrid1.ActualWidth - _width) / 2).Single(), ((CompositionGrid1.ActualHeight - _height) / 2).Single(), 0); _bgVisual1.Brush = _compositor.CreateColorBrush(Colors.DarkOrange); container1.Children.InsertAtBottom(_bgVisual1); // Create custom shaped visual using CompositionMaskBrush _visual1 = _compositor.CreateSpriteVisual(); _visual1.Size = new Vector2(_width, _height); _visual1.Offset = new Vector3(((CompositionGrid1.ActualWidth - _width) / 2).Single(), ((CompositionGrid1.ActualHeight - _height) / 2).Single(), 0); // Create the CompositionMask var ellipseGeometry = CanvasGeometry.CreateEllipse(_generator.Device, _width / 2, _height / 2, 0.4f * _width, 0.4f * _height); var compositionMask = _generator.CreateMask(_visual1.Size.ToSize(), ellipseGeometry); // Create Masked BackdropBrush from CompositionMask _visual1.Brush = _compositor.CreateMaskedBackdropBrush(compositionMask, Colors.AntiqueWhite, 30f, _backdropBrush); container1.Children.InsertAtTop(_visual1); ElementCompositionPreview.SetElementChildVisual(CompositionGrid1, container1); // Initialize the visuals for the Animated Canvas // Create the container to host the visuals var container2 = _compositor.CreateContainerVisual(); container2.Size = new Vector2(CompositionGrid2.ActualWidth.Single(), CompositionGrid2.ActualHeight.Single()); // Background Visual _bgVisual2 = _compositor.CreateSpriteVisual(); _bgVisual2.Size = new Vector2(_width * Factor, _height * Factor); _bgVisual2.Offset = new Vector3(((CompositionGrid2.ActualWidth - (_width * Factor)) / 2).Single(), ((CompositionGrid2.ActualHeight - (_height * Factor)) / 2).Single(), 0); //var radians = ((45f * Math.PI) / 180).Single(); //var bgGeometry = _combinedGeometry.Transform(Matrix3x2.CreateRotation(radians, new Vector2(_width / 2, _height / 2))); //var bgMask = await _generator.CreateMaskAsync(_bgVisual2.Size.ToSize(), bgGeometry, Colors.DarkRed); //_bgVisual2.Brush = _compositor.CreateSurfaceBrush(bgMask.Surface); _bgVisual2.Brush = _compositor.CreateColorBrush(Colors.LawnGreen); container2.Children.InsertAtBottom(_bgVisual2); // Animated Visual _animatedVisual = _compositor.CreateSpriteVisual(); _animatedVisual.Size = new Vector2(_width, _height); _animatedVisual.Offset = new Vector3(((CompositionGrid2.ActualWidth - _width) / 2).Single(), ((CompositionGrid2.ActualHeight - _height) / 2).Single(), 0); // Create the Excluded geometry _outerGeometry = CanvasGeometry.CreateRectangle(_generator.Device, 0, 0, _width, _height); var excludedGeometry = _outerGeometry.CombineWith(_combinedGeometry, Matrix3x2.Identity, CanvasGeometryCombine.Exclude); // Create the CompositionMask _animatedCompositionMask = _generator.CreateMask(_animatedVisual.Size.ToSize(), excludedGeometry); var animBrush = _compositor.CreateMaskedBackdropBrush(_animatedCompositionMask, Colors.AntiqueWhite, 10f, _backdropBrush); _animatedVisual.Brush = animBrush; container2.Children.InsertAtTop(_animatedVisual); ElementCompositionPreview.SetElementChildVisual(CompositionGrid2, container2); }
private void OnLoaded(object sender, RoutedEventArgs e) { _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; _generator = CompositionGeneratorFactory.GetCompositionGenerator(_compositor); _width = 300f; _height = 300f; // Create the combined geometry var ellipse1 = CanvasGeometry.CreateEllipse(_generator.Device, _width / 2, _height / 2, 0.45f * _width, 0.225f * _height); var ellipse2 = CanvasGeometry.CreateEllipse(_generator.Device, _width / 2, _height / 2, 0.225f * _width, 0.45f * _height); _combinedGeometry = ellipse1.CombineWith(ellipse2, Matrix3x2.Identity, CanvasGeometryCombine.Union); // Create custom shaped visual using CompositionMaskBrush _visual1 = _compositor.CreateSpriteVisual(); _visual1.Size = new Vector2(_width, _height); _visual1.Offset = new Vector3(((CompositionGrid1.ActualWidth - _width) / 2).Single(), ((CompositionGrid1.ActualHeight - _height) / 2).Single(), 0); var visualChild = _compositor.CreateSpriteVisual(); visualChild.Size = new Vector2(_width * 0.75f, _height * 0.75f); visualChild.Offset = new Vector3(_width * 0.125f, _height * 0.125f, 0); _visual1.Children.InsertAtTop(visualChild); // Create the CompositionMask var compositionMask = _generator.CreateMask(_visual1.Size.ToSize(), _combinedGeometry); // Create SurfaceBrush from CompositionMask var mask = _compositor.CreateSurfaceBrush(compositionMask.Surface); var source = _compositor.CreateColorBrush(Color.FromArgb(255, 0, 173, 239)); // Create mask brush var maskBrush = _compositor.CreateMaskBrush(); maskBrush.Mask = mask; maskBrush.Source = source; _visual1.Brush = maskBrush; ElementCompositionPreview.SetElementChildVisual(CompositionGrid1, _visual1); // Create custom shaped visual using CompositionMaskBrush _visual2 = _compositor.CreateSpriteVisual(); _visual2.Size = new Vector2(_width, _height); _visual2.Offset = new Vector3(((CompositionGrid2.ActualWidth - _width) / 2).Single(), ((CompositionGrid2.ActualHeight - _height) / 2).Single(), 0); // Create the CompositionMask filled with color var compositionMask2 = _generator.CreateMask(_visual2.Size.ToSize(), _combinedGeometry, Color.FromArgb(192, 192, 0, 0)); // Create SurfaceBrush from CompositionMask var surfaceBrush = _compositor.CreateSurfaceBrush(compositionMask2.Surface); _visual2.Brush = surfaceBrush; ElementCompositionPreview.SetElementChildVisual(CompositionGrid2, _visual2); // Initialize the visuals for the Animated Canvas // Create the container to host the visuals var container = _compositor.CreateContainerVisual(); container.Size = new Vector2(CompositionGrid3.ActualWidth.Single(), CompositionGrid3.ActualHeight.Single()); // Background Visual _bgVisual = _compositor.CreateSpriteVisual(); _bgVisual.Size = new Vector2(_width, _height); _bgVisual.Offset = new Vector3(((CompositionGrid3.ActualWidth - _width) / 2).Single(), ((CompositionGrid3.ActualHeight - _height) / 2).Single(), 0); var radians = ((45f * Math.PI) / 180).Single(); var bgGeometry = _combinedGeometry.Transform(Matrix3x2.CreateRotation(radians, new Vector2(_width / 2, _height / 2))); var bgMask = _generator.CreateMask(_bgVisual.Size.ToSize(), bgGeometry, Color.FromArgb(255, 0, 173, 239)); var bgBrush = _compositor.CreateSurfaceBrush(bgMask.Surface); _bgVisual.Brush = bgBrush; container.Children.InsertAtBottom(_bgVisual); // Animated Visual _animatedVisual = _compositor.CreateSpriteVisual(); _animatedVisual.Size = new Vector2(_width, _height); _animatedVisual.Offset = new Vector3(((CompositionGrid3.ActualWidth - _width) / 2).Single(), ((CompositionGrid3.ActualHeight - _height) / 2).Single(), 0); // Create the Excluded geometry _outerGeometry = CanvasGeometry.CreateRectangle(_generator.Device, 0, 0, _width, _height); var excludedGeometry = _outerGeometry.CombineWith(_combinedGeometry, Matrix3x2.Identity, CanvasGeometryCombine.Exclude); // Create the CompositionMask _animatedCompositionMask = _generator.CreateMask(_animatedVisual.Size.ToSize(), excludedGeometry, Color.FromArgb(192, 192, 0, 0)); var animBrush = _compositor.CreateSurfaceBrush(_animatedCompositionMask.Surface); _animatedVisual.Brush = animBrush; container.Children.InsertAtTop(_animatedVisual); ElementCompositionPreview.SetElementChildVisual(CompositionGrid3, container); }
/// <summary> /// Handles the Arrange layout phase /// </summary> /// <param name="finalSize">Final Size of the control</param> /// <returns>Size</returns> protected override Size ArrangeOverride(Size finalSize) { if ((_compositor == null) || (_generator == null)) { return(base.ArrangeOverride(finalSize)); } if (Double.IsInfinity(finalSize.Width) || Double.IsInfinity(finalSize.Height) || Double.IsNaN(finalSize.Width) || Double.IsNaN(finalSize.Height)) { return(base.ArrangeOverride(finalSize)); } // Stop the animations and dispose the previous nodes // and their animations if (_isAnimationStarted) { for (var i = 0; i < _nodes.Count; i++) { _nodes[i].StopAnimation(AnimatedProperty); _animations[i].Dispose(); _animations[i] = null; _nodes[i].Dispose(); _nodes[i] = null; } _container.StopAnimation(AnimatedProperty); _containerAnimation.Dispose(); _containerAnimation = null; _container.Dispose(); _container = null; _animations.Clear(); _nodes.Clear(); _isAnimationStarted = false; } // Validate MaxNodes and ActiveNodes if ((MaxNodes <= 0) || (ActiveNodes <= 0)) { return(finalSize); } // Coerce ActiveNodes to MaxNodes if ActiveNodes > MaxNodes if (ActiveNodes > MaxNodes) { ActiveNodes = MaxNodes; } // Take the smallest of the width or height var sideLength = (float)Math.Min(finalSize.Width, finalSize.Height); // Size of the progress ring displayed _ringSize = new Vector2(sideLength, sideLength); var sideHalf = sideLength / 2f; // Radius of each node _nodeRadius = (float)NodeSizeFactor * sideHalf; // Size of each node _nodeSize = new Vector2(_nodeRadius * 2f, _nodeRadius * 2f); // Radius of the node _ringRadius = sideHalf - _nodeRadius; // Each animation will consist of '_maxFrameBlocks' number of // FrameBlocks. Each FrameBlock will consist of keyframes which allow // the element being animated to move to the next slot and wait // at that slot until all other elements have moved to their next slot. // Each FrameBlock (except the last one) will have '_maxFramesPerBlock' // number of keyframes. The last keyframe in the last FrameBlock // will always be (1f, "this.StartingValue + 360") // Total number of FrameBlocks in each animation _maxFrameBlocks = ActiveNodes; // Total keyframes in each FrameBlock _maxFramesPerBlock = ActiveNodes + 1; // Total keyframes in each animation _maxKeyFrames = _maxFrameBlocks * _maxFramesPerBlock; // Normalized Progress Key unit value for each keyframe _keyFrameSlice = 1f / _maxKeyFrames; // ======================================================================== // NOTE: // gamma * maxNodes = 360 // gamma = alpha + beta // beta = 2 * Asin(nodeRadius / ringRadius) * (180 / Math.PI) // invisibleNodes = MaxNodes - ActiveNodes // phi = (invisibleNodes * gamma) // theta = phi - beta // ======================================================================== // gamma is the angle between adjacent nodes when maxNodes number of nodes are arranged in a circle _gamma = 360f / MaxNodes; // beta is the angle a node must travel after hitting the adjacent node _beta = 2f * (float)(Math.Asin(_nodeRadius / _ringRadius) * (180f / Math.PI)); // alpha is the smallest angle a node must travel before hitting the adjacent node _alpha = _gamma - _beta; // phi is the angle occupied by (MaxNodes - ActiveNodes) number of nodes _phi = (MaxNodes - ActiveNodes + 1) * _gamma; // theta is the largest angle a node must travel before hitting the adjacent node _theta = _phi - _beta; // Create the Animations _animations = CreateAnimations(); // Create the Container _container = _compositor.CreateContainerVisual(); _container.Size = _ringSize; _container.Offset = new Vector3(((float)finalSize.Width - sideLength) / 2f, ((float)finalSize.Height - sideLength) / 2f, 0f); _container.CenterPoint = new Vector3(_ringSize.X / 2f, _ringSize.Y / 2f, 0f); // Create the Nodes var offset = new Vector3(_nodeRadius, _ringSize.Y / 2f, 0); var centerPoint = new Vector3(_ringSize.X / 2f - _nodeRadius, 0, 0); _nodes = new List <SpriteVisual>(); var geometry = CanvasGeometry.CreateCircle(_generator.Device, new Vector2(_nodeRadius, _nodeRadius), _nodeRadius); // Create/Update the nodeMask var color = NodeColor; if (_nodeMask == null) { //Task.Run(async () => // { _nodeMask = _generator.CreateMask(_nodeSize.ToSize(), geometry, color); // }) //.Wait(); } else { //Task.Run(async () => // { _nodeMask.Redraw(_nodeSize.ToSize(), geometry, color); // }) //.Wait(); } // Create the SurfaceBrush for the nodes var brush = _compositor.CreateSurfaceBrush(_nodeMask.Surface); var baseAngle = 0f; // Create the visuals for the nodes for (var i = 0; i < _maxFramesPerBlock; i++) { var node = _compositor.CreateSpriteVisual(); node.Size = _nodeSize; node.AnchorPoint = new Vector2(0.5f); node.Offset = offset; node.CenterPoint = centerPoint; node.Brush = brush; node.RotationAngleInDegrees = baseAngle; if (i == 0) { baseAngle += _phi; } else if (i == _maxFramesPerBlock - 2) { baseAngle = -_beta; } else { baseAngle += _gamma; } _nodes.Add(node); // Add the visual to the container _container.Children.InsertAtTop(node); } // Add the container to the Visual Tree ElementCompositionPreview.SetElementChildVisual(this, _container); // Start Node animations for (var i = 0; i < _maxFramesPerBlock; i++) { _nodes[i].StartAnimation(AnimatedProperty, _animations[i]); } // Start container animation _containerAnimation = _compositor.CreateScalarKeyFrameAnimation(); _containerAnimation.InsertExpressionKeyFrame(1f, "this.StartingValue + 360f", _compositor.CreateLinearEasingFunction()); _containerAnimation.Duration = RingDuration; _containerAnimation.IterationBehavior = AnimationIterationBehavior.Forever; _container.StartAnimation(AnimatedProperty, _containerAnimation); _isAnimationStarted = true; return(finalSize); }