第二十一章:变换(十二)

简介: 这两个问题都在非最小的BoxViewClock中得到解决。 XAML文件与MinimalBoxViewClock非常相似,但代码隐藏文件更为广泛。 它以名为HandParams的小结构开始,该结构定义每只手相对于半径的大小,但也包括偏移值。

这两个问题都在非最小的BoxViewClock中得到解决。 XAML文件与MinimalBoxViewClock非常相似,但代码隐藏文件更为广泛。 它以名为HandParams的小结构开始,该结构定义每只手相对于半径的大小,但也包括偏移值。 这是手的总长度的一部分,表示它与钟面中心对齐的位置。 它也成为旋转的AnchorY值:

public partial class BoxViewClockPage : ContentPage
{
    // Structure for storing information about the three hands.
    struct HandParams
    {
        public HandParams(double width, double height, double offset) : this()
        {
            Width = width;
            Height = height;
            Offset = offset;
        }
        public double Width { private set; get; } // fraction of radius
        public double Height { private set; get; } // ditto
        public double Offset { private set; get; } // relative to center pivot
    }
    static readonly HandParams secondParams = new HandParams(0.02, 1.1, 0.85);
    static readonly HandParams minuteParams = new HandParams(0.05, 0.8, 0.9);
    static readonly HandParams hourParams = new HandParams(0.125, 0.65, 0.9);
    BoxView[] tickMarks = new BoxView[60];
    public BoxViewClockPage()
    {
        InitializeComponent();
        // Create the tick marks (to be sized and positioned later).
        for (int i = 0; i < tickMarks.Length; i++)
        {
            tickMarks[i] = new BoxView { Color = Color.Black };
            absoluteLayout.Children.Add(tickMarks[i]);
        }
    }
    void OnAbsoluteLayoutSizeChanged(object sender, EventArgs args)
    {
        // Get the center and radius of the AbsoluteLayout.
        Point center = new Point(absoluteLayout.Width / 2, absoluteLayout.Height / 2);
        double radius = 0.45 * Math.Min(absoluteLayout.Width, absoluteLayout.Height);
        // Position, size, and rotate the 60 tick marks.
        for (int index = 0; index < tickMarks.Length; index++)
        {
            double size = radius / (index % 5 == 0 ? 15 : 30);
            double radians = index * 2 * Math.PI / tickMarks.Length;
            double x = center.X + radius * Math.Sin(radians) - size / 2;
            double y = center.Y - radius * Math.Cos(radians) - size / 2;
            AbsoluteLayout.SetLayoutBounds(tickMarks[index], new Rectangle(x, y, size, size));
            tickMarks[index].Rotation = 180 * radians / Math.PI;
        }
        // Position and size the three hands.
        LayoutHand(secondHand, secondParams, center, radius);
        LayoutHand(minuteHand, minuteParams, center, radius);
        LayoutHand(hourHand, hourParams, center, radius);
    }
    void LayoutHand(BoxView boxView, HandParams handParams, Point center, double radius)
    {
        double width = handParams.Width * radius;
        double height = handParams.Height * radius;
        double offset = handParams.Offset;
        AbsoluteLayout.SetLayoutBounds(boxView,
            new Rectangle(center.X - 0.5 * width,
                          center.Y - offset * height,
                          width, height));
        // Set the AnchorY property for rotations.
        boxView.AnchorY = handParams.Offset;
    }
}

钟面周围的刻度线也是BoxView元素,但其中有60个具有两种不同的尺寸,它们使用您已经看过的技术定位。 考虑到没有Xamarin.Forms图形系统,视觉效果出奇的好:
2019_01_18_092557
最重要的是,你实际上可以告诉时间。
这个时钟有另一个有趣的功能,使手的运动相当迷人。 秒针既不会从第二个滑动到第二个也不会产生离散跳跃; 相反,它有一个更复杂的运动。 它略微向后拉,然后向前跳,但略微超过它的标记,
然后备份并休息。 这是怎么做到的?
在下一章中,您将看到Xamarin.Forms实现了几个缓动函数,这些函数可以通过更改动画“速度”来加速动画并加速动画,从而为动画添加真实感。。 这样的缓动函数已经成为整个计算机行业的标准,而Xamarin.FormsBook.Toolkit包含一个值转换器,它实现了一个称为后退缓动的缓动函数:

namespace Xamarin.FormsBook.Toolkit
{
    public class SecondBackEaseConverter : IValueConverter
    {
        public object Convert(object value, Type targetType,
                              object parameter, CultureInfo culture)
        {
            int seconds = (int)((double)value / 6); // 0, 1, 2, ... 60
            double t = (double)value / 6 % 1; // 0 --> 1
            double v = 0; // 0 --> 1
            // Back-ease in and out functions from http://robertpenner.com/easing/
 
            if (t < 0.5)
            {
                t *= 2;
                v = 0.5 * t * t * ((1.7 + 1) * t - 1.7);
            }
            else
            {
                t = 2 * (t - 0.5);
                v = 0.5 * (1 + ((t - 1) * (t - 1) * ((1.7 + 1) * (t - 1) + 1.7) + 1));
            }
            return 6 * (seconds + v);
        }
        public object ConvertBack(object value, Type targetType, 
                                  object parameter, CultureInfo culture)
        {
            return (double)value;
        }
    }
}

BoxViewClock XAML文件中引用了此转换器:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:toolkit=
                 "clr-namespace:Xamarin.FormsBook.Toolkit;assembly=Xamarin.FormsBook.Toolkit"
             x:Class="BoxViewClock.BoxViewClockPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness"
                    iOS="0, 20, 0, 0" />
    </ContentPage.Padding>
    <ContentPage.Resources>
        <ResourceDictionary>
            <toolkit:SecondBackEaseConverter x:Key="secondBackEase" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <AbsoluteLayout x:Name="absoluteLayout"
                    BackgroundColor="White"
                    SizeChanged="OnAbsoluteLayoutSizeChanged">
 
        <AbsoluteLayout.BindingContext>
            <toolkit:AnalogClockViewModel />
        </AbsoluteLayout.BindingContext>
 
        <BoxView x:Name="hourHand"
                 Color="Black"
                 Rotation="{Binding HourAngle}" />
 
        <BoxView x:Name="minuteHand"
                 Color="Black"
                 Rotation="{Binding MinuteAngle}" />
 
        <BoxView x:Name="secondHand"
                 Color="Black"
                 Rotation="{Binding SecondAngle, Converter={StaticResource secondBackEase}}" />
    </AbsoluteLayout>
</ContentPage>

您将在下一章中看到更多的缓动函数。

目录
相关文章
|
5月前
|
算法 C语言
一文搞懂:一文教你快速搞懂速度曲线规划之S形曲线(超详细+图文+推导+附件代码)
一文搞懂:一文教你快速搞懂速度曲线规划之S形曲线(超详细+图文+推导+附件代码)
173 0
一文搞懂:一文教你快速搞懂速度曲线规划之S形曲线(超详细+图文+推导+附件代码)
|
数据可视化 数据挖掘 图形学
|
vr&ar 图形学
【Unity3D 灵巧小知识点】☀️ | Unity 四元数、欧拉角 与 方向向量 之间转换
Unity 小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 。 包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助 Unity 将创意变成现实。
|
Android开发
第二十一章:变换(十四)
3D-ish旋转 即使计算机屏幕是平面和二维的,也可以在这些屏幕上绘制视觉对象,使其具有第三维的外观。 在本章的前面,您看到了一些文本效果,它们提供了第三个维度的提示,而Xamarin.Forms支持两个额外的旋转,名为RotationX和RotationY,它们似乎也突破了屏幕固有的二维平面度。
1389 0
|
JavaScript Android开发
第二十一章:变换(十一)
模拟时钟用于图形用户界面的经典示例程序之一是模拟时钟。 BoxView再一次为时钟之手进行救援。 必须根据当前时间的小时,分钟和秒旋转这些BoxView元素。让我们首先使用名为AnalogClockViewModel的类来处理旋转数学,该类包含在Xamarin.
1094 0
|
Android开发
第二十一章:变换(十三)
垂直滑块?某些观点是否可以轮换并仍然可以正常工作? 更具体地说,Xamarin.Forms的普通水平Slider元素可以旋转成垂直滑块吗?我们来试试吧。 VerticalSliders程序在StackLayout中包含三个滑块,StackLayout本身逆时针旋转90度: <ContentPage xmlns="http://xamarin.
815 0
|
Android开发 索引
第二十一章:变换(十)
样式通过将AnchorX值设置为0来结束,该值将旋转中心设置为每个Label的左边缘的垂直中心。 然后每个Label都会获得一个独特的旋转设置:显然,选择“ROTATE”字符串之前的空格,以便R的垂直条组合形成一个看起来几乎像圆的16边多边形。
1043 0
|
JavaScript Android开发 索引
第二十一章:变换(九)
旋转的文字效果轮换很有趣。 旋转动画时更有趣(正如您将在下一章中看到的那样),但即使使用静态图像也很有趣。本章和下一章中的几个旋转示例涉及将视觉元素排列在一个圆圈中,所以让我们首先尝试显示一个简单的圆圈。
877 0
|
Android开发
第二十一章:变换(八)
旋转变换 “旋转”属性旋转屏幕表面上的可视元素。 将“旋转”属性设置为以度为单位的角度(不是弧度)。 正角度顺时针旋转元素。 您可以将“旋转”设置为小于0或大于360的角度。实际旋转角度是旋转属性模数360的值。
839 0
|
Android开发 iOS开发
第二十一章:变换(七)
锚定规模当你尝试使用Scale属性时,你可能已经注意到视觉元素的任何扩展都是从元素的中心向外发生的,如果你将视觉元素缩小到任何东西,它也会向中心收缩。这是另一种思考方式:无论Scale属性的设置如何,视觉元素正中心的点都保持在同一位置。
965 0