Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Evenly Spaced Dashes with StrokeDashArray

I'm trying to create a poker chip like the one here: http://www.casinowholesalers.com/shop/product_info.php?cPath=57&products_id=379 using Expression Blend 4 for a WP7.1 Silverlight 4 app.

I'm trying to create the six white "boxes" on the edge of the chip (ignoring for now the dice images and inner dashed line). The way I did it was two create two ellipses, one with no stroke, the other is the exact same size but with a stroke of 24, a color of White, and the StrokeDashArray to 1.8 (that's not "1 8", it's actually 1.8 with no second value). It looks pretty close to evenly sized and spaced (but not quite); I found it by trial and error. The XAML is below.

<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Ellipse Fill="#FFC83838" Margin="112,253,128,275" Grid.Row="1" Stroke="#FFC83838" StrokeThickness="3"/>
    <Ellipse Fill="#FFC83838" Margin="112,253,128,275" Grid.Row="1" Stroke="White" StrokeThickness="30" StrokeDashArray="1.79" StrokeDashOffset="6" RenderTransformOrigin="0.5,0.5"/>
</Grid>

I guess I have two questions:

  1. Is there a better way to create this shape besides using two ellipses?
  2. How can I mathematically determine what the StrokeDashArray value should be so the dashes are evenly spaced and sized instead of using trial and error?
like image 570
Jeff Avatar asked May 29 '12 15:05

Jeff


1 Answers

I'll start from the second point.

First, the inner logic of StrokeDashArray is explained here. The important point is that the stroke dash array is not expressed in pixels, it's dependent upon stroke thickness to get the final pixel value for each number in the array.

So, for the math part, lets define some variables:

  1. S - visible portion of the stroke (same as in the link).
  2. G - the non-visible portion of the stroke (same as in the link).
  3. r - the radius of your chip. It will be half of the actual width or half of the actual height.
  4. n - the number of repetitions of S+G that you want. Integer.
  5. T - stroke thickness
  6. p - the mathematical pi (3.14...)

So we have:

2*p*r = n*(T*S+T*G)

Or,

S+G = 2pr/nT

In your case, and what I see from the image of the chip, the visible part of the stroke is square so S=1, there are six white squares with six gaps so n=6 and you decided for thickness of 30px so T=30. This gives you the value of G as:

G = 2pr/180 - 1

You can get the value of r from blend, the actual width and height will be written in parenthesis in the Width and Height boxes - divide it by two. From the details that you provided, I guess the radius is 102.55. And the final stroke dash array is:

StrokeDashArray="1,2.58"

For your first point, the answer is: it depends. If your chip is the same throughout the life-time of the application - this is the best way. It gives you the slight curvature on the outside to make the "square" flush with the outer contour of the chip and it requires a one-time calculation in design time.

Even if you have different sizes for the chip, this might be the best way to implement the graphics for the chip. Provided, you can design it with fixed size and then sticking it into a ViewBox and it still looks good.

If there's a need for variable sizes and the view box route doesn't work - there's another way to implement it (because Silverlight fails when you bind to ActualWidth\ActualHeight properties) - with Borders that hold rectangles. But it opens a whole new can of worms, and this answer is long enough. :)

like image 152
XAMeLi Avatar answered Sep 22 '22 09:09

XAMeLi