图形
图形无疑是当代应用程序界面最重要的功能,君不见那些控件不管是很cool的还是不cool的都要使用几何图形来显示。大家知道,图形分成两大类:位图和矢量图。有意思的是在界面设计上网页以位图居多,Windows桌面应用则是矢量图居多。究其原因,并不难理解,因为网页大部分的控件尺寸都是固定的,是用位图不会对界面带来太大的影响,而桌面应用中的窗体大小大多数都是可变的,所以矢量图更适合。在XAML中你不用会很大的劲就可以设计出各种图形,无论是二维还是三维图形。
我们先介绍2D图形,使用最后一次的XAML,把最后一个空的StackPanel改为<Canvas>。下面的代码显示了一组线段,是用不同的颜色和宽度:
<Canvas>
<Line X1="10" Y1="10" X2="100" Y2="10" Stroke="#FF0000"></Line>
<Line X1="10" Y1="20" X2="100" Y2="20" Stroke="#00FF00" StrokeThickness="2"></Line>
<Line X1="10" Y1="30" X2="100" Y2="30" Stroke="#0000FF" StrokeThickness="3"></Line>
<Line X1="10" Y1="40" X2="100" Y2="40" Stroke="#FFFF00" StrokeThickness="4"></Line>
<Line X1="10" Y1="50" X2="100" Y2="50" Stroke="#00FFFF" StrokeThickness="5"></Line>
<Line X1="10" Y1="60" X2="100" Y2="60" Stroke="#FF00FF" StrokeThickness="6"></Line>
</Canvas>
Line元素的X1,Y1, X2,Y2属性分别表示线段的两个端点坐标,Stroke属性指定线段的颜色,StrockThickness属性指定线段的宽度。
另外线段的颜色也可以进行渐变填充,如下面的代码:
<Canvas>
...
<Line X1="10" Y1="100" X2="100" Y2="100" StrokeThickness="10">
<Line.Stroke>
<LinearGradientBrush EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Red" Offset="0.0" />
<GradientStop Color="Yellow" Offset="1.0" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Line.Stroke>
</Line>
</Canvas>
其他的几何图形:
<!-- 矩形 -->
<Rectangle Width="150" Height="80" Stroke="#000000" StrokeThickness="1" Canvas.Left="120" Canvas.Top="10" />
<Rectangle Width="150" Height="80" Stroke="#000000" StrokeThickness="1" Canvas.Left="300" Canvas.Top="10"
Fill="LightGreen" />
<Rectangle Width="150" Height="80" Stroke="#000000" StrokeThickness="1" Canvas.Left="120" Canvas.Top="100"
RadiusX="5" RadiusY="5" />
<Rectangle Width="150" Height="80" Stroke="#000000" StrokeThickness="1" Canvas.Left="300" Canvas.Top="100"
Fill="Orange" RadiusX="5" RadiusY="5"/>
<!-- 椭圆 -->
<Ellipse Width="150" Height="80" Stroke="#000000" StrokeThickness="1" Canvas.Left="120" Canvas.Top="200" />
<!-- 圆 -->
<Ellipse Width="80" Height="80" Stroke="#000000" StrokeThickness="1" Canvas.Left="300" Canvas.Top="200" />
<!--多边形 -->
<Polygon Stroke="#FF000000" Points="500,10 460,30 475,60 525,60 540,30" StrokeThickness="1">
<Polygon.Fill>
<LinearGradientBrush EndPoint="0.707106781186548,0.707106781186547">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="#FF00FFFF" />
<GradientStop Offset="1" Color="#FF0000FF" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Polygon.Fill>
</Polygon>
我们这里介绍的仅仅是一个部分。下面介绍三维图形:
三维图形除了X,Y坐标,还有一个表示深度的Z坐标,要了解3D作图,首先必须熟悉3D场景:
在WPF中,三维坐标的原点在屏幕的中心,X向左为正,Y向上为正,Z向前为正。一个3D场景,你至少需要指定一个相机对象,并设置它的位置和其他属性。有两种相机对象,一种是正交的,另外一种是透视的。
下面的代码就定义了一个透视相机对象:
<Viewport3D.Camera>
<PerspectiveCamera FarPlaneDistance="50" LookDirection="0,0,-1" UpDirection="0,1,0" NearPlaneDistance="1" Position="2,2,15" FieldOfView="45" />
</Viewport3D.Camera>
其中FarPalneDistance和NearPalneDistance属性限定视觉范围,Position属性定义相机的位置,LookDirection属性定义相机的朝向,UpDirection定义相机正上方的方向, FieldOfView顾名思义就是相机的视角了。
定义了相机之后,你可以定义灯光,目前WPF支持4种灯光,它们分别是:AmbientLight、DirectionalLight、SpotLight和PointLight。3D场景中灯光的应用相当重要,如何巧妙的应用灯光效果已经超出了我们的介绍范围,你可以找有关3D设计的资料来看。
下面的代码定义了一盏白色的射灯:
<DirectionalLight Color="White" Direction="-3,-4,-5" />
有了相机和灯光,你就可以构造3D模型了,目前WPF只支持面片模型,也就是说用许多3角形的面构成一个模型表面,三角平面则是通过设置3个顶点坐标进行定义。构造一个3D物体模型相当复杂,以下代码仅仅是一个矩形平面的模型:
<GeometryModel3D>
<!-- 定义物体的几何特征 -->
<GeometryModel3D.Geometry>
<MeshGeometry3D
Positions="-1 -1 0 1 -1 0 -1 1 0 1 1 0"
Normals="0 0 1 0 0 1 0 0 1 0 0 1"
TextureCoordinates="0 1 1 1 0 0 1 0"
TriangleIndices="0,1,2,1,3,2" />
</GeometryModel3D.Geometry>
<!-- 定义物体的材质 -->
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Cyan" Opacity="0.3"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<!-- 定义物体的几何变换 -->
<GeometryModel3D.Transform>
<TranslateTransform3D
OffsetX="-3" OffsetY="0" OffsetZ="-10" >
</TranslateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
最后我们综合到我们上一次的代码,在剩下的界面空间,放置上面的一个平面物体以及一个圆锥物体:
<Viewport3D Name="myViewport" ClipToBounds="True">
<!-- Add a camera. -->
<Viewport3D.Camera>
<PerspectiveCamera FarPlaneDistance="50" LookDirection="0,0,-1" UpDirection="0,1,0" NearPlaneDistance="1" Position="2,1,15" FieldOfView="45" />
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<DirectionalLight Color="White" Direction="-3,-2,-5" />
<!-- Define a plane. -->
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D
Positions="-1 -1 0 1 -1 0 -1 1 0 1 1 0"
Normals="0 0 1 0 0 1 0 0 1 0 0 1"
TextureCoordinates="0 1 1 1 0 0 1 0 "
TriangleIndices="0,1,2,1,3,2" />
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Cyan" Opacity="0.3"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<GeometryModel3D.Transform>
<TranslateTransform3D
OffsetX="-3" OffsetY="0" OffsetZ="-10" >
</TranslateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
<!-- Define a cone. -->
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D
Positions="0.293893 -0.5 0.404509 0.475528 -0.5 0.154509 0 0.5 0 0.475528 -0.5 0.154509 0 0.5 0 0 0.5 0 0.475528 -0.5 0.154509 0.475528 -0.5 -0.154509 0 0.5 0 0.475528 -0.5 -0.154509 0 0.5 0 0 0.5 0 0.475528 -0.5 -0.154509 0.293893 -0.5 -0.404509 0 0.5 0 0.293893 -0.5 -0.404509 0 0.5 0 0 0.5 0 0.293893 -0.5 -0.404509 0 -0.5 -0.5 0 0.5 0 0 -0.5 -0.5 0 0.5 0 0 0.5 0 0 -0.5 -0.5 -0.293893 -0.5 -0.404509 0 0.5 0 -0.293893 -0.5 -0.404509 0 0.5 0 0 0.5 0 -0.293893 -0.5 -0.404509 -0.475528 -0.5 -0.154509 0 0.5 0 -0.475528 -0.5 -0.154509 0 0.5 0 0 0.5 0 -0.475528 -0.5 -0.154509 -0.475528 -0.5 0.154509 0 0.5 0 -0.475528 -0.5 0.154509 0 0.5 0 0 0.5 0 -0.475528 -0.5 0.154509 -0.293892 -0.5 0.404509 0 0.5 0 -0.293892 -0.5 0.404509 0 0.5 0 0 0.5 0 -0.293892 -0.5 0.404509 0 -0.5 0.5 0 0.5 0 0 -0.5 0.5 0 0.5 0 0 0.5 0 0 -0.5 0.5 0.293893 -0.5 0.404509 0 0.5 0 0.293893 -0.5 0.404509 0 0.5 0 0 0.5 0 "
Normals="0.7236065,0.4472139,0.5257313 0.2763934,0.4472138,0.8506507 0.5308242,0.4294462,0.7306172 0.2763934,0.4472138,0.8506507 0,0.4294458,0.9030925 0.5308242,0.4294462,0.7306172 0.2763934,0.4472138,0.8506507 -0.2763934,0.4472138,0.8506507 0,0.4294458,0.9030925 -0.2763934,0.4472138,0.8506507 -0.5308242,0.4294462,0.7306172 0,0.4294458,0.9030925 -0.2763934,0.4472138,0.8506507 -0.7236065,0.4472139,0.5257313 -0.5308242,0.4294462,0.7306172 -0.7236065,0.4472139,0.5257313 -0.858892,0.429446,0.279071 -0.5308242,0.4294462,0.7306172 -0.7236065,0.4472139,0.5257313 -0.8944269,0.4472139,0 -0.858892,0.429446,0.279071 -0.8944269,0.4472139,0 -0.858892,0.429446,-0.279071 -0.858892,0.429446,0.279071 -0.8944269,0.4472139,0 -0.7236065,0.4472139,-0.5257313 -0.858892,0.429446,-0.279071 -0.7236065,0.4472139,-0.5257313 -0.5308242,0.4294462,-0.7306172 -0.858892,0.429446,-0.279071 -0.7236065,0.4472139,-0.5257313 -0.2763934,0.4472138,-0.8506507 -0.5308242,0.4294462,-0.7306172 -0.2763934,0.4472138,-0.8506507 0,0.4294458,-0.9030925 -0.5308242,0.4294462,-0.7306172 -0.2763934,0.4472138,-0.8506507 0.2763934,0.4472138,-0.8506507 0,0.4294458,-0.9030925 0.2763934,0.4472138,-0.8506507 0.5308249,0.4294459,-0.7306169 0,0.4294458,-0.9030925 0.2763934,0.4472138,-0.8506507 0.7236068,0.4472141,-0.5257306 0.5308249,0.4294459,-0.7306169 0.7236068,0.4472141,-0.5257306 0.8588922,0.4294461,-0.27907 0.5308249,0.4294459,-0.7306169 0.7236068,0.4472141,-0.5257306 0.8944269,0.4472139,0 0.8588922,0.4294461,-0.27907 0.8944269,0.4472139,0 0.858892,0.429446,0.279071 0.8588922,0.4294461,-0.27907 0.8944269,0.4472139,0 0.7236065,0.4472139,0.5257313 0.858892,0.429446,0.279071 0.7236065,0.4472139,0.5257313 0.5308242,0.4294462,0.7306172 0.858892,0.429446,0.279071"
TriangleIndices="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 "/>
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Red" Opacity="1.0"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
</GeometryModel3D>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
一个3D物体最复杂的就是那些顶点数据,手工完成他们是难以想象的,这通常通过3D建模软件来生成。WPF的未来版本会有相应的3D设计器,那时候就方便了。
图形设计我们就简单的到此为止,下一次我们介绍动画。
WPF体验(一)
WPF体验(二)
WPF体验(三)
WPF体验(五)