人立方关系搜索的silverlight控件外观定制揭秘
来源:互联网 发布:js blur onblur 区别 编辑:程序博客网 时间:2024/09/21 09:04
最近微软亚洲研究院的人立方关系搜索新发布了几个Silverlight的应用,包括关系图搜索,六度搜索和新闻时间轴。相信其绚丽的界面效果和赏心悦目的动画给大家留下了深刻印象。这里,我就尝试和大家一起来对这些应用进行揭谜,着重探讨siliverlight中三种定制控件外观的方法:
1)
在代码里面设置控件的风格
这种方法只能对控件的外观做一些简单的,轻量级的修改。比如这个半透明的矩形框:
我们只需要在代码里面这样写:
<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"/>
……
有没有简单清晰的做法呢?有的!
我们仍然以六度搜索界面中的控件为例子:
图中白色的矩形框显示了两个人物之间的关系来源。
现在我们来设置其中黄色框中的两个名字的显示属性。它是一个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)
重写控件的模板
有时我们不得不面对复杂一些的情况:
请看图中黄色椭圆框中的控件,它们都是Button控件,但是其外观被完全改头换面了。我会选取其中三个控件作为例子在这里谈一谈:
3.1
箭头按钮
这个按钮的外形是个三角形,其定义为:
<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><PolygonPoints="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
圆圈按钮
那么如果想做这个具有人立方特色的圆圈按钮,其步骤就可以分为如下几步:
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的属性,于是就可以设置它的值:
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应用里面还有这样的线段按钮,它很细,但是很容易被鼠标点击到,具有很好的用户体验。其制作步骤也是类似的:
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
- 人立方关系搜索的silverlight控件外观定制揭秘
- 人立方关系搜索的silverlight控件外观定制揭秘
- 人立方关系搜索
- UIAppearance定制控件的默认外观
- 微软亚洲研究院推出“人立方”人物关系搜索
- 微软亚洲研究院发布“人立方关系搜索”
- WTL初步:定制控件外观
- 使用appearance proxy定制控件的默认外观(详解)
- 定制DataGrid的外观
- 定制DataGrid的外观
- Xpage中对定制控件在设计视图下外观的定制
- Silverlight 使用控件模板定制控件
- 控制台程序的外观定制
- Lesson9: 定制应用程序的外观
- Lesson9: 定制应用程序的外观
- 微软的人立方关系图竟然用的Flash!!!
- 人立方六度搜索的界面设计的来龙去脉
- 对windows 10 UWP中控件的外观进行定制(customization)
- Modbus rtu CRC在线计算
- 符号的英文读法
- Android JNI 使用的数据结构JNINativeMethod详解
- IOS 5编程 内存管理 ARC技术概述
- SEH中的prolog和epilog
- 人立方关系搜索的silverlight控件外观定制揭秘
- JAVASCRIPTVS JQUERY
- awstats分析多个日志
- 用GDB调试程序(二)
- SQL语句经典大全(二)提升
- DDD调试opencore/stagefright
- java中四种操作(DOM、SAX、JDOM、DOM4J)xml方式详解与比较
- stagefright + omx小结
- “惊群”问题