Question

I'm currently creating a PDF viewer of sorts that, if the user moves their cursor over one of a number of areas of interest on the current slide (defined in an external file), the rest of the slide will darken, highlighting that area.

Currently, these areas of interest are Path shapes, created with the Geometry.Parse() method using the information provided in the external file and stored in a List<List<Path>>.

The current XAML for this shading is as follows:

    <Image Name="SlideImage" HorizontalAlignment="Left" VerticalAlignment="Top">
        <Image.OpacityMask>
            <DrawingBrush Opacity="0.4">
                <DrawingBrush.Drawing>
                    <GeometryDrawing x:Name="ShadeGeometry">
                        <GeometryDrawing.Brush>
                            <RadialGradientBrush>
                                <RadialGradientBrush.GradientStops>
                                    <GradientStop Offset="0" Color="Transparent"/>
                                    <GradientStop Offset="1" Color="Black"/>
                                </RadialGradientBrush.GradientStops>
                            </RadialGradientBrush>
                        </GeometryDrawing.Brush>
                        <GeometryDrawing.Pen>
                            <Pen Thickness="0.1" Brush="Black"/>
                        </GeometryDrawing.Pen>
                    </GeometryDrawing>
                </DrawingBrush.Drawing>
            </DrawingBrush>
        </Image.OpacityMask>
 <Image>

The Geometry of the Drawing is altered with the following method:

public void ShadeCommand(ref GeometryDrawing ShadeGeometry, int page, int shape)
{
    if (page < commands.Count && shape < commands[page].Count)
    {
        ShadeGeometry.Geometry = Geometry.Parse(
            "M 0,0 " + "H " + resolution.X + " V " + resolution.Y +
            " H 0 V 0 L " + commands[page][shape].Substring(2) + " Z");
    }
    else
    {
        ShadeGeometry.Geometry = null;  //Geometry.Empty
    }
}

This draws a shape which goes around the image area, then the given shape before returning to the starting point.

The problem with this approach is that it creates very strange looking shapes, and the gradient of the opacity mask seems to whiten an area instead of darkening the rest.

I'm not too concerned about a gradual shift from darkness into the shape, as long as I can find a solution that will darken the area around a shape but still show the slide underneath, I'll come away happy. Thanks in advance.

Was it helpful?

Solution

It might be easier to overlay the Image with a semi-transparent black Path element that uses a CombinedGeometry consisting of a large enough RectangleGeometry and an excluded PathGeometry.

Like this:

<Grid>
    <Image Source="C:\Users\Public\Pictures\Sample Pictures\Koala.jpg" Stretch="None"/>
    <Path Fill="Black" Opacity="0.5"> 
        <Path.Data>
            <CombinedGeometry GeometryCombineMode="Exclude">
                <CombinedGeometry.Geometry1>
                    <RectangleGeometry Rect="0,0,10000,10000"/>
                </CombinedGeometry.Geometry1>
                <CombinedGeometry.Geometry2>
                    <PathGeometry Figures="M 280,375 l100,-50 100,50 -100,50z"/>
                </CombinedGeometry.Geometry2>
            </CombinedGeometry>
        </Path.Data>
    </Path>
</Grid>

You might now programatically adjust the PathGeometry (or perhaps StreamGeometry) in CombinedGeometry.Geometry2.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top