第二十一章:变换(十)

简介: 样式通过将AnchorX值设置为0来结束,该值将旋转中心设置为每个Label的左边缘的垂直中心。 然后每个Label都会获得一个独特的旋转设置:显然,选择“ROTATE”字符串之前的空格,以便R的垂直条组合形成一个看起来几乎像圆的16边多边形。

样式通过将AnchorX值设置为0来结束,该值将旋转中心设置为每个Label的左边缘的垂直中心。 然后每个Label都会获得一个独特的旋转设置:
2019_01_16_113122
显然,选择“ROTATE”字符串之前的空格,以便R的垂直条组合形成一个看起来几乎像圆的16边多边形。
如果每个字母都是单独的Label元素,您还可以在文本字符串中旋转单个字母。 首先将这些Label元素放在AbsoluteLayout中,然后应用Rotation属性使其看起来好像字母遵循特定的非线性路径。 CircularText程序将这些字母排成一个圆圈。
CircularText是一个仅代码程序,类似于备用BoxViewCircle算法。 构造函数负责创建所有单个Label元素并将它们添加到AbsoluteLayout的Children集合中。 在构造函数中没有执行定位或旋转,因为程序还不知道这些单独的Label元素有多大,或者AbsoluteLayout有多大:

public class CircularTextPage : ContentPage
{
    AbsoluteLayout absoluteLayout;
    Label[] labels;
    public CircularTextPage()
    {
        // Create the AbsoluteLayout.
        absoluteLayout = new AbsoluteLayout();
        absoluteLayout.SizeChanged += (sender, args) =>
            {
                LayOutLabels();
            };
        Content = absoluteLayout;
        // Create the Labels.
        string text = "Xamarin.Forms makes me want to code more with ";
        labels = new Label[text.Length];
        double fontSize = 32;
        int countSized = 0;
        for (int index = 0; index < text.Length; index++)
        {
            char ch = text[index];
            Label label = new Label
                {
                    Text = ch == ' ' ? "-" : ch.ToString(),
                    Opacity = ch == ' ' ? 0 : 1,
                    FontSize = fontSize,
                };
            label.SizeChanged += (sender, args) =>
                {
                    if (++countSized >= labels.Length)
                        LayOutLabels();
                };
            labels[index] = label;
            absoluteLayout.Children.Add(label);
        }
    }
    void LayOutLabels()
    {
        // Calculate the total width of the Labels.
        double totalWidth = 0;
        foreach (Label label in labels)
        {
            totalWidth += label.Width;
        }
        // From that, get a radius of the circle to center of Labels.
        double radius = totalWidth / 2 / Math.PI + labels[0].Height / 2;
        Point center = new Point(absoluteLayout.Width / 2, absoluteLayout.Height / 2);
        double angle = 0;
        for (int index = 0; index < labels.Length; index++)
        {
            Label label = labels[index];
            // Set the position of the Label.
            double x = center.X + radius * Math.Sin(angle) - label.Width / 2;
            double y = center.Y - radius * Math.Cos(angle) - label.Height / 2;
            AbsoluteLayout.SetLayoutBounds(label, new Rectangle(x, y, AbsoluteLayout.AutoSize,
                                                                    AbsoluteLayout.AutoSize));
            // Set the rotation of the Label.
            label.Rotation = 360 * angle / 2 / Math.PI;
            // Increment the rotation angle.
            if (index < labels.Length - 1)
            {
                angle += 2 * Math.PI * (label.Width + labels[index + 1].Width) / 2 / totalWidth;
            }
        }
    }
}

请注意创建每个Label元素的代码:如果原始文本字符串中的字符是空格,则Label的Text属性将分配一个破折号,但Opacity属性设置为0,以便破折号不可见。这是修复Windows运行时平台上出现的问题的一个小技巧:如果Label只包含一个空格,那么Label的宽度计算为零,所有单词一起运行。
所有操作都发生在LayOutLabels方法中。从构造函数中表示为lambda函数的两个SizeChanged处理程序调用此方法。在程序启动后或手机改变方向时,很快就会调用AbsoluteLayout的SizeChanged处理程序。
Label元素的SizeChanged处理程序跟踪到目前为止已调整大小的数量,并且仅在LayoutLabels准备就绪时调用它们。
LayOutLabels方法计算所有Label元素的总宽度。如果假设它是圆的圆周,则该方法可以容易地计算该圆的半径。但是这个半径实际上是每个Label的高度的一半。因此,该半径的端点与每个标签的中心重合。通过从该点减去标签宽度和高度的一半,Label位于AbsoluteLayout内。
累积角度既可用于查找下一个Label的半径端点,也可用于旋转Label。由于每个半径的端点与每个Label的中心重合,因此角度将根据当前Label的宽度的一半和下一个Label的宽度的一半递增。
虽然数学有点棘手,但结果是值得的:2019_01_16_113424
此程序不会设置AnchorX和AnchorY的非默认值,因此在iOS上更改手机方向没有问题。

目录
相关文章
|
前端开发 数据可视化 图形学
【数学篇】09 # 如何用仿射变换对几何图形进行坐标变换?
【数学篇】09 # 如何用仿射变换对几何图形进行坐标变换?
112 0
【数学篇】09 # 如何用仿射变换对几何图形进行坐标变换?
|
机器学习/深度学习 传感器 算法
【解包裹】基于可靠性直方图处理的快速二维相位展开算法附matlab代码和论文
【解包裹】基于可靠性直方图处理的快速二维相位展开算法附matlab代码和论文
|
vr&ar 图形学
【Unity3D 灵巧小知识点】 ☀️ | 求解 两个向量的夹角度数
Unity 小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 。 包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助 Unity 将创意变成现实。 Unity 平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持平台包括手机、平板电脑、PC、游戏主机、增强现实和虚拟现实设备。
【Unity3D 灵巧小知识点】 ☀️ | 求解 两个向量的夹角度数
Halcon标定系列(5):4点标定之眼在手外项目实践,已知仿射变换矩阵,计算得到旋转角度和缩放因子等参数
Halcon标定系列(5):4点标定之眼在手外项目实践,已知仿射变换矩阵,计算得到旋转角度和缩放因子等参数
805 0
Halcon标定系列(5):4点标定之眼在手外项目实践,已知仿射变换矩阵,计算得到旋转角度和缩放因子等参数
|
JavaScript Android开发 索引
第二十一章:变换(九)
旋转的文字效果轮换很有趣。 旋转动画时更有趣(正如您将在下一章中看到的那样),但即使使用静态图像也很有趣。本章和下一章中的几个旋转示例涉及将视觉元素排列在一个圆圈中,所以让我们首先尝试显示一个简单的圆圈。
841 0
|
Android开发
第二十一章:变换(八)
旋转变换 “旋转”属性旋转屏幕表面上的可视元素。 将“旋转”属性设置为以度为单位的角度(不是弧度)。 正角度顺时针旋转元素。 您可以将“旋转”设置为小于0或大于360的角度。实际旋转角度是旋转属性模数360的值。
816 0
|
Android开发
第二十一章:变换(十四)
3D-ish旋转 即使计算机屏幕是平面和二维的,也可以在这些屏幕上绘制视觉对象,使其具有第三维的外观。 在本章的前面,您看到了一些文本效果,它们提供了第三个维度的提示,而Xamarin.Forms支持两个额外的旋转,名为RotationX和RotationY,它们似乎也突破了屏幕固有的二维平面度。
1342 0
|
Android开发 iOS开发
第二十一章:变换(七)
锚定规模当你尝试使用Scale属性时,你可能已经注意到视觉元素的任何扩展都是从元素的中心向外发生的,如果你将视觉元素缩小到任何东西,它也会向中心收缩。这是另一种思考方式:无论Scale属性的设置如何,视觉元素正中心的点都保持在同一位置。
934 0
|
Android开发 iOS开发 Windows
第二十一章:变换(六)
两个按钮的Clicked处理程序每个都启动一个独立的动画。 第一个Button的Clicked处理程序将其Scale属性从1设置为5并再次返回,而第二个Button的Clicked处理程序将其FontSize属性设置为1到5的比例因子,然后再返回。
940 0
|
JavaScript Android开发
第二十一章:变换(五)
规模变换 VisualElement类定义名为Scale的属性,您可以使用该属性更改元素的呈现大小。 Scale属性不会影响布局(将在ButtonScaler程序中演示)。它不会影响元素的get-only Width和Height属性,也不会影响包含Width和Height值的get-only Bounds属性。
906 0