路径未获得所需输出的 WPF 剪辑矩形
WPF clip rectangle with path not getting desired output
我正在为流体容器创建用户控件。参考这个posthttps://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>
与其设置 Path 的 RenderTransform
,不如设置 Path 的 Geometry Transform
属性。
现在可以通过第二个Path的RectangleGeometry中Rect的Y
值轻松调整水位的高度。
<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>
可以用 CombinedGeometry
轻松绘制水。有了这个,您可以选择绘制一个区域,其中有两个 Geometry
overlap/intersect。现在你可以画一个巨大的 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>
有了这个,你可以调整BeakerForm
的Angle
,Water-Level会自动适应。
编辑
烧杯的大小为 x=150 和 y=150(四舍五入)。当它旋转 45° 并且宽度为 sqrt(150^2 + 150^2) = ~215 时,它达到其最大宽度。由于我们将水位设置为 0,因此高度不受影响。因此我们需要一个矩形,它覆盖从 (150 - 215) = -65 到 150 (315) 和从 0 到 150(高度)的区域(红色),如下图所示:
然后我们可以用这些数字得到Rect="-65,0 315,150"
.
注:旋转中心在Beaker/Square的右上角,旋转方向为顺时针(cw)。
我正在为流体容器创建用户控件。参考这个posthttps://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>
与其设置 Path 的 RenderTransform
,不如设置 Path 的 Geometry Transform
属性。
现在可以通过第二个Path的RectangleGeometry中Rect的Y
值轻松调整水位的高度。
<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>
可以用 CombinedGeometry
轻松绘制水。有了这个,您可以选择绘制一个区域,其中有两个 Geometry
overlap/intersect。现在你可以画一个巨大的 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>
有了这个,你可以调整BeakerForm
的Angle
,Water-Level会自动适应。
编辑
烧杯的大小为 x=150 和 y=150(四舍五入)。当它旋转 45° 并且宽度为 sqrt(150^2 + 150^2) = ~215 时,它达到其最大宽度。由于我们将水位设置为 0,因此高度不受影响。因此我们需要一个矩形,它覆盖从 (150 - 215) = -65 到 150 (315) 和从 0 到 150(高度)的区域(红色),如下图所示:
然后我们可以用这些数字得到Rect="-65,0 315,150"
.
注:旋转中心在Beaker/Square的右上角,旋转方向为顺时针(cw)。