Прямоугольник клипа WPF с путем, не получающим желаемый вывод - PullRequest
0 голосов
/ 13 марта 2019

Я создаю пользовательский элемент управления для контейнера с жидкостью. со ссылкой на этот пост https://pptcrafter.wordpress.com/2014/05/14/animation-liquids-filling-bubbling-etc/. Я использую прямоугольник для жидкости (вода) и путь для контейнера (стакан здесь). Я хочу обрезать водяной прямоугольник таким образом, чтобы он отображался только в контейнере. Я попытался обрезать, используя геометрию пути, а также использовал маску непрозрачности. Но не получить желаемый результат. Я думаю, что что-то упустил. Пожалуйста, помогите мне найти это.
Желаемый вывод: _________________________________________________________________________
Без отсечения:
_________________________________________________________________________

Клип, используя путь:

_________________________________________________________________________

Использование маски непрозрачности:
_________________________________________________________________________


<UserControl
x:Class="FluidFill.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FluidFill"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300">
<UserControl.Resources>
    <PathFigureCollection
        x:Key="fig">M0,0 L10,10 V135 A10,10 0 0 0 20,145 H 130 A10,10 0 0 0 140,135 V5 L145,0 Z</PathFigureCollection>
</UserControl.Resources>
<Grid
    Background="White">

        <Path Panel.ZIndex="1" RenderTransformOrigin="0.5,0.5"
            x:Name="ActualContainer"
            Stroke="Black"
            Fill="Transparent"
            StrokeThickness="2"
            Data="M0,0 L10,10 V135 A10,10 0 0 0 20,145 H 130 A10,10 0 0 0 140,135 V5 L145,0 Z"
            >
            <!--<Path.Effect>
                <DropShadowEffect
                    Color="#FF3C494B"
                    ShadowDepth="3"
                    Opacity="0.6" />
            </Path.Effect>-->
            <Path.RenderTransform>
            <TransformGroup>
                <TranslateTransform
                    X="50"
                    Y="30" />
                <RotateTransform
                    Angle="20" />
            </TransformGroup>
        </Path.RenderTransform>
        </Path>

    <Rectangle x:Name="Wtr"
        Height="200"
        Width="375"
        Fill="#4F81BD" Margin="0,52.5,0,47.5">
        <!--<Rectangle.Clip>
            <PathGeometry Transform="{Binding ElementName=ActualContainer,Path=RenderTransform}" Figures="{StaticResource fig}">                  
            </PathGeometry>
        </Rectangle.Clip>-->
        <!--<Rectangle.OpacityMask>
            <VisualBrush
                TileMode="Tile"
                Stretch="None">
                <VisualBrush.Visual>
                    <Grid
                        x:Name="waveGrid">

                        <Path  RenderTransform="{Binding ElementName=ActualContainer,Path=RenderTransform}"
                            Fill="#FF82C6FF"
                            Data="M0,0 L10,10 V135 A10,10 0 0 0 20,145 H 130 A10,10 0 0 0 140,135 V5 L145,0 Z"
                            />                            
                    </Grid>
                </VisualBrush.Visual>

            </VisualBrush>

        </Rectangle.OpacityMask>-->
    </Rectangle>


</Grid>

Ответы [ 2 ]

1 голос
/ 13 марта 2019

Вода может быть легко взята с CombinedGeometry. При этом у вас есть возможность нарисовать область, где два Geometry перекрываются / пересекаются. Теперь вы можете нарисовать огромный Rectangle в качестве уровня воды + стакан, и получившаяся область будет вашим желаемым результатом.

XAML:

<UserControl.Resources>
    <!-- Form of the Beaker with Rotation -->
    <PathGeometry x:Key="BeakerForm" Figures="M0,0 L10,10 V135 A10,10 0 0 0 20,145 H 130 A10,10 0 0 0 140,135 V5 L145,0 Z">
        <PathGeometry.Transform>
            <!-- Angle of the Beaker Rotation (Note: CenterX must be the highest X-Coordinate of the Figures-Data) -->
            <RotateTransform Angle="10" CenterX="145"/>
        </PathGeometry.Transform>
    </PathGeometry>
</UserControl.Resources>

<!-- Canvas to draw the Beaker -->
<Canvas Background="White" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="100,100">
    <!-- Beaker Fill-Water -->
    <Path Fill="#4F81BD" RenderTransformOrigin="1,0">
        <Path.Data>
            <!-- A Rectangle and a Beaker wil be drawn and the blue areais only 
                 visible where theese two figures intersect (overlap) -->
            <CombinedGeometry GeometryCombineMode="Intersect">
                <CombinedGeometry.Geometry1>
                    <StaticResource ResourceKey="BeakerForm"/>
                </CombinedGeometry.Geometry1>
                <CombinedGeometry.Geometry2>
                    <RectangleGeometry Rect="-65,0 315,150" />
                </CombinedGeometry.Geometry2>
            </CombinedGeometry>
        </Path.Data>
    </Path>

    <!-- Beaker line in the foreground -->
    <Path RenderTransformOrigin="1,0" Stroke="Black" Fill="Transparent" StrokeThickness="2" Data="{StaticResource BeakerForm}"/>
</Canvas>

С этим вы можете настроить Angle из BeakerForm, и уровень воды адаптируется к нему.

enter image description here

Редактировать

Стакан имеет размер х = 150 и у = 150 (округлено). Он достигает максимальной ширины, когда он поворачивается на 45 ° и имеет квадратную ширину (150 ^ 2 + 150 ^ 2) = ~ 215 по ширине. На высоту это не влияет, потому что мы установили уровень воды на 0. Таким образом, нам нужен прямоугольник, который покрывает область (красный) от (150 - 215) = от -65 до 150 (315) и от 0 до 150 (высота), как показано ниже :

enter image description here

Тогда мы можем использовать эти числа и получить Rect="-65,0 315,150".

Примечание. Центр вращения находится в верхнем правом углу мензурки / квадрата и вращается по часовой стрелке (непрерывно).

1 голос
/ 13 марта 2019

Вместо установки контура RenderTransform лучше установить свойство Transform геометрии контура.

Теперь вы можете легко отрегулировать высоту уровня воды с помощью значения Y объекта Rect в RectangleGeometry второго пути.

<Grid Background="White">
    <Path x:Name="ActualContainer" Panel.ZIndex="1" Stroke="Black" StrokeThickness="2">
        <Path.Data>
            <PathGeometry Figures="M0,0 L10,10 V135 A10,10 0 0 0 20,145 H 130 A10,10 0 0 0 140,135 V5 L145,0 Z">
                <PathGeometry.Transform>
                    <TransformGroup>
                        <TranslateTransform X="50" Y="30"/>
                        <RotateTransform Angle="20"/>
                    </TransformGroup>
                </PathGeometry.Transform>
            </PathGeometry>
        </Path.Data>
    </Path>

    <Path Data="{Binding Data, ElementName=ActualContainer}" Fill="#4F81BD">
        <Path.Clip>
            <RectangleGeometry Rect="0,125,200,200"/>
        </Path.Clip>
    </Path>
</Grid>
...