在椭圆内剪切和缩放图像(不是椭圆本身)

时间:2017-01-28 12:36:11

标签: c# xaml windows-runtime uwp windows-10-universal

我试图找到一种方法来剪切带有椭圆的图像,以便如果我缩放图像,我保持椭圆完整,但到目前为止,我已经有了没有运气。

这是我的XAML:

<Grid>
  <Grid.Clip>
    <RectangleGeometry x:Name="ClippingRectangle"
                       Rect="0,0,200,200"/>
  </Grid.Clip>
  <Ellipse Stretch="UniformToFill"
           x:Name="ImageEllipse"
           SizeChanged="ImageEllipse_OnSizeChanged">
    <Ellipse.Fill>
      <ImageBrush ImageSource="{x:Bind ViewModel.SomePath}>
    </Ellipse.Fill>
  </Ellipse>
</Grid>

我使用SizeChanged事件来更新剪裁矩形的大小。 问题在于外部GridEllipse与其图像一起剪切,因此结果是带有裁剪边的缩放圆。 相反,我想只是缩放里面的椭圆。

问题是Ellipse控件是一个形状,因此我无法在其中添加实际的Image控件,而是对其进行缩放。 有没有办法实际执行此操作,或者由于Microsoft决定将剪切属性限制为仅RectangleGeometry个对象,因此无法执行此操作?

使用Border时同样的问题,因为CornerRadius属性仅适用于其背景,并且实际上并未剪切其内容。

谢谢!

编辑#1 - 根据要求,这是我在缩放Ellipse时得到的结果: enter image description here

编辑#2 - 我已尝试动画ImageBrush这样的动画:

<ImageBrush.Transform>
  <ScaleTransform x:Name="AvatarTransform"
                  CenterY="0.5"
                  CenterX="0.5"/>
  </ImageBrush.Transform>
</ImageBrush.Transform>

然后:

<Storyboard x:Name="TestAnimation">
  <DoubleAnimation Storyboard.TargetName="AvatarTransform"
                   Storyboard.TargetProperty="ScaleY"
                   To="1.2" Duration="0:0:1"/>
</Storyboard>

但由于某些原因似乎没有发生任何事情,我甚至不确定它是否真的可以为Transform的{​​{1}}属性制作动画,因为它已经 Brush对象

编辑#3 - 这是我想用动画实现的一个例子: enter image description here

编辑#4 - 从两个答案中,我试图再次为UIElement属性设置动画:

ImageBrush.Translate

但它仍然无法运作。另外,通过这种方法,我无法设置<!--Image XAML--> <ImageBrush Stretch="Fill" ImageSource="/SomeImage.jpg"> <ImageBrush.Transform> <CompositeTransform x:Name="MyTransform"/> </ImageBrush.Transform> </ImageBrush> <!--Image storyboard--> <Storyboard x:Name="ScaleStory"> <DoubleAnimation Storyboard.TargetName="MyTransform" Storyboard.TargetProperty="ScaleX" From="1" To="1.4" Duration="0:0:1"/> </Storyboard> 属性,因为我没有RenerTransformOrigin可以使用,所以即使动画确实有效,图像也会缩放到右边和底部,这不是预期的结果。

编辑#4&gt;&gt;已解决! - 如标记为有效的答案所示,这是我的代码:

UIElement

事实证明它也适用于<Ellipse Stretch="UniformToFill" x:Name="ImageEllipse"> <Ellipse.Fill> <ImageBrush ImageSource="/SomePath/SomeImage.jpg"> <ImageBrush.RelativeTransform> <CompositeTransform CenterY="0.5" CenterX="0.5"/> </ImageBrush.RelativeTransform> </ImageBrush> </Ellipse.Fill> </Ellipse> 属性,所以我没有必要切换到Ellipse.Fill来创建剪辑图像的圆圈。

2 个答案:

答案 0 :(得分:0)

您可以将剪辑编辑为PathGeometry而不是RectangleGeometry,剪辑将起作用。这是一个可以放大和缩小并保持在剪裁区域内的图像示例。玩这个直到它适合你。

    <Grid Width="1000"
          Height="1000">
    <Grid HorizontalAlignment="Center"
          VerticalAlignment="Center"
          Width="500"
          Height="500">
        <Grid.Clip>
            <PathGeometry>
                <PathFigure IsClosed="True"
                            StartPoint="0, 250">
                    <ArcSegment Size="1, 1"
                                Point="500, 250"
                                SweepDirection="Counterclockwise"
                                IsLargeArc="True" />
                    <ArcSegment Size="1, 1"
                                Point="0, 250"
                                SweepDirection="Counterclockwise"
                                IsLargeArc="True" />
                </PathFigure>
            </PathGeometry>
        </Grid.Clip>

        <Image Source="12019035.jpg"
               RenderTransformOrigin="0.5,0.5">
            <Image.RenderTransform>
                <TransformGroup>
                    <ScaleTransform ScaleX="1.2"
                                    ScaleY="1.2" />
                    <SkewTransform />
                    <RotateTransform />
                    <TranslateTransform />
                </TransformGroup>
            </Image.RenderTransform>
        </Image>

    </Grid>
</Grid>

我只是在网格中放置一个网格,以便这个示例的大小正确。

我剪切了内部网格,使其成为使用路径的完美椭圆。您可以随意复制该细分,并根据需要使用它。您只需要调整大小等以匹配您自己的视图。

为了在此示例中放大和缩小图像,您需要设置动画或直接操作图像上的ScaleTransform Scale.X和Scale.Y属性,其中值为double,1为100%,1.5 150%等等。

如果您不确定如何使用路径,我可能会解释,但有一些例子。它基本上是PathFigure对象的起始点,PathFigure中每个段上的点是您希望遇到的下一个点。在这里,我从0,250开始并绘制一个弧到点500,250。然后我绘制另一个弧到0,250完成椭圆。它适用于这些数字,因为网格宽度/高度为500,500。

关于这个很酷的事情是你可以用你想要的任何图案绘制形状或剪辑任何UIElement :)它可能是一个星星,或者一些疯狂的其他形状。这就是你正在寻找的东西,但它有一些乐趣!

答案 1 :(得分:0)

我用来执行此操作的动画:将这些资源放在您的页面(XAML端)

 <Page.Resources>
    <Storyboard x:Name="StoryboardZoomIn">
        <DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
                                       Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(CompositeTransform.ScaleX)"
                                       Storyboard.TargetName="path">
            <EasingDoubleKeyFrame KeyTime="0:0:1"
                                  Value="1.5">
                <EasingDoubleKeyFrame.EasingFunction>
                    <CubicEase EasingMode="EaseIn" />
                </EasingDoubleKeyFrame.EasingFunction>
            </EasingDoubleKeyFrame>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
                                       Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(CompositeTransform.ScaleY)"
                                       Storyboard.TargetName="path">
            <EasingDoubleKeyFrame KeyTime="0:0:1"
                                  Value="1.5">
                <EasingDoubleKeyFrame.EasingFunction>
                    <CubicEase EasingMode="EaseIn" />
                </EasingDoubleKeyFrame.EasingFunction>
            </EasingDoubleKeyFrame>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
    <Storyboard x:Name="StoryboardZoomOut">
        <DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
                                       Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(CompositeTransform.ScaleX)"
                                       Storyboard.TargetName="path">
            <EasingDoubleKeyFrame KeyTime="0:0:1"
                                  Value="1">
                <EasingDoubleKeyFrame.EasingFunction>
                    <CubicEase EasingMode="EaseIn" />
                </EasingDoubleKeyFrame.EasingFunction>
            </EasingDoubleKeyFrame>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
                                       Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(CompositeTransform.ScaleY)"
                                       Storyboard.TargetName="path">
            <EasingDoubleKeyFrame KeyTime="0:0:1"
                                  Value="1">
                <EasingDoubleKeyFrame.EasingFunction>
                    <CubicEase EasingMode="EaseIn" />
                </EasingDoubleKeyFrame.EasingFunction>
            </EasingDoubleKeyFrame>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</Page.Resources>

现在,这是视图的其余部分。它是一个网格,两个按钮,画布和路径。

   <Grid Width="1000"
      Height="1000">
    <StackPanel>

        <Button Content="Zoom In" Click="ButtonZoomIn_Click" />
        <Button Content="Zoom Out" Click="ButtonZoomOut_Click"/>

    </StackPanel>

    <Canvas HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Width="500"
            Height="500"
            Grid.RowSpan="2">

        <Path x:Name="path">
            <Path.Fill>
                <ImageBrush Stretch="Fill"
                            ImageSource="12019035.jpg">
                    <ImageBrush.RelativeTransform>
                        <CompositeTransform CenterY="0.5"
                                            CenterX="0.5"
                                            ScaleX="1.5"
                                            ScaleY="1.5" />
                    </ImageBrush.RelativeTransform>
                </ImageBrush>
            </Path.Fill>
            <Path.Data>
                <PathGeometry>
                    <PathFigure IsClosed="True"
                                StartPoint="0, 250">
                        <ArcSegment Size="1, 1"
                                    Point="500, 250"
                                    SweepDirection="Counterclockwise"
                                    IsLargeArc="True" />
                        <ArcSegment Size="1, 1"
                                    Point="0, 250"
                                    SweepDirection="Counterclockwise"
                                    IsLargeArc="True" />
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
        </Path>

    </Canvas>
</Grid>

现在在后面的代码中(我讨厌代码并推荐MVVM)......

 private void ButtonZoomIn_Click(object sender, RoutedEventArgs e)
     => (Resources["StoryboardZoomIn"] as Storyboard)?.Begin();

 private void ButtonZoomOut_Click(object sender, RoutedEventArgs e)
     => (Resources["StoryboardZoomOut"] as Storyboard)?.Begin();

这将为图像设置动画,从图像中心点开始剪切在椭圆内。希望这会有所帮助:)