Daily Demos: Silverlight Deep Zoom Randomizing Images

Deep Zooms in Silverlight are great. On key feature is, that you have access to every sub image. So … why don’t we use this with animations?

image

Live Preview

XAML-Code

 <UserControl
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:TheOliver_Controls="clr-namespace:TheOliver.Controls"
    x:Class="DeepZoomMouseBehavior.MainPage"
    d:DesignHeight="300"
    d:DesignWidth="400">

    <Grid
        x:Name="LayoutRoot"
        Background="White">
        <TextBlock
            Text="Deep Zoom Sample" />
        <MultiScaleImage
            x:Name="_msi"
            Source="Images/dzc_output.xml"
            Margin="0,19,0,0">
            <i:Interaction.Behaviors>
                <TheOliver_Controls:DeepZoomBehavior />
            </i:Interaction.Behaviors>
        </MultiScaleImage>
        <Button
            x:Name="_home"
            HorizontalAlignment="Right"
            VerticalAlignment="Top"
            Width="53"
            Content="Home">
            <i:Interaction.Triggers>
                <i:EventTrigger
                    EventName="Click">
                    <TheOliver_Controls:DeepZoomNavigateHomeBehavior
                        TargetName="_msi" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
        <Button
            x:Name="_shuffle"
            HorizontalAlignment="Right"
            VerticalAlignment="Top"
            Width="53"
            Content="Shuffle"
            Margin="0,0,57,0">
            <i:Interaction.Triggers>
                <i:EventTrigger
                    EventName="Click">
                    <TheOliver_Controls:DeepZoomRandomImageArrangeBehavior
                        TargetName="_msi"
                        XOffset="1"
                        YOffset="1" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
    </Grid>
</UserControl>

Sourcecode

 // Copyright © Microsoft Corporation.  All Rights Reserved.
// This code released under the terms of the 
// Microsoft Public License (MS-PL, https://opensource.org/licenses/ms-pl.html.)

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
using System.Windows.Media.Animation;

namespace TheOliver.Controls
{
    public class DeepZoomRandomImageArrangeBehavior : TargetedTriggerAction<MultiScaleImage>
    {
        private List<MultiScaleSubImage> _randomList = new List<MultiScaleSubImage>();

        int _totalColumns = 0;
        int _totalRows = 0;

        private MultiScaleImage _msi;

        public double XOffset
        {
            get { return (double)GetValue(XOffsetProperty); }
            set { SetValue(XOffsetProperty, value); }
        }

        public static readonly DependencyProperty XOffsetProperty = 
            DependencyProperty.Register(
                "XOffset", typeof(double), 
                typeof(DeepZoomRandomImageArrangeBehavior), 
                new PropertyMetadata(1.25, XOffsetChanged));

        private static void XOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }

        public double YOffset
        {
            get { return (double)GetValue(YOffsetProperty); }
            set { SetValue(YOffsetProperty, value); }
        }

        public static readonly DependencyProperty YOffsetProperty = 
            DependencyProperty.Register(
                "YOffset", 
                typeof(double),
                typeof(DeepZoomRandomImageArrangeBehavior), 
                new PropertyMetadata(1.25, YOffsetChanged));

        private static void YOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }

        public int Speed
        {
            get { return (int)GetValue(SpeedProperty); }
            set { SetValue(SpeedProperty, value); }
        }

        public static readonly DependencyProperty SpeedProperty = 
            DependencyProperty.Register(
                "Speed", 
                typeof(int),
                typeof(DeepZoomRandomImageArrangeBehavior), 
                new PropertyMetadata(1000, SpeedChanged));

        private static void SpeedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }

        protected override void Invoke(object o)
        {
            _msi = this.Target;
            ArrangeIntoGrid();
        }

        private void ArrangeIntoGrid()
        {
            _randomList = RandomizedListOfImages();

            int totalImagesAdded = 0;
            double totalWidth = 0;
            double xoffset = XOffset;
            double yoffset = YOffset;
            double margin = .1;

            if (_randomList.Count > 1)
            {
                int numberOfImages = _randomList.Count;
                _totalColumns = 0;
                _totalColumns = (int)Math.Ceiling(Math.Sqrt(numberOfImages));
                _totalRows = numberOfImages / (_totalColumns - 1);
                totalWidth = _totalColumns * xoffset;

                Storyboard moveStoryboard = new Storyboard();

                for (int row = 0; row < _totalRows; row++)
                {
                    for (int col = 0; col < _totalColumns; col++)
                    {
                        if (numberOfImages != totalImagesAdded)
                        {
                            MultiScaleSubImage currentImage = _randomList[totalImagesAdded];
                            currentImage.ViewportWidth = 1;

                            Point currentPosition = new Point(0, 0);
                            Point futurePosition = new Point(-xoffset * col, -yoffset * row);

                            // Create Animation
                            PointAnimationUsingKeyFrames moveAnimation = new PointAnimationUsingKeyFrames();

                            // Create Keyframe
                            SplinePointKeyFrame startKeyframe = new SplinePointKeyFrame();
                            startKeyframe.Value = currentPosition;
                            startKeyframe.KeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero);

                            startKeyframe = new SplinePointKeyFrame();
                            startKeyframe.Value = futurePosition;
                            startKeyframe.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(Speed));

                            KeySpline ks = new KeySpline();
                            ks.ControlPoint1 = new Point(0, 1);
                            ks.ControlPoint2 = new Point(1, 1);
                            startKeyframe.KeySpline = ks;
                            moveAnimation.KeyFrames.Add(startKeyframe);

                            Storyboard.SetTarget(moveAnimation, currentImage);

                            Storyboard.SetTargetProperty(moveAnimation, new PropertyPath("ViewportOrigin"));

                            moveStoryboard.Children.Add(moveAnimation);

                            totalImagesAdded++;
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                if (!_msi.Resources.Contains("myAnim"))
                {
                    _msi.Resources.Add("myAnim", moveStoryboard);
                }

                this._msi.ViewportOrigin = new Point(-margin, -margin);
                this._msi.ViewportWidth = totalWidth + margin;

                // Play Storyboard
                moveStoryboard.Begin();
            }
            else
            {
                MultiScaleSubImage currentImage = _randomList[0];
                currentImage.ViewportWidth = 1 + 2 * margin;
                currentImage.ViewportOrigin = new Point(0, 0);
                this._msi.ViewportOrigin = new Point(-margin, -margin);
                this._msi.ViewportWidth = 1;
            }
        }

        private List<MultiScaleSubImage> RandomizedListOfImages()
        {
            List<MultiScaleSubImage> imageList = new List<MultiScaleSubImage>();
            Random ranNum = new Random();

            // Store List of Images
            foreach (MultiScaleSubImage subImage in _msi.SubImages)
            {
                subImage.Opacity = 1;
                imageList.Add(subImage);
            }

            int numImages = imageList.Count;

            // Randomize Image List
            for (int a = 0; a < numImages; a++)
            {
                MultiScaleSubImage tempImage = imageList[a];
                imageList.RemoveAt(a);

                int ranNumSelect = ranNum.Next(imageList.Count);

                imageList.Insert(ranNumSelect, tempImage);
            }

            return imageList;
        }
    }
}

 

Solutiondownload