65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF、Silverlight 和 WP7 的 XAML 遮罩 - 评级控件等

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (19投票s)

2011 年 4 月 30 日

Ms-PL

2分钟阅读

viewsIcon

41329

downloadIcon

685

为 WP7、WPF 和 Silverlight 使用 XAML 创建遮罩

引言

在微软发布 WP7 的过去几个月里,我开始使用 XNA 和 Silverlight 构建游戏和应用程序。

构建游戏与构建应用程序不同,尤其是在 UI 方面……大多数开发人员不喜欢处理 UI,但 UI 并不一定那么可怕,我将从我在 Photoshop 中学习到的一个简单技巧开始本文,称为“遮罩”。

第一个例子,我将从我构建的一个名为“Raise My Dog”的游戏中提取。Raise My Dog 是一款类似于 Tamagotchi 的 WP7 游戏。玩家可以在他的移动设备上养一只狗,喂养它,并看着它成长。

1.png

心形控制

3.png

UI 的一个重要部分是显示狗的健康状况的“心形控制”。这个心形,嗯,有一个心形 :) 因此我们需要填充它,而不会超出它的边界;我们该怎么做?

正如我在文章标题中提到的:使用遮罩 - 帮助遮住心形填充,而不会损坏边界;这种技术将为您节省大量时间。最初的目标是将心形边界与心形背景分离。在我的演示中,我使用了 Paths 而不是 Images,但概念仍然相同。

2.png

步骤 1:放置心形填充

心形填充需要位于所有内容之上。

<Path x:Name="path" Canvas.Left="246.758" Canvas.Top="199.33" 
   Stretch="Fill" Data="F1 M 246.759,219.964C 246.977,241.504 267.975,
            259.233 284.206,265.059L 284.206,265.059C 300.302,
            259.376 320.885,241.829 320.593,
            220.288L 320.593,220.288C 320.441,208.875 311.149,199.525 299.872,
            199.475L 299.872, 199.475C 293.324,199.446 287.546,202.799 283.884,
            207.667L 283.884,207.667C 283.766,207.823 283.651,207.982 283.536,
            208.142L 283.536,208.142C 279.778,202.988 273.756,199.359 266.995,
            199.33L 266.995,199.33C 263.721,199.316 260.634,200.087 257.902,
            201.468L 257.902,201.468C 251.226,204.844 246.679, 211.865 246.759,219.964 Z"
  Margin="15,20,0,0" RenderTransformOrigin="0.5,0.5" Height="62.369" 
  UseLayoutRounding="False" VerticalAlignment="Top" 
  HorizontalAlignment="Left" Width="65.75">
    <Path.RenderTransform>
        <CompositeTransform/>
    </Path.RenderTransform>
    <Path.Fill>
        <RadialGradientBrush RadiusX="0.470614" RadiusY="0.535016" 
                  Center="0.50193,0.500556" 
                  GradientOrigin="0.50193,0.500556">
            <RadialGradientBrush.GradientStops>
                <GradientStop Color="#FFED272A" Offset="0"/>
                <GradientStop Color="#FF611317" Offset="1"/>
            </RadialGradientBrush.GradientStops>
            <RadialGradientBrush.RelativeTransform>
                <TransformGroup>
                    <SkewTransform CenterX="0.50193" 
                       CenterY="0.500556" AngleX="0.881065" AngleY="0"/>
                    <RotateTransform CenterX="0.50193" 
                       CenterY="0.500556" Angle="0.279347"/>
                </TransformGroup>
            </RadialGradientBrush.RelativeTransform>
        </RadialGradientBrush>
    </Path.Fill>
</Path>

步骤 2:将遮罩放置在填充和边界之间

<Rectangle x:Name="Mask" Fill="{StaticResource PhoneBackgroundBrush}" 
   VerticalAlignment="Top" Margin="4,17,154,0" 
   Height="{Binding HeartValue,Converter={StaticResource HeartValueConverter}}"/>

我添加了一个转换器来调整健康状况以适应遮罩大小:如果狗的健康状况为 50%,那么我需要将遮罩高度更改为心形边界的中心(一半……),但大小必须相对于边界,因此遮罩大小将为 34.126。

//The max height of the heart border.
//100 represent the max scale 
private const double Max = 68.253;
public object Convert(object value, Type targetType, object parameter, 
                      System.Globalization.CultureInfo culture)
{        
    var health = (int)value; 
    return ((((health) * Max) / 100) - Max) * -1;
}
  • 健康值 = 0,遮罩高度 = 68.253
  • 健康值 = 50,遮罩高度 = 34.12
  • 健康值 = 90,遮罩高度 = 6.8

步骤 3:放置边界

<Path x:Name="border" Canvas.Left="243.55" Canvas.Top="195.863" 
  Stretch="Fill" Data="F1 M 243.553,218.219C 243.888,241.644 266.682,261.781 284.255, 
           268.184L 284.255,268.184C 301.628,262.071 323.779,242.306 323.365,218.88L 323.365,
           218.88C 323.143,206.466 313.059,196.258 300.868,196.157L 300.868, 196.157C 293.56,
           196.097 287.157,199.683 283.246,205.238L 283.246,205.238C 279.159,
           199.616 272.639,195.925 265.329,195.864L 265.329,195.864C 261.79,
           195.835 258.456,196.66 255.51,198.151L 255.51,198.151C 248.309,201.793 243.427,
           209.41 243.553,218.219 Z M 284.205,265.049C 268.588,259.359 248.32,
           240.575 248.022, 219.761L 248.022,219.761C 247.868,208.729 256.54,199.805 267.373,
           199.894L 267.373,199.894C 273.871,199.948 279.662,203.228 283.295,208.224L 283.295,
           208.224C 286.767,203.286 292.456,200.102 298.951,200.154L 298.951,
           200.154C 309.784,200.245 318.746,209.315 318.942,220.346L 318.942,
           220.346C 319.271,238.91 303.666,255.593 289.337,262.84L 289.337,262.84C 287.598,
           263.72 285.875,264.461 284.205,265.049 Z " 
  Margin="12,17,0,0" RenderTransformOrigin="0.5,0.5" 
  Width="70.75" Height="68.253" UseLayoutRounding="False" 
  HorizontalAlignment="Left" VerticalAlignment="Top">
    <Path.RenderTransform>
        <CompositeTransform/>
    </Path.RenderTransform>
    <Path.Fill>
        <LinearGradientBrush StartPoint="0.00275276,0.496476" 
                EndPoint="1.0027,0.496476">
            <LinearGradientBrush.RelativeTransform>
                <TransformGroup>
                    <SkewTransform CenterX="0.00275276" 
                       CenterY="0.496476" AngleX="1.353" AngleY="0"/>
                    <RotateTransform CenterX="0.00275276" 
                       CenterY="0.496476" Angle="0.520549"/>
                </TransformGroup>
            </LinearGradientBrush.RelativeTransform>
            <LinearGradientBrush.GradientStops>
                <GradientStop Color="#FFFAF6AF" Offset="0"/>
                <GradientStop Color="#FFF1E091" Offset="0.13058"/>
                <GradientStop Color="#FFE9CA74" Offset="0.159348"/>
                <GradientStop Color="#FF9C6636" Offset="0.510986"/>
                <GradientStop Color="#FFC29855" Offset="0.595192"/>
                <GradientStop Color="#FFE9CA74" Offset="0.75824"/>
                <GradientStop Color="#FFFAF6AF" Offset="0.972534"/>
                <GradientStop Color="#FFFAF6AF" Offset="1"/>
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>
    </Path.Fill>
</Path>

4.png

评分

5.png

评级控件在应用程序中更常见。与心形遮罩相同的概念适用,除了这里我为边界和填充使用相同的 Path,并且所有星形对象的区别在于 Fill 属性设置为 Yellow。此外,我不是更改遮罩的高度,而是更改了宽度。

步骤 1:将星形 Path 定义为 StaticResource

App.Xaml 中,我创建了一个名为 StarPath 的 Static Resource。

<Application.Resources>
    <sys:String x:Key="StarPath">F1 M 0,217.042L 227.5,217.042L 297.875,
        0L 367.542,217L 595.542,217L 410.208,353.667L 480.708,
        569.667L 297.208,436.667L 116.208,568.167L 185.708,352.667L 0,217.042 Z</sys:String>
</Application.Resources>

步骤 2:使用 Path 创建 5 个星形

<Path Name="star" Stretch="Uniform" Data="{StaticResource StarPath}" 
  Fill="Yellow" Width="73" Height="73" HorizontalAlignment="Left" 
  Margin="3,0.667,0,0" VerticalAlignment="Top" d:LayoutOverrides="Width, Height" />
<Path x:Name="star2" Stretch="Uniform" Data="{StaticResource StarPath}" 
  Fill="Yellow" Width="73" Height="73" Margin="81.922,0.333,0,0" 
  HorizontalAlignment="Left" VerticalAlignment="Top" />
<Path x:Name="star3" Stretch="Uniform" Data="{StaticResource StarPath}" 
  Fill="Yellow" Width="73" Height="73" Margin="161.569,0.333,0,0" 
  HorizontalAlignment="Left" VerticalAlignment="Top" />
<Path x:Name="star4" Stretch="Uniform" Data="{StaticResource StarPath}" 
  Fill="Yellow" Width="73" Height="73" Margin="240.895,0.333,0,0" 
  HorizontalAlignment="Left" VerticalAlignment="Top" />
<Path x:Name="star5" Stretch="Uniform" Data="{StaticResource StarPath}" 
  Fill="Yellow" Width="73" Height="73" Margin="320.89,0.333,0,0" 
  HorizontalAlignment="Left" VerticalAlignment="Top" />

步骤 3:将遮罩放置在填充和边界之间

<Rectangle x:Name="Mask" Fill="{StaticResource PhoneBackgroundBrush}" 
   VerticalAlignment="Top" Height="74" HorizontalAlignment="Left" 
   Width="{Binding Value, Converter={StaticResource RaitingValueToWidthConverter}}" 
   RenderTransformOrigin="0.5,0.5"></Rectangle> 

并且我添加了一个转换器来调整宽度以适应遮罩大小(与心形控制相同)。

//The max Width of all stars.
//5 represent the max scale
private const double Max = 395;
public object Convert(object value, Type targetType, object parameter, 
                      System.Globalization.CultureInfo culture)
{          
    var rate = (double)value; 
    return ((((rate) * Max) / 5) - Max) * -1;
}

步骤 4:使用 Path 创建 5 个星形,但不带 Fill 属性

<Path Name="border"  Stretch="Uniform" Data="{StaticResource StarPath}" 
  StrokeThickness="2" Stroke="White" Width="75" Height="75" 
  HorizontalAlignment="Left" Margin="2,-0.333,0,0" 
  VerticalAlignment="Top" d:LayoutOverrides="Width, Height"/>
<Path x:Name="border2"  Stretch="Uniform" Data="{StaticResource StarPath}" 
  StrokeThickness="2" Stroke="White" Width="75" Height="75" 
  Margin="81,-0.333,0,0"  HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Path x:Name="border3"  Stretch="Uniform" Data="{StaticResource StarPath}" 
  StrokeThickness="2" Stroke="White" Width="75" Height="75" 
  Margin="160.659,-0.334,0,0"  HorizontalAlignment="Left" VerticalAlignment="Top" />
<Path x:Name="border4"  Stretch="Uniform" Data="{StaticResource StarPath}" 
  StrokeThickness="2" Stroke="White" Width="75" Height="75" 
  Margin="240.318,-0.334,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" />
<Path x:Name="border5"  Stretch="Uniform" Data="{StaticResource StarPath}" 
  StrokeThickness="2" Stroke="White" Width="75" Height="75" 
  Margin="319.98,-0.334,0,0"  HorizontalAlignment="Left" VerticalAlignment="Top" />

6.png

© . All rights reserved.