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);
        }
Esempio n. 3
0
        /// <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);
        }