Opacity mask ignores ClipToBounds True

I have a "canvas mask" that I can use as the OpacityMask source of my main canvas.

Both of my canvases are the same size, but I get unexpected results when I start painting near the border of the canvas.

Ive created a gif to illustrate my problem: enter image description here

In gif, I first painted a mask (in black). Then on another canvas with the OpacityMask attached to the mask canvas, I started painting with the grass texture. It works great if I paint on the canvas, but if I get close to the border of the canvas, it translates and scales the painting.

I think that when I get closer to the edge, the canvas of the painting changes, which distorts the image. How do I get around this, I set ClipToBounds = "True" for both canvases. How do I keep the canvas mask proportional to the painting canvas?

Edit . Here is the code for the two canvases. Canvas mask:

<ItemsControl Name="maskDataBinding" Background="Transparent" Panel.ZIndex="-1" ClipToBounds="True" Height="512" Width="512" HorizontalAlignment="Center" VerticalAlignment="Center">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas Background="Transparent"  
                        Height="512" 
                        Width="512" 
                        HorizontalAlignment="Center" 
                        VerticalAlignment="Center"
                        ClipToBounds="True">
                </Canvas>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>

        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Image Source="{Binding Name}"
                            Width="{Binding Width}"
                            Height="{Binding Height}"
                            Opacity="{Binding Opacity}">
                    <Image.RenderTransform>
                        <TransformGroup>
                            <TranslateTransform X="{Binding OffsetX}" Y="{Binding OffsetY}"/>
                            <RotateTransform CenterX="{Binding CenterX}" CenterY="{Binding CenterY}" Angle="{Binding Angle}"/>
                        </TransformGroup>
                    </Image.RenderTransform>
                </Image>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

      

Picture:

<!--Outer collection-->
<ItemsControl Name="canvasDataBinding"
            Focusable="True"
            HorizontalAlignment="Center" 
            Height="512"
            Width="512" 
            VerticalAlignment="Center" 
            ClipToBounds="True">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas MouseMove="Canvas_MouseMove"
                    MouseEnter="Canvas_MouseEnter"
                    MouseLeave="Canvas_MouseLeave"
                    MouseDown="Canvas_MouseDown"
                    MouseUp="Canvas_MouseUp"
                    Background="Transparent"
                    ClipToBounds="True">

            </Canvas>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>

            <!--nested collection-->
            <ItemsControl Height="512" Width="512" HorizontalAlignment="Center" VerticalAlignment="Center" ItemsSource="{Binding ImageSource}" ClipToBounds="True">

                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas Background="Transparent"  
                                Height="512" 
                                Width="512" 
                                HorizontalAlignment="Center" 
                                VerticalAlignment="Center"
                                ClipToBounds="True">
                            <Canvas.OpacityMask>
                                <VisualBrush Visual="{Binding ElementName=maskDataBinding}"/>
                            </Canvas.OpacityMask>
                        </Canvas>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>

                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Image Source="{Binding Name}"
                        Width="{Binding Width}"
                        Height="{Binding Height}"
                        Opacity="{Binding Opacity}">
                            <Image.RenderTransform>
                                <TransformGroup>
                                    <TranslateTransform X="{Binding OffsetX}" Y="{Binding OffsetY}"/>
                                    <RotateTransform CenterX="{Binding CenterX}" CenterY="{Binding CenterY}" Angle="{Binding Angle}"/>
                                </TransformGroup>
                            </Image.RenderTransform>
                        </Image>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>

        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

      

My painting canvas is really just a collection of canvases (each canvas to simulate a layer). And each canvas has a collection of images. You can see that I am binding the OpacityMask inside the nested collection canvas.

Edit : So my guess is correct. It crosses the image as I get closer to the border because the canvas of the painting grows in width (if you get closer to the left / right edge) and grows in height (if you get closer to the top / bottom edges), so the mask stretches. Any ideas for a solution / workaround?

Here's another gif. I removed the opacity mask, so now I just paint on the canvas. I also set ClipToBounds = False to my canvas. An opacity mask is applied on this unfixed canvas, regardless of whether ClipToBounds is false or true.
enter image description here

+3


source to share


1 answer


I understood that. I just needed to apply OpacityMask to any canvas parent. OpacityMask sees everything on the canvas, even outside the bounds (ClipToBounds set to True or False doesn't matter). The parent of the Canvas (in my case the actual ItemsControl) gets rid of any information outside the Canvas, so using a mask on the parent works.



<!--nested collection-->
<ItemsControl Height="512" Width="512" HorizontalAlignment="Center" VerticalAlignment="Center" ItemsSource="{Binding ImageSource}" >

    <ItemsControl.ItemsPanel>

        <ItemsPanelTemplate>

            <Canvas Name="paintingCanvas"
                    Background="Transparent"  
                    Height="512" 
                    Width="512" 
                    HorizontalAlignment="Center" 
                    VerticalAlignment="Center"
                    ClipToBounds="True">
            </Canvas>
        </ItemsPanelTemplate>

    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Image Source="{Binding Name}"
        Width="{Binding Width}"
        Height="{Binding Height}"
        Opacity="{Binding Opacity}">
                <Image.RenderTransform>
                    <TransformGroup>
                        <TranslateTransform X="{Binding OffsetX}" Y="{Binding OffsetY}"/>
                        <RotateTransform CenterX="{Binding CenterX}" CenterY="{Binding CenterY}" Angle="{Binding Angle}"/>
                    </TransformGroup>
                </Image.RenderTransform>
            </Image>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.OpacityMask>
        <VisualBrush Visual="{Binding ElementName=maskDataBinding}"/>
    </ItemsControl.OpacityMask>
</ItemsControl>

      

0


source







All Articles