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?
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;
}
}
}