天天看點

人立方關系搜尋的silverlight控件外觀定制揭秘

 最近微軟亞洲研究院的人立方關系搜尋新釋出了幾個Silverlight的應用,包括關系圖搜尋,六度搜尋和新聞時間軸。相信其絢麗的界面效果和賞心悅目的動畫給大家留下了深刻印象。這裡,我就嘗試和大家一起來對這些應用進行揭謎,着重探讨siliverlight中三種定制控件外觀的方法:

1)

在代碼裡面設定控件的風格

這種方法隻能對控件的外觀做一些簡單的,輕量級的修改。比如這個半透明的矩形框:

人立方關系搜尋的silverlight控件外觀定制揭秘

我們隻需要在代碼裡面這樣寫:

<Rectangle Fill="White" Opacity="0.1" Height="75" Canvas.Left="0" Canvas.Top="1" Margin="0,0,0,100" Width="20000"/>

其中Opacity屬性就是設定矩形框的透明度,這裡設為0.1,使其非常透明。可惜的是,這個矩形框在後來的設計中去掉了L

2)

把控件的風格寫成資源檔案

很多情況下,上面的方法就夠用了。但是有時我們會遇到這樣的情況:我們需要給多個控件設定類似的屬性。仍然以上面的矩形框為例子,那代碼就會是這樣:

<Rectangle Fill="White" Opacity="0.1" Height="75" Canvas.Left="0" Canvas.Top="1" Margin="0,0,0,100" Width="2000"/>

<Rectangle Fill="White" Opacity="0.2" Height="75" Canvas.Left="0" Canvas.Top="1" Margin="0,0,0,100" Width="2000"/>

<Rectangle Fill="White" Opacity="0.3" Height="75" Canvas.Left="0" Canvas.Top="1" Margin="0,0,0,100" Width="2000"/>

<Rectangle Fill="White" Opacity="0.4" Height="75" Canvas.Left="0" Canvas.Top="1" Margin="0,0,0,100" Width="2000"/>

……

有沒有簡單清晰的做法呢?有的!

我們仍然以六度搜尋界面中的控件為例子:

人立方關系搜尋的silverlight控件外觀定制揭秘

圖中白色的矩形框顯示了兩個人物之間的關系來源。

現在我們來設定其中黃色框中的兩個名字的顯示屬性。它是一個TextBlock控件,代碼裡面我們這樣寫:

<TextBlock x:Name="textBlock" Text="{Binding Path=TitleB}" Style="{StaticResource

TitleBlock}"/>

這個TextBlock的風格指向了名為”TitleBlock”的資源,其定義為:

<Style x:Key="TitleBlock" TargetType="TextBlock">

<Setter Property="FontFamily" Value="Microsoft YaHei"/>

<Setter Property="FontSize" Value="12"/>

<Setter Property="VerticalAlignment" Value="Center"/>

<Setter Property="HorizontalAlignment" Value="Left"/>

<Setter Property="Grid.Row" Value="1"/>

<Setter Property="Grid.Column" Value="1"/>

<Setter Property="Grid.ColumnSpan" Value="1"/>

</Style>

這樣,多個控件可以共享這個名為“TitleBlock”的資源。我們可以通過修改這個資源檔案,進而輕易的修改多個控件的外觀。

3)

重寫控件的模闆

有時我們不得不面對複雜一些的情況:

人立方關系搜尋的silverlight控件外觀定制揭秘

請看圖中黃色橢圓框中的控件,它們都是Button控件,但是其外觀被完全改頭換面了。我會選取其中三個控件作為例子在這裡談一談:

3.1

箭頭按鈕

人立方關系搜尋的silverlight控件外觀定制揭秘

這個按鈕的外形是個三角形,其定義為:

<Button x:Name="arrowUp" Canvas.Top="9" Canvas.Left="15" Canvas.ZIndex="99" Style="{StaticResource ArrowUpButton}"Click="ArrayUp_Click"/>

它的Style指向了:

<Style x:Key="ArrowUpButton" TargetType="Button">
<Setter Property="Cursor" Value="Hand"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Unfocused"/>
<VisualState x:Name="Focused"/>
</VisualStateGroup>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed"/>
<VisualState x:Name="Disabled"/>
<VisualState x:Name="Normal"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Polygon
Points="0,5 5,0 10,5 0,5"
Stroke="White"
StrokeThickness="0">
<Polygon.Fill>
<SolidColorBrush Color="White" Opacity="1"/>
</Polygon.Fill>
</Polygon>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
           

我們可以看到,這個控件的“内部”被放入了一個Polygon控件,是以這個箭頭按鈕會呈現這個Polygon所描繪的三角形。

3.2

圓圈按鈕

人立方關系搜尋的silverlight控件外觀定制揭秘

那麼如果想做這個具有人立方特色的圓圈按鈕,其步驟就可以分為如下幾步:

3.2.1

把多個Ellipse控件封裝到Button控件中

<Grid Height="auto" HorizontalAlignment="Center" VerticalAlignment="Center" Width="auto" IsHitTestVisible="True"Background="{x:Null}">

<Ellipse Margin="0,0,0,0" Stroke="{x:Null}" HorizontalAlignment="Center" VerticalAlignment="Center" Width="{TemplateBindingCircleButtonWidth1}" Height="{TemplateBinding CircleButtonHeight1}" IsHitTestVisible="False" x:Name="ellipse1"Fill="{TemplateBinding Ellipse1Fill}">

</Ellipse>

<Grid Margin="0,0,0,0" HorizontalAlignment="Center" Width="1024" Height="1024" VerticalAlignment="Center"RenderTransformOrigin="0.5,0.5" x:Name="grid" Opacity="1" Background="{x:Null}" IsHitTestVisible="True">

<Ellipse Fill="{TemplateBinding Ellipse2Fill}" Stroke="{TemplateBinding Ellipse2Stroke}" Margin="0,0,0,0" Width="{TemplateBindingCircleButtonWidth2}" Height="{TemplateBinding CircleButtonHeight2}" x:Name="ellipse2" RenderTransformOrigin="0.5,0.5"HorizontalAlignment="Center" VerticalAlignment="Center">

</Ellipse>

<Ellipse Margin="2,2,2,2" Fill="{TemplateBinding Ellipse3Fill}" Width="{TemplateBinding CircleButtonWidth3}"Height="{TemplateBinding CircleButtonHeight3}" x:Name="ellipse3" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Center"VerticalAlignment="Center">

</Ellipse>

<TextBlock Margin="0,0,0,0" FontFamily="Microsoft YaHei" FontSize="{TemplateBinding FontSize}" Foreground="#FFFFFFFF"HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="textBlock" Text="{TemplateBinding Content}"RenderTransformOrigin="0.5,0.5" IsHitTestVisible="False">

</TextBlock>

</Grid>

</Grid>

3.2.2

注冊一些屬性,使得我們可以在代碼裡面動态的設定它們:

///
<summary>
/// The ellipse1 fill.
///
</summary>
public Brush Ellipse1Fill
{
get
{
return (Brush)base.GetValue(Ellipse1FillProperty);
}
set
{
base.SetValue(Ellipse1FillProperty, value);
}
}
///
<summary>
/// Register property.
///
</summary>
public static readonly DependencyProperty Ellipse1FillProperty = DependencyProperty.Register("Ellipse1Fill", typeof(Brush),typeof(CircleButton), null);
           

這裡我們就注冊了名為Ellipse1Fill的屬性,于是就可以設定它的值:

人立方關系搜尋的silverlight控件外觀定制揭秘

3.2.3

給其中部分Ellipse控件加上合适的storyboard,來處理滑鼠的MouseOver事件

<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="ellipse2"Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1.5"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="ellipse2"Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1.5"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="ellipse3"Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1.5"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="ellipse3"Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1.5"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="textBlock"Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1.5"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="textBlock"Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1.5"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
           

這樣,這個具有人立方特色的圓圈按鈕就完成了。

3.3       線段按鈕

人立方關系搜尋的silverlight控件外觀定制揭秘

人立方的silverlight應用裡面還有這樣的線段按鈕,它很細,但是很容易被滑鼠點選到,具有很好的使用者體驗。其制作步驟也是類似的:

3.3.1.

封裝兩個Path控件到Button控件中:

a)

一個用來處理滑鼠的Mouse over事件

<Path x:Name="outerPath" Stroke="White" StrokeThickness="10" Data="{TemplateBinding OuterPathData}" Opacity="0"></Path>

b)

一個用來顯示這條線段

<Path x:Name="path" Stroke="White" StrokeThickness="1" Data="{TemplateBinding PathData}" Opacity="{TemplateBindingOpacity}"></Path>

3.3.2.

注冊Path的Data屬性

public Geometry PathData
{
get
{
return (Geometry)base.GetValue(PathDataProperty);
}
set
{
base.SetValue(PathDataProperty, value);
}
}
public static readonly DependencyProperty PathDataProperty = DependencyProperty.Register("PathData", typeof(Geometry),typeof(PathButton), null);
           

3.3.3.

Path控件的Data屬性設定為特殊的貝賽爾曲線,使得整個關系圖看起來更具有立體感。

this.PathData = CreatePathData();

private PathGeometry CreatePathData()

{

PathGeometry pathGeometry = new PathGeometry();

PathFigure pathFigure = new PathFigure();

pathFigure.StartPoint = leftPoint;

pathGeometry.Figures.Add(pathFigure);

Point midPoint = To2D.getPoint(leftPoint, rightPoint, centerPoint);

QuadraticBezierSegment arcs = new QuadraticBezierSegment();

arcs.Point1 = midPoint;

arcs.Point2 = rightPoint;

pathFigure.Segments.Add(arcs);

return pathGeometry;

}

3.3.4.

加入對應的storyboard

DoubleAnimation opacity = new DoubleAnimation();

opacity.From = 0;

         opacity.To = endOpacity;

         opacity.Duration = new Duration(TimeSpan.FromSeconds(1));

         Storyboard story = new Storyboard();

         story.Children.Add(opacity);

         Storyboard.SetTarget(opacity, this);

         Storyboard.SetTargetProperty(opacity, new PropertyPath("(UIElement.Opacity)"));

         story.BeginTime = TimeSpan.FromSeconds(beginTime);

         story.Completed += new EventHandler(AppearStory_Completed);

         story.Begin();

使得當滑鼠hover到線段按鈕上時,整條線段變亮。

快速連結:

人立方六度連連看(Silverlight):http://renlifang.msra.cn/6du.aspx

人立方六度連連看(Flash):http://renlifang.msra.cn/6dumap.aspx

人立方實時資訊關系圖(Silverlight):http://renlifang.msra.cn/news.aspx

人立方實時資訊關系圖(Flash):http://renlifang.msra.cn/newsMap.aspx 

繼續閱讀