/// <summary> /// Performs to the required animation to reset selection on the Selected Visual /// </summary> private void ResetBannerItems() { if (_selectedVisual == null) { return; } _isCollapsing = true; // Get the value to set for the LeftInset of the InsetClip float left; _selectedVisual.Properties.TryGetScalar("LeftInset", out left); _collapseLeftInset.InsertKeyFrame(1f, left); // Get the value to set for the RightInset of the InsetClip float right; _selectedVisual.Properties.TryGetScalar("RightInset", out right); _collapseRightInset.InsertKeyFrame(1f, right); // Use a scoped batch helper to queue up animations one after the other _compositor.CreateScopedBatch(CompositionBatchTypes.Animation, () => { // Collapse the visual _selectedVisual.Clip.StartAnimation("RightInset", _collapseInsetClip.Animation); }, async() => { // If the first visual is selected, then no need to move it to the leftmost // position as it is already there. if (!ReferenceEquals(_selectedVisual, _fluidItems.Keys.ElementAt(0))) { // Move the visual back to its original location in the banner _selectedVisual.Clip.StartAnimation("LeftInset", _collapseLeftInset.Animation); _selectedVisual.Clip.StartAnimation("RightInset", _collapseRightInset.Animation); } // Fade in the other visuals and scale them to normal size foreach (var child in _bgLayer.Children) { child.Scale = Vector3.One; child.Opacity = 1; } // Delay the exchange, of selected visual, between the top and background layers // by the DefaultScaleAnimationDuration so that other visuals in // the Banner scale back to normal await Task.Delay((int)DefaultScaleAnimationDuration.TotalMilliseconds); // Bring the selected visual from top layer to the background layer _topLayer.Children.Remove(_selectedVisual); _bgLayer.Children.InsertAtTop(_selectedVisual); _selectedVisual = null; _isCollapsing = false; // Check the current location of the Pointer and whether it is hovering // over any of the FluidBanner items HandlePointerPosition(GetPointerPosition()); }); }
/// <summary> /// Initialize all Composition related stuff here (Compositor, Animations etc) /// </summary> private void InitializeComposition() { var rootVisual = ElementCompositionPreview.GetElementVisual(this); // Compositor _compositor = rootVisual.Compositor; // Composition Generator _generator = CompositionGeneratorFactory.GetCompositionGenerator(_compositor); // Final Value Expressions var vector3Expr = _compositor.CreateFinalValueExpression <Vector3>(); var scalarExpr = _compositor.CreateFinalValueExpression <float>(); // Opacity Animation var opacityAnimation = _compositor.CreateKeyFrameAnimation <float>() .HavingDuration(DefaultOpacityAnimationDuration) .ForTarget(() => rootVisual.Opacity); opacityAnimation.InsertExpressionKeyFrame(1f, scalarExpr); // Scale Animation var scaleAnimation = _compositor.CreateKeyFrameAnimation <Vector3>() .HavingDuration(DefaultScaleAnimationDuration) .ForTarget(() => rootVisual.Scale); scaleAnimation.InsertExpressionKeyFrame(1f, vector3Expr); // ImplicitAnimation _implicitAnimationCollection = _compositor.CreateImplicitAnimationCollection(); _implicitAnimationCollection["Opacity"] = opacityAnimation.Animation; _implicitAnimationCollection["Scale"] = scaleAnimation.Animation; // Expand Animations _expandLeftInset = _compositor.CreateKeyFrameAnimation <float>() .HavingDuration(InsetAnimationDuration) .DelayBy(InsetAnimationDelayDuration); _expandLeftInset.InsertKeyFrame(1f, 0); _expandRightInset = _compositor.CreateKeyFrameAnimation <float>() .HavingDuration(InsetAnimationDuration) .DelayBy(InsetAnimationDelayDuration); _expandInsetClip = _compositor.CreateKeyFrameAnimation <float>() .HavingDuration(InsetClipAnimationDuration); _expandInsetClip.InsertKeyFrame(1f, 0); // Collapse Animations _collapseLeftInset = _compositor.CreateKeyFrameAnimation <float>() .HavingDuration(InsetAnimationDuration); _collapseRightInset = _compositor.CreateKeyFrameAnimation <float>() .HavingDuration(InsetAnimationDuration); _collapseInsetClip = _compositor.CreateKeyFrameAnimation <float>() .HavingDuration(InsetClipAnimationDuration); // Root Container _rootContainer = _compositor.CreateContainerVisual(); // Background Layer _bgLayer = _compositor.CreateLayerVisual(); _bgLayer.Size = _rootContainer.Size; _bgLayer.CenterPoint = new Vector3(_bgLayer.Size * 0.5f, 0); // Top Layer _topLayer = _compositor.CreateLayerVisual(); _topLayer.Size = _rootContainer.Size; _rootContainer.Children.InsertAtBottom(_bgLayer); _rootContainer.Children.InsertAtTop(_topLayer); // Add the rootContainer to the visual tree ElementCompositionPreview.SetElementChildVisual(this, _rootContainer); }
/// <summary> /// Handles the Arrange pass during Layout /// </summary> /// <param name="finalSize">Final Size of the control</param> /// <returns>Total size occupied by all the Children</returns> protected override Size ArrangeOverride(Size finalSize) { if ((ItemsSource == null) || !ItemsSource.Any()) { return(finalSize); } // Resize the rootContainer _rootContainer.Size = finalSize.ToVector2(); var padding = Padding; var paddingSize = padding.CollapseThickness(); var width = finalSize.Width; var height = finalSize.Height; _itemCount = ItemsSource.Count(); _availableWidth = (width - paddingSize.Width).Single(); _availableHeight = (height - paddingSize.Height).Single(); var gapCount = _itemCount - 1; var totalGap = (gapCount * ItemGap).Single(); var availableNonGapWidth = _availableWidth - totalGap; var availableNonGapHeight = _availableHeight; _itemWidth = availableNonGapWidth / _itemCount; _itemHeight = availableNonGapHeight; _bannerBounds = new Rect(padding.Left, padding.Top, _availableWidth, _availableHeight); // Update Visual sizes and surfaceImages var availableSize = new Vector2(_availableWidth, _availableHeight); _rootContainer.Size = availableSize; _bgLayer.Size = availableSize; _bgLayer.CenterPoint = new Vector3(_bgLayer.Size * 0.5f, 0); _topLayer.Size = availableSize; // Check if any visual is currently selected. If yes then obtain its index. // The new visual at that index should be selected and added to the toplayer var selectedVisualIndex = -1; if (_selectedVisual != null) { foreach (var item in _fluidItems) { selectedVisualIndex++; if (ReferenceEquals(item.Key, _selectedVisual)) { break; } } } for (var index = 0; index < _surfaceImages.Count; index++) { // Get the surfaceImage var surfaceImage = _surfaceImages.ElementAt(index); // Get the visual corresponding to this surfaceImage var itemVisual = _surfaceVisuals[surfaceImage]; if (itemVisual == null) { continue; } itemVisual.Size = availableSize; itemVisual.CenterPoint = new Vector3(itemVisual.Size * 0.5f, 0); var contentVisual = itemVisual.Children.ElementAt(0) as SpriteVisual; if (contentVisual == null) { continue; } contentVisual.Size = availableSize; contentVisual.CenterPoint = itemVisual.CenterPoint; (contentVisual.Brush as CompositionSurfaceBrush)?.UpdateSurfaceBrushOptions(Stretch, AlignX, AlignY); // Calculate the Inset Clip var left = index * (_itemWidth + ItemGap.Single()); var right = _availableWidth - (left + _itemWidth); itemVisual.Properties.InsertScalar("LeftInset", left); itemVisual.Properties.InsertScalar("RightInset", right); itemVisual.Clip = (index == selectedVisualIndex) ? _compositor.CreateInsetClip(0, 0, 0, 0) : _compositor.CreateInsetClip(left, 0, right, 0); // Center Point itemVisual.CenterPoint = new Vector3(left + (_itemWidth / 2f), (float)padding.Top + (_itemHeight / 2f), 0); contentVisual.CenterPoint = itemVisual.CenterPoint; // Update Fluid Items _fluidItems[itemVisual] = new Rect(padding.Left + left, padding.Top, _itemWidth, _itemHeight); } // Update Animations' keyframes _expandRightInset.InsertKeyFrame(1f, _availableWidth - _itemWidth); _collapseInsetClip.InsertKeyFrame(1f, _availableWidth - _itemWidth); return(finalSize); }
/// <summary> /// Initialize all Composition related stuff here (Compositor, Animations etc) /// </summary> private void InitializeComposition() { var rootVisual = ElementCompositionPreview.GetElementVisual(this); // Compositor _compositor = rootVisual.Compositor; // Composition Generator _generator = CompositionGeneratorFactory.GetCompositionGenerator(_compositor); // Final Value Expressions var vector3Expr = _compositor.CreateFinalValueExpression<Vector3>(); var scalarExpr = _compositor.CreateFinalValueExpression<float>(); // Opacity Animation var opacityAnimation = _compositor.CreateKeyFrameAnimation<float>() .HavingDuration(DefaultOpacityAnimationDuration) .ForTarget(() => rootVisual.Opacity); opacityAnimation.InsertExpressionKeyFrame(1f, scalarExpr); // Scale Animation var scaleAnimation = _compositor.CreateKeyFrameAnimation<Vector3>() .HavingDuration(DefaultScaleAnimationDuration) .ForTarget(() => rootVisual.Scale); scaleAnimation.InsertExpressionKeyFrame(1f, vector3Expr); // ImplicitAnimation _implicitAnimationCollection = _compositor.CreateImplicitAnimationCollection(); _implicitAnimationCollection["Opacity"] = opacityAnimation.Animation; _implicitAnimationCollection["Scale"] = scaleAnimation.Animation; // Expand Animations _expandLeftInset = _compositor.CreateKeyFrameAnimation<float>() .HavingDuration(InsetAnimationDuration) .DelayBy(InsetAnimationDelayDuration); _expandLeftInset.InsertKeyFrame(1f, 0); _expandRightInset = _compositor.CreateKeyFrameAnimation<float>() .HavingDuration(InsetAnimationDuration) .DelayBy(InsetAnimationDelayDuration); _expandInsetClip = _compositor.CreateKeyFrameAnimation<float>() .HavingDuration(InsetClipAnimationDuration); _expandInsetClip.InsertKeyFrame(1f, 0); // Collapse Animations _collapseLeftInset = _compositor.CreateKeyFrameAnimation<float>() .HavingDuration(InsetAnimationDuration); _collapseRightInset = _compositor.CreateKeyFrameAnimation<float>() .HavingDuration(InsetAnimationDuration); _collapseInsetClip = _compositor.CreateKeyFrameAnimation<float>() .HavingDuration(InsetClipAnimationDuration); // Root Container _rootContainer = _compositor.CreateContainerVisual(); // Background Layer _bgLayer = _compositor.CreateLayerVisual(); _bgLayer.Size = _rootContainer.Size; _bgLayer.CenterPoint = new Vector3(_bgLayer.Size * 0.5f, 0); // Top Layer _topLayer = _compositor.CreateLayerVisual(); _topLayer.Size = _rootContainer.Size; _rootContainer.Children.InsertAtBottom(_bgLayer); _rootContainer.Children.InsertAtTop(_topLayer); // Add the rootContainer to the visual tree ElementCompositionPreview.SetElementChildVisual(this, _rootContainer); }
/// <summary> /// Initialize all Composition related stuff here (Compositor, Animations etc) /// </summary> private void InitializeComposition() { var rootVisual = ElementCompositionPreview.GetElementVisual(this); // Compositor _compositor = rootVisual.Compositor; // Final Value Expressions var vector3Expr = _compositor.CreateFinalValueExpression <Vector3>(); var scalarExpr = _compositor.CreateFinalValueExpression <float>(); // Opacity Animation var opacityAnimation = _compositor.CreateKeyFrameAnimation <float>() .HavingDuration(DefaultOpacityAnimationDuration) .ForTarget(() => rootVisual.Opacity); opacityAnimation.InsertExpressionKeyFrame(1f, scalarExpr); // Scale Animation var scaleAnimation = _compositor.CreateKeyFrameAnimation <Vector3>() .HavingDuration(DefaultScaleAnimationDuration) .ForTarget(() => rootVisual.Scale); scaleAnimation.InsertExpressionKeyFrame(1f, vector3Expr); // ImplicitAnimation _implicitAnimationCollection = _compositor.CreateImplicitAnimationCollection(); _implicitAnimationCollection["Opacity"] = opacityAnimation.Animation; _implicitAnimationCollection["Scale"] = scaleAnimation.Animation; // Expand Animations _expandLeftInset = _compositor.CreateKeyFrameAnimation <float>() .HavingDuration(InsetAnimationDuration) .DelayBy(InsetAnimationDelayDuration); _expandLeftInset.InsertKeyFrame(1f, 0); _expandRightInset = _compositor.CreateKeyFrameAnimation <float>() .HavingDuration(InsetAnimationDuration) .DelayBy(InsetAnimationDelayDuration); _expandInsetClip = _compositor.CreateKeyFrameAnimation <float>() .HavingDuration(InsetClipAnimationDuration); _expandInsetClip.InsertKeyFrame(1f, 0); // Collapse Animations _collapseLeftInset = _compositor.CreateKeyFrameAnimation <float>() .HavingDuration(InsetAnimationDuration); _collapseRightInset = _compositor.CreateKeyFrameAnimation <float>() .HavingDuration(InsetAnimationDuration); _collapseInsetClip = _compositor.CreateKeyFrameAnimation <float>() .HavingDuration(InsetClipAnimationDuration); // Root Container _rootContainer = _compositor.CreateContainerVisual(); // Image Factory _imageFactory = CompositionImageFactory.CreateCompositionImageFactory(_compositor); // If the ItemsSource has any items then create their corresponding images CreateImages(); }
/// <summary> /// Handles the Arrange pass during Layout /// </summary> /// <param name="finalSize">Final Size of the control</param> /// <returns>Total size occupied by all the Children</returns> protected override Size ArrangeOverride(Size finalSize) { if ((ItemsSource == null) || (!ItemsSource.Any())) { return(finalSize); } var padding = Padding; var paddingSize = padding.CollapseThickness(); var width = finalSize.Width; var height = finalSize.Height; var itemCount = ItemsSource.Count(); _availableWidth = (width - paddingSize.Width).Single(); _availableHeight = (height - paddingSize.Height).Single(); var gapCount = itemCount - 1; var totalGap = (gapCount * ItemGap).Single(); var availableNonGapWidth = _availableWidth - totalGap; var availableNonGapHeight = _availableHeight; _itemWidth = availableNonGapWidth / itemCount; _itemHeight = availableNonGapHeight; _bannerBounds = new Rect(padding.Left, padding.Top, _availableWidth, _availableHeight); // Check if any visual is currently selected. If yes then obtain its index. // The new visual at that index should be selected and added to the toplayer var selectedVisualIndex = -1; if (_selectedVisual != null) { foreach (var item in _fluidItems) { selectedVisualIndex++; if (ReferenceEquals(item.Key, _selectedVisual)) { break; } } } // Clear previous visuals _fluidItems.Clear(); _rootContainer.Children.RemoveAll(); _rootContainer.Size = finalSize.ToVector2(); // Background Layer _bgLayer = _compositor.CreateLayerVisual(); _bgLayer.Size = _rootContainer.Size; _rootContainer.Children.InsertAtBottom(_bgLayer); _bgLayer.CenterPoint = new Vector3(_bgLayer.Size * 0.5f, 0); // Top Layer _topLayer = _compositor.CreateLayerVisual(); _topLayer.Size = _rootContainer.Size; _rootContainer.Children.InsertAtTop(_topLayer); // Create Visuals for (var i = 0; i < itemCount; i++) { // Add a visual for the background var bgVisual = _compositor.CreateSpriteVisual(); bgVisual.Size = new Vector2(_availableWidth, _availableHeight); bgVisual.Brush = _compositor.CreateColorBrush(ItemBackground); // Create the visual for the content var contentVisual = _compositor.CreateSpriteVisual(); contentVisual.Offset = Vector3.Zero; contentVisual.Size = new Vector2(_availableWidth, _availableHeight); // Load image from the Uri contentVisual.Brush = _compositor.CreateSurfaceBrush(_images.ElementAt(i).Surface); // Create the container for the content var container = _compositor.CreateContainerVisual(); container.Offset = new Vector3((float)padding.Left, (float)padding.Top, 0); container.Size = new Vector2(_availableWidth, _availableHeight); // Calculate the Inset Clip var left = i * (_itemWidth + ItemGap.Single()); var right = _availableWidth - (left + _itemWidth); container.Properties.InsertScalar("LeftInset", left); container.Properties.InsertScalar("RightInset", right); // If the current value of 'i' same as the index of the previously selected visual // then the InsetClip value should be appropriately set container.Clip = (i == selectedVisualIndex) ? _compositor.CreateInsetClip(0, 0, 0, 0) : _compositor.CreateInsetClip(left, 0, right, 0); // Center Point container.CenterPoint = new Vector3(left + (_itemWidth / 2f), (float)padding.Top + (_itemHeight / 2f), 0); contentVisual.CenterPoint = container.CenterPoint; container.ImplicitAnimations = _implicitAnimationCollection; contentVisual.ImplicitAnimations = _implicitAnimationCollection; // Set the container content container.Children.InsertAtTop(contentVisual); container.Children.InsertAtBottom(bgVisual); // Is the current value of 'i' same as the index of the previously selected visual if (i == selectedVisualIndex) { // Add to the Top Layer _topLayer.Children.InsertAtTop(container); _selectedVisual = container; } else { // Add to Background Layer _bgLayer.Children.InsertAtTop(container); } // Add Visual to the fluid items _fluidItems[container] = new Rect(padding.Left + left, padding.Top, _itemWidth, _itemHeight); } // If there was a previously selected visual then Scale back // and fade the other visuals in the banner if (selectedVisualIndex > -1) { // foreach (var child in _bgLayer.Children) { child.Scale = new Vector3(ScaleDownFactor, ScaleDownFactor, 1); child.Opacity = TargetOpacity; } } // Update Animations' keyframes _expandRightInset.InsertKeyFrame(1f, _availableWidth - _itemWidth); _collapseInsetClip.InsertKeyFrame(1f, _availableWidth - _itemWidth); // Add the rootContainer to the visual tree ElementCompositionPreview.SetElementChildVisual(this, _rootContainer); return(base.ArrangeOverride(finalSize)); }