Last July I had the pleasure of creating my second Silverlight app for Microsoft Advertising (You can read about the first one here) while working at VCCP. This Silverlight tool lets you view and filter videos from the Ad Vision series in an easy to use and visually engaging way.
Turning scamps into designs
This time around a creative team was involved and came to the briefing with a scamp (Thanks Ant & Rich!). “We’d like the videos to float in 3D space… and can you put some controls down the left to filter them according to date or who is in them.” Sure, that sounds great ;-).
Here’s the designs exported from Adobe Illustrator.
If you don’t want to filter the videos the panel on the left will slide out of the way so you can enjoy the videos clutter free.
Note the inclusion of the search box. This was removed in development. Unless the users were familiar with the speakers, or we included topics in the tagging, it wasn’t that useful.
Actually the zoomed in ‘quote’ plaque didn’t make it into the development. Clicking the plaque takes you to the video that the quote is from.
All videos are hosted on MSN Video and streamed in by the custom XAML video player. With some visual trickery the plaque in space is tweened using a XAML storyboard animation and swapped to the fixed position video player at the end.
Linq, XML and plaques
Linq is great for importing XML. All the plaque data and text (including buttons) are stored and updated in XML. Here’s a sample.
<plaque ref="plaque7" type="quote"> <quote><![CDATA["I'm most excited about the merging of the physical and digital world."]]></quote> <cite><![CDATA[Trevor Kaufman]]></cite> </plaque> <plaque ref="plaque7" type="hidden"> <title><![CDATA[Interview with Trevor Kaufman, CEO of Possible Worldwide]]></title> <desc><![CDATA[Trevor Kaufman on the future of digital creativity and keeping up with the pace of change.]]></desc> <video><![CDATA[mms://….wmv]]></video> <speaker><![CDATA[Trevor Kaufman]]></speaker> <thumb><![CDATA[/images/thumbs/thumb_7.jpg]]></thumb> <tag><![CDATA[Interviews]]></tag> <date year="2011" month="5" day="17" /> </plaque>
There are three types of plaques, quote
, hidden
and video
. When clicked a quote plaque will use the ref
attribute to animate to a video. The reference should match a hidden plaque’s reference. Hidden plaques are otherwise the same as the video ones.
The speaker
, tag
and date
nodes are used by the filtering tools.
Zoom slider
The most exciting part of this project was creating the custom slider for zooming through the videos in 3D space. This was done by extending the default Slider control, appropriately named ‘ZoomSlider’. An extra dependency property (UpdateTicksHeight
) was added to update the height, and tick marks along the slider, whenever the videos are filtered. Here’s the C#.
… namespace AdVisionTool.View { public class ZoomSlider : Slider { public static readonly DependencyProperty UpdateTicksHeightProperty = DependencyProperty.Register("UpdateTicksHeight", typeof(double), typeof(ZoomSlider), new PropertyMetadata(UpdateTicksHeight_Changed)); private double _height { get; set; } public double UpdateTicksHeight { get { return (double)GetValue(UpdateTicksHeightProperty); } set { SetValue(UpdateTicksHeightProperty, value); } } public ZoomSlider() { DefaultStyleKey = typeof(ZoomSlider); this.Loaded += new RoutedEventHandler(ZoomSlider_Loaded); } private void ZoomSlider_Loaded(object sender, RoutedEventArgs e) { _height = base.ActualHeight; } public override void OnApplyTemplate() { AddOrUpdateTicks(); base.OnApplyTemplate(); } private void ZoomSlider_LayoutUpdated(object sender, EventArgs e) { AddOrUpdateTicks(); } private void AddOrUpdateTicks() { Grid ticksOuter = (Grid)GetTemplateChild("VerticalTrackTicksOuter"); Grid ticksInner = (Grid)GetTemplateChild("VerticalTrackTicksInner"); Thumb thumb = (Thumb)GetTemplateChild("VerticalThumb"); if (ticksOuter != null && ticksInner != null) { // remove any ticks from previous updates if (ticksOuter.Children.Count > 0) while (ticksOuter.Children.Count > 0) ticksOuter.Children.RemoveAt(0); if (ticksInner.Children.Count > 0) while (ticksInner.Children.Count > 0) ticksInner.Children.RemoveAt(0); GradientStopCollection stops = new GradientStopCollection(); GradientStop stop1 = new GradientStop(); GradientStop stop2 = new GradientStop(); stop1.Color = Color.FromArgb(255, 242, 242, 242); stop2.Color = Color.FromArgb(255, 204, 204, 204); stop1.Offset = 0; stop1.Offset = 1; stops.Add(stop1); stops.Add(stop2); LinearGradientBrush grad = new LinearGradientBrush(stops, 90); int h = Convert.ToInt32(Math.Floor(_height / 20)); // add ticks for (int i = 0; i < h; i++) { Rectangle r = new Rectangle(); r.SetValue(NameProperty, "TickOuter_" + i); r.Height = 3; r.Width = 11; r.HorizontalAlignment = HorizontalAlignment.Center; r.VerticalAlignment = VerticalAlignment.Top; if (i==0) r.Margin = new Thickness(0, 4, 0, 0); else r.Margin = new Thickness(0,i*((_height-11)/(h-1))+4,0,0); r.Fill = grad; ticksOuter.Children.Add(r); Rectangle g = new Rectangle(); g.SetValue(NameProperty, "TickInner_" + i); g.Height = 1; g.Width = 9; g.HorizontalAlignment = HorizontalAlignment.Center; g.VerticalAlignment = VerticalAlignment.Top; if (i == 0) g.Margin = new Thickness(0, 5, 0, 0); else g.Margin = new Thickness(0,i*((_height-11)/(h-1))+5,0,0); g.Fill = new SolidColorBrush(Colors.Black); ticksInner.Children.Add(g); } } } public static void UpdateTicksHeight_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) { ZoomSlider slider = (ZoomSlider)d; slider._height = (double)e.NewValue; slider.AddOrUpdateTicks(); } } }
Most of the Microsoft Advertising website has gone all HTML 5. The Ad Vision Tool is no longer available. For those of you with the Silverlight 4 or higher plug-in I’ve placed a copy link. :-)