WP7 The Mask Way– Rating Control and More

30/04/2011

WP7 The Mask Way– Rating Control and Moreimage

In the last couple of months since Microsoft has release the WP7 I’ve started to build games and apps in XNA and Silverlight.

Regarding building games, it’s different then building applications, especially in UI… and most of the developers don’t like dealing with UI, but UI doesn’t have to be so scary and I’ll start this post with a nice and simple technic I learned when I worked with Photoshop called “Masking”.

The first example I’ll take from the first game I built called = “Raise My Dog” – Raise My Dog is an interactive game for WP7 that allows you to raise a dog inside you mobile device, something like – Tamagotchi game.

imageHeart - I need to build Heart Control to show the user his health, but how do I fill the heart without exceeded the borders???

And as I mention in the article title – Using Mask – to help mask out the heart fill without harming the border,  This technique will save you a lot of time.
The initial goal is to separate the Heart Border from the Heart Background, In my demo I used Paths and not Images but the concept remain the same.

image

Step 1: Placing the Heart Fill
(The heart fill need to be above everything)

<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
>

Step 2: Placing the Mask Between the Fill and Border

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

And I‘ve added a converter to adjust the Health to the Mask Size,
Example:  If the user Health is 50% than I need to change the Mask Height to the center of the Heart Border (half…), but the size have to be relative to the Border Or Heart Fill Size so the Mask size will be 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; }
  • Health = 0 then Mask Height= 68.253
  • Health = 50 then Mask Height= 34.12
  • Health = 90 then Mask Height= 6.8

Step 3: Placing the Border

<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
>

And you’re done! – Download The Demo Project For WP7

image

 

imageRating

Rating Control is more common for application and lots of application use it, The same concept as Heart Masking but here in the Rating Control I used the Same Path for Border and Fill and the difference between them is the Fill property set to “Yellow” in all Stars objects and instead of changing the Height of the Mask I’m changing the Width.

Step 1: Define the Star Path as StaticResource


In the App.Xaml I created a Static Resource called StarPath

<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>

Step 2: Create 5 Stars using Path

<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” />

Step 3: Placing the Mask Between the Fill and Border

<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; }

Step 4: Create 5 Stars using Path but without the Fill Property

<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" />
And you’re done! – Download The Demo Project For WP7
image
Add comment
facebook linkedin twitter email

Leave a Reply