CircularGauge and OpacityMask

Gauge for WPF Forum

Posted 9 years ago by Patrick Vinson
Version: 10.1.0523
Avatar
Hello,

Just wanted to start off with saying that I did a quick search but didn't find much on my question so if I did overlook someone's post and this has already been answered then I apologize.

So, I'm looking to build a compass for a HUD I'm working on at work. With a little playing around with a CircularGauge and custom labels I was able to get the compass look I wanted very easily. (Seriously, you guys make building custom gauges so simple, thank you!).

Now, I was hoping to go for the look of having only the top part of the compass being shown so I figured why not use the OpacityMask with a horizontal gradient from black to transparent. I placed this masking at the CircularGauge level in XAML assuming all of its children would be affected and sure enough it worked.

The problem came when I wanted to start rotating the compass so that the top part (normally the default degree of 270) would be the current heading. Thinking about it some I placed a RenderTransform on just the CircularTickSet. Cause all I really wanted was the custom label ticks and major/minor ticks to rotate since I have no rim or background. The compass only shows the ticks and labels acting like a HUD overlay.

Doing this, I noticed that the OpacityMask placed all the way up at the top level was also rotating after everything was set up. Which is where my issue is.

I'd like to have this compass only show the top portion with some masking to give the effect of the compass fading off to the sides but very bold in the center where the current heading is.

So, is there anything special I have to do to keep the OpacityMask from rotating or is that when you rotate one of the children everyone rotates? I did apply a RenderTransformOrigin with a point of 0.5, 0.5 to keep it centered when rotating. Should the effect I'm going for be done any differently? Like maybe place a second control over the gauge and use it for an opacity mask?

    <gauge:CircularGauge BackgroundType="None" RimType="None">
      <gauge:CircularGauge.OpacityMask>
        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
          <GradientStop Color="Black" Offset="0" />
          <GradientStop Color="Transparent" Offset="0.199" />
        </LinearGradientBrush>
      </gauge:CircularGauge.OpacityMask>
      <gauge:CircularGauge.Items>
        <gauge:DigitalGauge Name="digitalHeading" Width="100" Height="40" CharacterCount="5" CharacterSpacing="2" CharacterType="DotMatrix5By7Ellipse" Y="-305px" BackgroundType="None" RimType="None" GlassType="None" Foreground="Lime" DimmedBrush="#00000000" />
      </gauge:CircularGauge.Items>
      <gauge:CircularScale BarExtent="5px" IsBarVisible="False" Radius="360px" StartAngle="270" Name="scaleHeading">
        <gauge:CircularTickSet Maximum="360">
          <gauge:CircularTickSet.Ticks>
            <gauge:CircularTickLabelCustom Text="N" TextOrientation="RotatedAdjusted" Value="0" Foreground="Red" FontFamily="Calibri" FontSize="20px" FontWeight="Bold" HasDropShadow="True" />
            <gauge:CircularTickLabelCustom FontFamily="Calibri" FontSize="20px" FontWeight="Bold" Foreground="Red" HasDropShadow="True" Text="NE" TextOrientation="RotatedAdjusted" Value="45" />
            <gauge:CircularTickLabelCustom Text="E" TextOrientation="RotatedAdjusted" Value="90" FontFamily="Calibri" FontSize="20px" FontWeight="Bold" Foreground="Red" HasDropShadow="True" />
            <gauge:CircularTickLabelCustom FontFamily="Calibri" FontSize="20px" FontWeight="Bold" Foreground="Red" HasDropShadow="True" Text="SE" TextOrientation="RotatedAdjusted" Value="135" />
            <gauge:CircularTickLabelCustom Text="S" TextOrientation="RotatedAdjusted" Value="180" Foreground="Red" FontFamily="Calibri" FontSize="20px" FontWeight="Bold" HasDropShadow="True" />
            <gauge:CircularTickLabelCustom FontFamily="Calibri" FontSize="20px" FontWeight="Bold" Foreground="Red" HasDropShadow="True" Text="SW" TextOrientation="RotatedAdjusted" Value="225" />
            <gauge:CircularTickLabelCustom FontFamily="Calibri" FontSize="20px" FontWeight="Bold" Text="W" TextOrientation="RotatedAdjusted" Value="270" Foreground="Red" />
            <gauge:CircularTickLabelCustom FontFamily="Calibri" FontSize="20px" FontWeight="Bold" Foreground="Red" HasDropShadow="True" Text="NW" TextOrientation="RotatedAdjusted" Value="315" />
            <gauge:CircularTickMarkMajor Background="Lime" ScalePlacement="Inside" TickMarkType="Diamond" ScaleOffset="5px" MajorInterval="45" />
            <gauge:CircularTickMarkMinor ScalePlacement="Inside" TickMarkType="Diamond" Background="Lime" ScaleOffset="8px" MinorInterval="2" MajorInterval="45" />
          </gauge:CircularTickSet.Ticks>
        </gauge:CircularTickSet>
      </gauge:CircularScale>
    </gauge:CircularGauge>

scaleHeading.Dispatcher.BeginInvoke(DispatcherPriority.Input, (Action)(() =>
{
  scaleHeading.RenderTransformOrigin = new Point(0.5, 0.5);
  scaleHeading.RenderTransform = new RotateTransform(tempData.BoatCompass.Heading);
}));
Hopefully I made it all clear on my issue. If not, I'll try to explain unclear areas a bit better if needed. Thank you all for your time.

[Modified at 10/11/2010 09:21 AM]

Comments (4)

Posted 9 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Patrick,

I tried your sample, but didn't see the OpacityMask rotate. If you are setting the OpacityMask on the CircularGauge, then it should not be affect by rotating any of it's children. If you can put together a small sample project that compiles and email it over to our support address then we can take a closer look.

You could also simply change the CircularScale.StartAngle to "rotate" it's elements. You have it at 270 by default, but if you change it to 90, then S would be at the top. Changing StartAngle has the benefit of correctly rendering the labels so they are oriented correct. If you use RotateTransform, then some labels may end up upside down (i.e. SW).


Actipro Software Support

Posted 9 years ago by Patrick Vinson
Avatar
Thank you for the quick response. I went ahead and sent out to support a test example showing what I get. It sort of pulsates but shows what I am getting over here.

I will say that your suggested solution of using the StartAngle over RenderTransform is smart. That "SW" is now sticking out like a sore thumb to me, hehe. The OpacityMask is behaving for me and all is good. I honestly don't know why I didn't think to use that from the beginning, I mean I was already using it but didn't think about it when wanting to rotate. Either way, thank you for the help!
Posted 9 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Patrick,

Thanks for the sample. This may actually be a bug in WPF. It seems like the opacity mask is being "applied" to some(?) of the child elements. Here is a report of a similar issue using a ScrollViewer (i.e. CircularGauge in our case) and a TextBlock (i.e. the scale/ticks): http://stackoverflow.com/questions/1901709/scrollviewer-edge-blur-effect-opacitymask-not-working-properly

When the opacity mask is applied to the child element, it's top/bottom get faded. Since you are rotating using render transform, the mask isn't "updated". By animating the StartAngle, you are changing what is rendered at the top of the scale, so the mask is reapplied.

But it does appear that the mask is updated sometimes when using render transform, so that may actually be another bug in WPF :-)


Actipro Software Support

Posted 9 years ago by Patrick Vinson
Avatar
Interesting...

At least I'm not the only one having similar issues! =D

I guess I just need to be a bit more careful on how I use OpacityMask for any element in the future. Again, thank you for your time on helping me out and looking into the issue. The StartAngle solution is working like a charm.
The latest build of this product (v2019.1 build 0681) was released 12 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.