/// <summary> /// Creates a reflection of the given Visual /// </summary> /// <param name="visual">Visual whose reflection has to be created</param> /// <param name="reflectionDistance">Distance of the reflection from the visual</param> /// <param name="reflectionLength">Normalized Length of the reflected visual that will be visible.</param> /// <param name="location"> <see cref="ReflectionLocation"/> - Location of the reflection with respect /// to the Visual - Bottom, Top, Left or Right</param> public void CreateReflection(ContainerVisual visual, float reflectionDistance = 0f, float reflectionLength = 0.7f, ReflectionLocation location = ReflectionLocation.Bottom) { // Create the visual layer that will contained the visual's reflection var reflectionLayer = _compositor.CreateLayerVisual(); reflectionLayer.Size = visual.Size; reflectionLayer.CenterPoint = new Vector3(visual.Size * 0.5f, 0); // Create the effect to create the opacity mask var effect = 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 effectFactory = _compositor.CreateEffectFactory(effect); var effectBrush = effectFactory.CreateBrush(); // Create the gradient brush for the effect CanvasLinearGradientBrush gradientBrush = new CanvasLinearGradientBrush(_canvasDevice, Colors.White, Colors.Transparent); // Based on the reflection location, // Set the Offset, RotationAxis and RotationAngleInDegrees of the reflectionLayer and // set the StartPoint and EndPoint of the gradientBrush switch (location) { case ReflectionLocation.Bottom: reflectionLayer.RotationAxis = new Vector3(1, 0, 0); reflectionLayer.RotationAngleInDegrees = 180; reflectionLayer.Offset = new Vector3(0, visual.Size.Y + reflectionDistance, 0); gradientBrush.StartPoint = new Vector2(visual.Size.X * 0.5f, 0); gradientBrush.EndPoint = new Vector2(visual.Size.X * 0.5f, visual.Size.Y * reflectionLength); break; case ReflectionLocation.Top: reflectionLayer.RotationAxis = new Vector3(1, 0, 0); reflectionLayer.RotationAngleInDegrees = -180; reflectionLayer.Offset = new Vector3(0, -visual.Size.Y - reflectionDistance, 0); gradientBrush.StartPoint = new Vector2(visual.Size.X * 0.5f, visual.Size.Y); gradientBrush.EndPoint = new Vector2(visual.Size.X * 0.5f, visual.Size.Y * (1f - reflectionLength)); break; case ReflectionLocation.Left: reflectionLayer.RotationAxis = new Vector3(0, 1, 0); reflectionLayer.RotationAngleInDegrees = -180; reflectionLayer.Offset = new Vector3(-visual.Size.X - reflectionDistance, 0, 0); gradientBrush.StartPoint = new Vector2(visual.Size.X, visual.Size.Y * 0.5f); gradientBrush.EndPoint = new Vector2(visual.Size.X * (1f - reflectionLength), visual.Size.Y * 0.5f); break; case ReflectionLocation.Right: reflectionLayer.RotationAxis = new Vector3(0, 1, 0); reflectionLayer.RotationAngleInDegrees = 180; reflectionLayer.Offset = new Vector3(visual.Size.X + reflectionDistance, 0, 0); gradientBrush.StartPoint = new Vector2(0, visual.Size.Y * 0.5f); gradientBrush.EndPoint = new Vector2(visual.Size.X * reflectionLength, visual.Size.Y * 0.5f); break; } // Create a mask filled with gradientBrush var mask = CreateMask(visual.Size.ToSize(), null, gradientBrush); // Set the 'mask' parameter of the effectBrush effectBrush.SetSourceParameter("mask", _compositor.CreateSurfaceBrush(mask.Surface)); // Set the effect for the reflection layer reflectionLayer.Effect = effectBrush; // Now we need to duplicate the visual tree of the visual ArrangeVisualReflection(visual, reflectionLayer, true); visual.Children.InsertAtTop(reflectionLayer); }
/// <summary> /// Creates a reflection of the given Visual /// </summary> /// <param name="visual">Visual whose reflection has to be created</param> /// <param name="reflectionDistance">Distance of the reflection from the visual</param> /// <param name="reflectionLength">Normalized Length of the reflected visual that will be visible.</param> /// <param name="location"> <see cref="ReflectionLocation"/> - Location of the reflection with respect /// to the Visual - Bottom, Top, Left or Right</param> public void CreateReflection(ContainerVisual visual, float reflectionDistance = 0f, float reflectionLength = 0.7f, ReflectionLocation location = ReflectionLocation.Bottom) { // Create the visual layer that will contained the visual's reflection var reflectionLayer = _compositor.CreateLayerVisual(); reflectionLayer.Size = visual.Size; reflectionLayer.CenterPoint = new Vector3(visual.Size * 0.5f, 0); // Create the effect to create the opacity mask var effect = 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 effectFactory = _compositor.CreateEffectFactory(effect); var effectBrush = effectFactory.CreateBrush(); // Create the gradient brush for the effect var gradientBrush = new CanvasLinearGradientBrush(_canvasDevice, Colors.White, Colors.Transparent); // Based on the reflection location, // Set the Offset, RotationAxis and RotationAngleInDegrees of the reflectionLayer and // set the StartPoint and EndPoint of the gradientBrush switch (location) { case ReflectionLocation.Bottom: reflectionLayer.RotationAxis = new Vector3(1, 0, 0); reflectionLayer.RotationAngleInDegrees = 180; reflectionLayer.Offset = new Vector3(0, visual.Size.Y + reflectionDistance, 0); gradientBrush.StartPoint = new Vector2(visual.Size.X * 0.5f, 0); gradientBrush.EndPoint = new Vector2(visual.Size.X * 0.5f, visual.Size.Y * reflectionLength); break; case ReflectionLocation.Top: reflectionLayer.RotationAxis = new Vector3(1, 0, 0); reflectionLayer.RotationAngleInDegrees = -180; reflectionLayer.Offset = new Vector3(0, -visual.Size.Y - reflectionDistance, 0); gradientBrush.StartPoint = new Vector2(visual.Size.X * 0.5f, visual.Size.Y); gradientBrush.EndPoint = new Vector2(visual.Size.X * 0.5f, visual.Size.Y * (1f - reflectionLength)); break; case ReflectionLocation.Left: reflectionLayer.RotationAxis = new Vector3(0, 1, 0); reflectionLayer.RotationAngleInDegrees = -180; reflectionLayer.Offset = new Vector3(-visual.Size.X - reflectionDistance, 0, 0); gradientBrush.StartPoint = new Vector2(visual.Size.X, visual.Size.Y * 0.5f); gradientBrush.EndPoint = new Vector2(visual.Size.X * (1f - reflectionLength), visual.Size.Y * 0.5f); break; case ReflectionLocation.Right: reflectionLayer.RotationAxis = new Vector3(0, 1, 0); reflectionLayer.RotationAngleInDegrees = 180; reflectionLayer.Offset = new Vector3(visual.Size.X + reflectionDistance, 0, 0); gradientBrush.StartPoint = new Vector2(0, visual.Size.Y * 0.5f); gradientBrush.EndPoint = new Vector2(visual.Size.X * reflectionLength, visual.Size.Y * 0.5f); break; } // Create a mask filled with gradientBrush var mask = CreateGeometrySurface(visual.Size.ToSize(), null, Colors.Transparent, gradientBrush); // Set the 'mask' parameter of the effectBrush effectBrush.SetSourceParameter("mask", _compositor.CreateSurfaceBrush(mask.Surface)); // Set the effect for the reflection layer reflectionLayer.Effect = effectBrush; // Now we need to duplicate the visual tree of the visual ArrangeVisualReflection(visual, reflectionLayer, true); visual.Children.InsertAtTop(reflectionLayer); }