private void InitComposition() { _compositor = Window.Current.Compositor; _generator = _compositor.CreateCompositionGenerator(); _angle = 0f; _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); _geometry = ellipse1.CombineWith(ellipse2, Matrix3x2.Identity, CanvasGeometryCombine.Union); _visual1 = _compositor.CreateSpriteVisual(); _visual1.Size = new Vector2(_width, _height); _visual1.Offset = new Vector3(((RenderGrid.ActualWidth - _width) / 2).ToSingle(), ((RenderGrid.ActualHeight - _height) / 2).ToSingle(), 0); _geometrySurface = _generator.CreateGeometrySurface(_visual1.Size.ToSize(), _geometry, Color.FromArgb(255, 192, 0, 0)); _visual1.Brush = _compositor.CreateSurfaceBrush(_geometrySurface); ElementCompositionPreview.SetElementChildVisual(RenderGrid, _visual1); _visual2 = _compositor.CreateSpriteVisual(); _visual2.Size = new Vector2(_width, _height); _visual2.Offset = new Vector3(((AnimatedGrid.ActualWidth - _width) / 2).ToSingle(), ((AnimatedGrid.ActualHeight - _height) / 2).ToSingle(), 0); var ellipse3 = CanvasGeometry.CreateEllipse(_generator.Device, _width / 2, _height / 2, 0.45f * _width, 0.225f * _height); var ellipse4 = CanvasGeometry.CreateEllipse(_generator.Device, _width / 2, _height / 2, 0.225f * _width, 0.45f * _height); _animatedGeometry = ellipse3.CombineWith(ellipse4, Matrix3x2.Identity, CanvasGeometryCombine.Xor); _animatedGeometrySurface = _generator.CreateGeometrySurface(_visual1.Size.ToSize(), _animatedGeometry, Color.FromArgb(255, 192, 0, 0)); _visual2.Brush = _compositor.CreateSurfaceBrush(_animatedGeometrySurface); ElementCompositionPreview.SetElementChildVisual(AnimatedGrid, _visual2); }
/// <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.CreateGeometrySurface(_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); }
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.CreateMaskSurface(_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.CreateGeometrySurface(_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.CreateGeometrySurface(_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 _animatedMaskSurface = _generator.CreateGeometrySurface(_animatedVisual.Size.ToSize(), excludedGeometry, Color.FromArgb(192, 192, 0, 0)); var animBrush = _compositor.CreateSurfaceBrush(_animatedMaskSurface.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.CreateGeometrySurface(_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; }
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.CreateMaskSurface(_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.CreateGeometrySurface(_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.CreateGeometrySurface(_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 _animatedMaskSurface = _generator.CreateGeometrySurface(_animatedVisual.Size.ToSize(), excludedGeometry, Color.FromArgb(192, 192, 0, 0)); var animBrush = _compositor.CreateSurfaceBrush(_animatedMaskSurface.Surface); _animatedVisual.Brush = animBrush; container.Children.InsertAtTop(_animatedVisual); ElementCompositionPreview.SetElementChildVisual(CompositionGrid3, container); }
private void SquirclePage_Loaded(object sender, RoutedEventArgs e) { _compositor = Window.Current.Compositor; _generator = _compositor.CreateCompositionGenerator(); // Create Squircle shaped visual using CompositionSurfaceBrush _roundedRectangleVisual = _compositor.CreateSpriteVisual(); _roundedRectangleVisual.Size = new Vector2(_width, _height); _roundedRectangleVisual.Offset = new Vector3(((RoundedRectangleGrid.ActualWidth - _width) / 2).ToSingle(), ((RoundedRectangleGrid.ActualHeight - _height) / 2).ToSingle(), 0); // Create the geometry surface for squircle filled with red color var roundedRectGeometry = CanvasGeometry.CreateRoundedRectangle(_generator.Device, 0, 0, _width, _height, _radius, _radius); _roundedRectangleSurface = _generator.CreateGeometrySurface(_roundedRectangleVisual.Size.ToSize(), roundedRectGeometry, Color.FromArgb(255, 192, 0, 0)); // Create SurfaceBrush from CompositionMask var rectSurfaceBrush = _compositor.CreateSurfaceBrush(_roundedRectangleSurface.Surface); _roundedRectangleVisual.Brush = rectSurfaceBrush; ElementCompositionPreview.SetElementChildVisual(RoundedRectangleGrid, _roundedRectangleVisual); // Create Squircle shaped visual using CompositionSurfaceBrush _squircleVisual = _compositor.CreateSpriteVisual(); _squircleVisual.Size = new Vector2(_width, _height); _squircleVisual.Offset = new Vector3(((SquircleGrid.ActualWidth - _width) / 2).ToSingle(), ((SquircleGrid.ActualHeight - _height) / 2).ToSingle(), 0); // Create the geometry surface for squircle filled with red color var squircleGeometry = CanvasObject.CreateSquircle(_generator.Device, 0, 0, _width, _height, _radius, _radius); _squircleSurface = _generator.CreateGeometrySurface(_squircleVisual.Size.ToSize(), squircleGeometry, Color.FromArgb(255, 192, 0, 0)); // Create SurfaceBrush from CompositionMask var surfaceBrush = _compositor.CreateSurfaceBrush(_squircleSurface); _squircleVisual.Brush = surfaceBrush; ElementCompositionPreview.SetElementChildVisual(SquircleGrid, _squircleVisual); // Create visual showing difference between the two geometries _differenceVisual = _compositor.CreateSpriteVisual(); _differenceVisual.Size = new Vector2(_width, _height); // Create the geometry surface for squircle filled with red color var differenceGeometry = roundedRectGeometry.CombineWith(squircleGeometry, Matrix3x2.Identity, CanvasGeometryCombine.Exclude); _differenceSurface = _generator.CreateGeometrySurface(_differenceVisual.Size.ToSize(), differenceGeometry, Color.FromArgb(255, 192, 192, 0)); // Create SurfaceBrush from CompositionMask _differenceVisual.Brush = _compositor.CreateSurfaceBrush(_differenceSurface); _xorVisual = _compositor.CreateSpriteVisual(); _xorVisual.Size = _differenceVisual.Size; _xorVisual.Offset = new Vector3(((DifferenceGrid.ActualWidth - _width) / 2).ToSingle(), ((DifferenceGrid.ActualHeight - _height) / 2).ToSingle(), 0); var xorGeometry = roundedRectGeometry.CombineWith(squircleGeometry, Matrix3x2.Identity, CanvasGeometryCombine.Xor); _xorSurface = _generator.CreateGeometrySurface(_xorVisual.Size.ToSize(), xorGeometry, Color.FromArgb(255, 192, 0, 0)); // Create SurfaceBrush from CompositionMask _xorVisual.Brush = _compositor.CreateSurfaceBrush(_xorSurface); _xorVisual.Children.InsertAtTop(_differenceVisual); ElementCompositionPreview.SetElementChildVisual(DifferenceGrid, _xorVisual); }
/// <summary> /// Initializes the Composition elements /// </summary> private void InitComposition() { // Compositor _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; // CompositionGenerator _generator = CompositionGeneratorFactory.GetCompositionGenerator(_compositor); // Fade Out Animation _fadeOutAnimation = _compositor.CreateScalarKeyFrameAnimation(); _fadeOutAnimation.InsertKeyFrame(1f, 0); _fadeOutAnimation.Duration = TransitionDuration; // Fade In Animation _fadeInAnimation = _compositor.CreateScalarKeyFrameAnimation(); _fadeInAnimation.InsertKeyFrame(1f, 1); _fadeInAnimation.Duration = TransitionDuration; // Color Animation _colorAnimation = _compositor.CreateColorKeyFrameAnimation(); _colorAnimation.Duration = TransitionDuration; // Offset Animation _offsetAnimation = _compositor.CreateVector3KeyFrameAnimation(); _offsetAnimation.Target = "Offset"; _offsetAnimation.Duration = TransitionDuration; _offsetAnimation.InsertKeyFrame(1f, Vector3.Zero); // Alignment animations _alignXAnimation = _compositor.CreateScalarKeyFrameAnimation(); _alignXAnimation.Duration = AlignmentTransitionDuration; _alignYAnimation = _compositor.CreateScalarKeyFrameAnimation(); _alignYAnimation.Duration = AlignmentTransitionDuration; // ZoomIn Animation Group _scaleAnimation = _compositor.CreateVector3KeyFrameAnimation(); _scaleAnimation.Target = "Scale"; _scaleAnimation.InsertKeyFrame(1f, Vector3.One); _scaleAnimation.Duration = TransitionDuration; _zoomInAnimationGroup = _compositor.CreateAnimationGroup(); _zoomInAnimationGroup.Add(_scaleAnimation); _zoomInAnimationGroup.Add(_offsetAnimation); // Visuals _rootContainer = _compositor.CreateContainerVisual(); _frameLayer = _compositor.CreateLayerVisual(); _frameBackgroundVisual = _compositor.CreateSpriteVisual(); _frameContentVisual = _compositor.CreateSpriteVisual(); _placeholderContentVisual = _compositor.CreateSpriteVisual(); _placeholderBackgroundVisual = _compositor.CreateSpriteVisual(); _nextVisualContent = _compositor.CreateSpriteVisual(); _frameLayer.Children.InsertAtTop(_frameBackgroundVisual); _frameLayer.Children.InsertAtTop(_frameContentVisual); _frameLayer.Children.InsertAtTop(_placeholderBackgroundVisual); _frameLayer.Children.InsertAtTop(_placeholderContentVisual); _frameLayer.Children.InsertAtTop(_nextVisualContent); // Placeholder content _placeholderContentMask = _generator.CreateGeometrySurface(PlaceholderSize, GetPlaceHolderGeometry(), PlaceholderColor, PlaceholderBackground); _placeholderContentBrush = _compositor.CreateSurfaceBrush(_placeholderContentMask.Surface); _placeholderContentVisual.Brush = _placeholderContentBrush; // Placeholder background _placeholderBackgroundVisual.Brush = _compositor.CreateColorBrush(PlaceholderBackground); // By default placeholder visual will not be visible HidePlaceholder(); // Shadow visual _shadowVisual = _compositor.CreateSpriteVisual(); _rootContainer.Children.InsertAtBottom(_shadowVisual); _rootContainer.Children.InsertAtTop(_frameLayer); _frameBackgroundVisual.Brush = _compositor.CreateColorBrush(FrameBackground); // Create the effect to create the opacity mask var layerEffect = new CompositeEffect { // CanvasComposite.DestinationIn - Intersection of source and mask. // Equation: O = MA * S // where O - Output pixel, MA - Mask Alpha, S - Source pixel. Mode = CanvasComposite.DestinationIn, Sources = { new CompositionEffectSourceParameter("source"), new CompositionEffectSourceParameter("mask") } }; var layerEffectFactory = _compositor.CreateEffectFactory(layerEffect); _layerEffectBrush = layerEffectFactory.CreateBrush(); // The mask for the imageFrame _frameLayerMask = _generator.CreateMaskSurface(new Size(0, 0), null); _layerEffectBrush.SetSourceParameter("mask", _compositor.CreateSurfaceBrush(_frameLayerMask.Surface)); // Apply the mask effect to the frameLayer _frameLayer.Effect = _layerEffectBrush; ElementCompositionPreview.SetElementChildVisual(this, _rootContainer); }
/// <summary> /// Disposes the resources /// </summary> public void Dispose() { // Clean up resources _compositor = null; Source = null; DataContext = null; Foreground = null; Background = null; _scheduledObject = null; _currentObject = null; // Clean up Composition Objects _imageSurface?.Dispose(); _imageSurface = null; _nextImageSurface?.Dispose(); _nextImageSurface = null; _frameLayerMask?.Dispose(); _frameLayerMask = null; _placeholderContentMask?.Dispose(); _placeholderContentMask = null; _placeholderContentBrush?.Dispose(); _placeholderContentBrush = null; _nextSurfaceBrush?.Dispose(); _nextSurfaceBrush = null; _rootContainer?.Dispose(); _rootContainer = null; _shadowVisual?.Dispose(); _shadowVisual = null; _frameLayer?.Dispose(); _frameLayer = null; _frameBackgroundVisual?.Dispose(); _frameBackgroundVisual = null; _placeholderBackgroundVisual?.Dispose(); _placeholderBackgroundVisual = null; _placeholderContentVisual?.Dispose(); _placeholderContentVisual = null; _frameContentVisual?.Dispose(); _frameContentVisual = null; _nextVisualContent?.Dispose(); _nextVisualContent = null; _shadow?.Dispose(); _shadow = null; _layerEffectBrush?.Dispose(); _layerEffectBrush = null; _imageOptions = null; _zoomInAnimationGroup?.Dispose(); _zoomInAnimationGroup = null; _fadeOutAnimation?.Dispose(); _fadeOutAnimation = null; _fadeInAnimation?.Dispose(); _fadeInAnimation = null; _colorAnimation?.Dispose(); _colorAnimation = null; _alignXAnimation?.Dispose(); _alignXAnimation = null; _alignYAnimation?.Dispose(); _alignYAnimation = null; _offsetAnimation?.Dispose(); _offsetAnimation = null; _scaleAnimation?.Dispose(); _scaleAnimation = null; // Dispose the generator at the end to allow the // dependant composition objects to unsubscribe from // generator events _generator?.Dispose(); _generator = null; }