Геометрия геометрии кликов в WinRT

Сегодня я начал портировать образец очереди страницы, созданный здесь для Windows Phone 7 для WinRT (XAML, С#) для помощи этот задан в Stack Overflow. Но во время портирования я застрял с отсечением части страницы. В образце телефона Windows они используют клики Path Geometry для обрезки страницы. Но в WinRT Кажется, только геометрия прямоугольника поддерживает опцию отсечения.

Как добиться такой же функциональности, как отсечение геометрии траектории в WinRT?

Вы можете скачать код телефона с образцами из здесь

Пожалуйста, найдите Исходный код я Tried загрузите

В этом разделе найдите класс PageTurn.cs, я прокомментировал код с вопросами, в:

void left_PointerEntered(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
    //_workingOdd.Clip = _oddClipRegion;       
    //_workingEven.Clip = _evenClipRegion;
}

Ответ 1

Я немного опоздал, чтобы дать более полный ответ, но я получил вдохновение и начал работать над переходом на управление/переходом страницы. Текущий прототип отлично работает с RenderTransforms и Clip Transforms для приятной поддержки независимой анимации.

enter image description here

Я буду работать над этим многоразовым элементом управления для WinRT XAML Toolkit, но пока вы можете проверить этот код:

XAML

<Page
    x:Class="FlipControls.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:FlipControls"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid
        x:Name="ManipulationGrid"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
        ManipulationMode="TranslateX,TranslateY,TranslateInertia"
        ManipulationStarted="ManipulationGrid_OnManipulationStarted"
        ManipulationDelta="ManipulationGrid_OnManipulationDelta"
        ManipulationCompleted="ManipulationGrid_OnManipulationCompleted">
        <Grid
            x:Name="Page1">
            <Grid.Clip>
                <RectangleGeometry
                    Rect="0,0,80000,80000">
                    <RectangleGeometry.Transform>
                        <TransformGroup>
                            <TranslateTransform
                                x:Name="Page1ClipTranslateTransform" />
                            <RotateTransform
                                x:Name="Page1ClipRotateTransform" />
                        </TransformGroup>
                    </RectangleGeometry.Transform>
                </RectangleGeometry>
            </Grid.Clip>
            <Grid
                x:Name="Page1ContentGrid">
                <Image
                    VerticalAlignment="Stretch"
                    HorizontalAlignment="Stretch"
                    Stretch="UniformToFill"
                    Source="http://bigbackground.com/wp-content/uploads/2013/07/tropical-beach-screensaver.jpg" />
            </Grid>
        </Grid>
        <Grid
            x:Name="Page2"
            Opacity="0">
            <Grid.Clip>
                <RectangleGeometry
                    Rect="0,0,80000,80000">
                    <RectangleGeometry.Transform>
                        <TransformGroup>
                            <TranslateTransform
                                x:Name="Page2ClipTranslateTransform" />
                            <RotateTransform
                                x:Name="Page2ClipRotateTransform" />
                        </TransformGroup>
                    </RectangleGeometry.Transform>
                </RectangleGeometry>
            </Grid.Clip>
            <Grid
                x:Name="Page2ContentGrid">
                <Image
                    x:Name="Page2SampleContentImage"
                    VerticalAlignment="Stretch"
                    HorizontalAlignment="Stretch"
                    Stretch="UniformToFill"
                    Source="http://www.photography-match.com/views/images/gallery/Tropical_Lagoon.jpg" />
            </Grid>
        </Grid>
        <Grid
            x:Name="TransitionGridContainer">
            <Grid
                x:Name="TransitionGrid"
                Opacity="0">
                <Grid.RenderTransform>
                    <CompositeTransform
                        x:Name="TransitionGridContainerTransform" />
                </Grid.RenderTransform>
                <Grid.Clip>
                    <RectangleGeometry
                        Rect="0,0,80000,80000">
                        <RectangleGeometry.Transform>
                            <TransformGroup>
                                <TranslateTransform
                                    x:Name="TransitionGridClipTranslateTransform" />
                                <RotateTransform
                                    x:Name="TransitionGridClipRotateTransform" />
                            </TransformGroup>
                        </RectangleGeometry.Transform>
                    </RectangleGeometry>
                </Grid.Clip>
                <Image
                    x:Name="TransitionImage"
                    Stretch="None" />
            </Grid>
        </Grid>
    </Grid>
</Page>

С#

using System;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Media.Imaging;

namespace FlipControls
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            PreloadTransitionGridContentAsync();
        }

        private async Task PreloadTransitionGridContentAsync()
        {
            #region Waiting for page 2 content to load
            var bi = Page2SampleContentImage.Source as BitmapImage;

            if (bi.PixelWidth == 0)
            {
                bi.ImageFailed += (s, e) => new MessageDialog("Need a different sample image.").ShowAsync();
                bi.ImageOpened += (s, e) => PreloadTransitionGridContentAsync();
                return;
            }

            if (Page2ContentGrid.ActualWidth == 0)
            {
                SizeChangedEventHandler sizeChangedEventHandler = null;
                sizeChangedEventHandler = (s, e) =>
                {
                    PreloadTransitionGridContentAsync();
                    Page2ContentGrid.SizeChanged -= sizeChangedEventHandler;
                };

                Page2ContentGrid.SizeChanged += sizeChangedEventHandler;

                return;
            } 
            #endregion

            var rtb = new RenderTargetBitmap();
            await rtb.RenderAsync(Page2ContentGrid);
            TransitionImage.Source = rtb;
            await Task.Delay(40000);
        }

        private bool isCancellationRequested;

        private enum FlipDirections
        {
            Left,
            Right
        }

        private FlipDirections flipDirection;
        private Point manipulationStartPosition;
        private double rotationCenterX;
        private double rotationCenterY;

        private void ManipulationGrid_OnManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
        {
            if (TransitionImage.Source == null)
            {
                CancelManipulation(e);
                return;
            }

            manipulationStartPosition = e.Position;

            if (Page1.Opacity == 1)
            {
                flipDirection = FlipDirections.Left;
                Page2ClipTranslateTransform.X = ManipulationGrid.ActualWidth;
                Page2.Opacity = 1;
                TransitionGridClipTranslateTransform.X = -80000;
                TransitionGridContainerTransform.TranslateX = ManipulationGrid.ActualWidth;
                TransitionGrid.Opacity = .975;
            }
            else
            {
                if (manipulationStartPosition.X >= this.ManipulationGrid.ActualWidth / 2)
                {
                    // Can't flip left since there is no page after the current one
                    CancelManipulation(e);
                    return;
                }

                flipDirection = FlipDirections.Right;

                Page1.Opacity = 1;
            }
        }

        private void ManipulationGrid_OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            if (this.isCancellationRequested)
            {
                return;
            }

            if (flipDirection == FlipDirections.Left)
            {
                var w = this.ManipulationGrid.ActualWidth;
                var h = this.ManipulationGrid.ActualHeight;

                var cx = Math.Min(0, Math.Max(e.Position.X - w, -w));
                var cy = e.Cumulative.Translation.Y;
                var angle = (Math.Atan2(cx + manipulationStartPosition.Y - w, -cy) * 180 / Math.PI + +90) % 360;

                this.rotationCenterX = w + cx / 2;

                if (cy < 0)
                {
                    this.rotationCenterY = h;
                }
                else
                {
                    this.rotationCenterY = 0;
                }

                Page2ClipTranslateTransform.X = w + cx / 2;
                Page2ClipTranslateTransform.Y = -40000 + h / 2;
                Page2ClipRotateTransform.CenterX = this.rotationCenterX;
                Page2ClipRotateTransform.CenterY = this.rotationCenterY;
                Page2ClipRotateTransform.Angle = angle;

                TransitionGridClipTranslateTransform.X = -80000 - (cx / 2);
                TransitionGridClipTranslateTransform.Y = -40000 + h / 2;
                TransitionGridClipRotateTransform.CenterX = -cx / 2;
                TransitionGridClipRotateTransform.CenterY = this.rotationCenterY;
                TransitionGridClipRotateTransform.Angle = -angle;

                TransitionGridContainerTransform.TranslateX = w + cx;
                TransitionGridContainerTransform.CenterX = -cx / 2;
                TransitionGridContainerTransform.CenterY = this.rotationCenterY;
                TransitionGridContainerTransform.Rotation = 2 * angle;
            }
        }

        private void ManipulationGrid_OnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            if (this.isCancellationRequested)
            {
                this.isCancellationRequested = false;
                return;
            }

            var w = this.ManipulationGrid.ActualWidth;
            var h = this.ManipulationGrid.ActualHeight;

            var sb = new Storyboard();
            AddAnimation(sb, Page2ClipTranslateTransform, "X", w / 2);
            AddAnimation(sb, Page2ClipRotateTransform, "CenterX", w / 2);
            AddAnimation(sb, Page2ClipRotateTransform, "Angle", 0);

            AddAnimation(sb, TransitionGridClipTranslateTransform, "X", -80000 + (w / 2));
            AddAnimation(sb, TransitionGridClipRotateTransform, "CenterX", w / 2);
            AddAnimation(sb, TransitionGridClipRotateTransform, "Angle", 0);

            AddAnimation(sb, TransitionGridContainerTransform, "TranslateX", 0);
            AddAnimation(sb, TransitionGridContainerTransform, "CenterX", w / 2);
            AddAnimation(sb, TransitionGridContainerTransform, "Rotation", 0);
            sb.Begin();
        }

        private static void AddAnimation(Storyboard sb, DependencyObject dob, string path, double to)
        {
            var da = new DoubleAnimation();
            Storyboard.SetTarget(da, dob);
            Storyboard.SetTargetProperty(da, path);
            da.To = to;
            da.Duration = TimeSpan.FromSeconds(.2);
            sb.Children.Add(da);
        }

        private void CancelManipulation(ManipulationStartedRoutedEventArgs e)
        {
            this.isCancellationRequested = true;
            e.Complete();
        }
    }
}

Ответ 2

Надеюсь, это поможет вам.

Вот XAML, чтобы получить именно тот вид, с которым вы связались:

Расчет траектории enter image description here

Изображение1

 <Grid Background="Black">
    <Grid Height="145" Width="210" >
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Border Margin="-3" BorderThickness="3" BorderBrush="White" Grid.ColumnSpan="2"></Border>
        <Image Grid.Column="0" Source="Images/1.jpg"></Image>
        <Image Grid.Column="1" Source="Images/2.jpg" ></Image>
        <Image Grid.Column="1" HorizontalAlignment="Left"  Source="Images/8.jpg" >
            <Image.Clip>
                <RectangleGeometry Rect="0,0,49,150"></RectangleGeometry>
            </Image.Clip>
        </Image>
        <Path Grid.ColumnSpan="2"  Data="M 180,0 L 153,145 L 85 120 L 160,-12"   >
            <Path.Fill>
                <ImageBrush ImageSource="Images/4.jpg"/>
            </Path.Fill>
        </Path>
        <!--polyline used for path image border-->
        <Polyline Points="180,0,160,-11,85,120,153,145" Margin="0,-2,0,0"  Stroke="White" StrokeThickness="3"  Grid.ColumnSpan="2"/>
    </Grid>
</Grid>

Image2

    <Grid Background="Black">
    <Grid Width="290" Height="180" >
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Border Grid.Column="0"  BorderThickness="2,0,0,0" BorderBrush="White">
            <Image Stretch="Fill"  Source="Images/4.jpg"></Image>
        </Border>
        <Image Grid.Column="1" Source="Images/3.jpg" ></Image>
        <Path Grid.ColumnSpan="2"  Data="M 200,0 L 170,180 L 82.5 160 L 130 0 "   >
            <Path.Fill>
                <ImageBrush ImageSource="Images/6.jpg"/>
            </Path.Fill>
        </Path>
        <!--polyline used for path image border-->
        <Polyline Points="130,0,82.5,160,170,180"   Stroke="White" StrokeThickness="2"  Grid.ColumnSpan="2"/>
    </Grid>
</Grid>

аудиовыхода

enter image description here

Вы можете увеличить размер изображения, поставив сетку image1 и image2 в окне просмотра, как показано ниже.

 <Viewbox Width="500" Height="350">
    <Grid Width="290" Height="180"/>        
 </Viewbox>

Ответ 3

Итак, дайте понять статус вещей.

  • WinRT XAML теперь поддерживается WP 8.1
  • WP Silverlight XAML может делать больше, чем WinRT XAML
  • Например, WP SL XAML может использовать пользовательские пути для отсечения
  • WinRT XAML может использовать только прямоугольники для обрезки
  • Причина: Прямоугольники выходят из любой пользовательской формы, периода
  • Команда XAML обеспечивает возможность выполнения козырей производительности
  • Сегодня команда XAML не планирует менять отсечение.

Теперь мы понимаем проблему. У нас есть другие возможности?

Если вы хотите обрезать изображение, вам повезло. Вы можете создать элемент пути любой формы и нарисовать фон кистью изображения. Это не технически обрезается, но вы имеете тот же эффект.

<Path Data="M540,394 C544.208,422.053 538.553,441.447 514,466 C490.615,489.385 
485.625,493.625 448,456 C423.947,431.947 425.435,394.188 486,374 C457.465,374 
452,353.019 452,312 C452,280.568 446.005,289.33 478,268 C514.938,243.374 
496.654,264 536,264 C538.338,275.69 546,280.948 546,294 C540.421,280.052 
545.708,255.719 564,242 C577.778,231.667 594.285,223.858 610,216 C617.244,212.378 
619.853,219.804 626,228 C630.353,233.805 671.625,322.65 620,302 C660.196,302 
680,306.666 680,374 C680,393.824 652.592,424.592 614,386 C614,403.28 
621.284,411.789 614,430 C607.693,445.768 601.833,454 580,454 C550.466,454 
548.934,443.082 534,414" HorizontalAlignment="Left" Height="269.872" 
Margin="433.483,215.058,0,0" Stretch="Fill" Stroke="Black" UseLayoutRounding="False" 
VerticalAlignment="Top" Width="247.517">
    <Path.Fill>
        <ImageBrush Stretch="None" ImageSource="Assets/SplashScreen.png"/>
    </Path.Fill>
</Path>

Это сделает это:

enter image description here

Но подождите там больше. Сам ImageBrush можно преобразовать. Это означает, что вы можете выполнить Перевод на изображение, перемещая изображение вокруг пути. Кроме того, вы можете также применить поворот на изображении.

Сначала рассмотрим анимацию, подобную той, что есть в FlipBoard. Это дает вам простую анимацию с переворотом страницы, которая выглядит потрясающе без необходимости сложного отсечения. Просмотрите эту демонстрацию: http://blog.jerrynixon.com/2012/12/walkthough-use-xamls-3d-planeprojection.html

Затем снова вы просто захотите воспроизвести эту демонстрацию. Это здорово. Ниже приведенный XAML даст вам именно тот эффект, который вы хотите. И легко оживить:

<Grid>
    <Rectangle Stroke="Black" Width="800" Height="400">
        <Rectangle.Fill>
            <ImageBrush Stretch="UniformToFill" ImageSource="Assets/car.jpg"/>
        </Rectangle.Fill>
    </Rectangle>
    <Grid Width="800" Height="400">
        <Grid.Clip>
            <RectangleGeometry Rect="0,-400,800,800" />
        </Grid.Clip>
        <Grid Width="800" Height="400" RenderTransformOrigin="0.5,0.5">
            <Grid.RenderTransform>
                <CompositeTransform ScaleX="-1" Rotation="30.957" TranslateX="527" TranslateY="108"/>
            </Grid.RenderTransform>
            <Grid.Background>
                <ImageBrush Stretch="UniformToFill" ImageSource="Assets/car.jpg"/>
            </Grid.Background>
            <Rectangle Fill="Purple" Opacity=".5" />
        </Grid>
    </Grid>
</Grid>

Это будет выглядеть так:

Здесь XAML, чтобы получить именно тот вид демонстрации, с которой вы связались:

<Grid Width="800" Height="200" Margin="283,283,283,285">
    <Grid.Clip>
        <RectangleGeometry Rect="-200,-200,1000,400" />
    </Grid.Clip>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="400" />
        <ColumnDefinition Width="400" />
    </Grid.ColumnDefinitions>
    <Path x:Name="Page2" Grid.Column="1" Data="M0.5,0.5 L495,-1 L399.5,199.5 L0.5,199.5 z" Stretch="Fill" Margin="0,-1.5,-95.5,0" UseLayoutRounding="False" RenderTransformOrigin="0.5,0.5" >
        <Path.RenderTransform>
            <CompositeTransform TranslateX="-200"/>
        </Path.RenderTransform>
        <Path.Fill>
            <ImageBrush Stretch="UniformToFill" ImageSource="Assets/Car2.jpg"/>
        </Path.Fill>
    </Path>
    <Path x:Name="Page4" Data="M94,2 L495,-1 L495,201 L0.5,199.5 z" Stretch="Fill" Margin="400,-3.5,-495.5,0.5" UseLayoutRounding="False" RenderTransformOrigin="0.5,0.5" >
        <Path.Fill>
            <ImageBrush Stretch="UniformToFill" ImageSource="Assets/Car4.jpg"/>
        </Path.Fill>
        <Path.RenderTransform>
            <CompositeTransform TranslateX="200"/>
        </Path.RenderTransform>
    </Path>
    <Image x:Name="Page1" Source="Assets/Car1.jpg" Grid.Column="0" Stretch="UniformToFill" />
    <Grid x:Name="Page3" Grid.Column="1" RenderTransformOrigin="0.5,0.5">
        <Grid.RenderTransform>
            <CompositeTransform TranslateX="-156" Rotation="25" TranslateY="-94" ScaleX="1.1" ScaleY="1.1"/>
        </Grid.RenderTransform>
        <Grid.Clip>
            <RectangleGeometry Rect="0,0,400,200" />
        </Grid.Clip>
        <Border BorderThickness="5,5,5,0" BorderBrush="White">
            <Border.RenderTransform>
                <CompositeTransform TranslateX="175"/>
            </Border.RenderTransform>
            <Image x:Name="Page3Image" Source="Assets/Car3.jpg" Stretch="UniformToFill"/>
        </Border>
    </Grid>
</Grid>

Будет выглядеть так:

enter image description here

Я не уверен, насколько это поможет, чтобы получить право, Стефан. Мое предположение... много. Хорошей новостью является то, что вы можете анимировать трансляции на GPU, поэтому большая часть этого должна быть ускорена.:)

//Джерри

Ответ 4

Для изображений - вы можете просто использовать ImageBrush и использовать его для заполнения Path, который имеет желаемую геометрию. Для чего-то более сложного - используйте RenderTargetBitmap.Render(), чтобы превратить ваш XAML в растровое изображение и вернуться к ответу 1.

Ответ 5

Я чувствую, что нужно сказать, что для метода "Путь с ImageBrush Fill" практически невозможно получить выравнивание изображения точно так же, как вы хотите, используя преобразования, поскольку точное положение изображения (изображения) внутри клип пути зависит от экстентов пути, включая Stroke.

Так, например, если у вас есть Bezier Path, вам нужно будет вычислить фактические экстенты этого Безье, чтобы затем определить точное преобразование масштаба/трансляции для применения к изображению.

Инсульт кажется невиновным, но когда у вас есть острые углы в вашей линии с полилинией, удар делает острый заостренный треугольник! Но также только в той степени, что после того, как угол становится очень резким, треугольник уже не так уж и заострен! Таким образом, вам нужно будет реплицировать точный алгоритм, который выполняет обводку для пути.

Наконец, мне нужно признать, что есть возможность дублировать ваш Path for the Stroke, так что пусть один с ImageBrush Fill, а другой без него, но с помощью Stroke.