当前位置: 首页 > news >正文

ftp怎么上传网站佛山外英语网站制作

ftp怎么上传网站,佛山外英语网站制作,做微商好还是开网站好,骨干专业群建设任务书网站原文#xff1a;Mesh Transforms 作者#xff1a;Bartosz Ciechanowski 译者#xff1a;kmyhy 我是 transform 属性的超级粉丝。让 UIView 或者 CALayer 的形体发生改变的最简单方法就是联合使用旋转、平移和缩放。在易于适用的同时#xff0c;常规变换所能实现的效果也同… 原文Mesh Transforms 作者Bartosz Ciechanowski 译者kmyhy 我是 transform 属性的超级粉丝。让 UIView 或者 CALayer 的形体发生改变的最简单方法就是联合使用旋转、平移和缩放。在易于适用的同时常规变换所能实现的效果也同时被限制住了——比如一个矩形只能变换成其它四边形。这是毫无疑问的但除此之外我们还可以做的更多。 本文介绍网格变形。网格变形的核心概念非常简单你可以将一个 layer 划分成若干个顶点通过移动顶点的方式让几何形状发生改变 本文的主要内容介绍了一个 Core Animateion 的私有 API这个框架从 iOS 5.0 之后开始引入。不用担心你的思想会被私有 API 所“污染”因为本文的第二部分会介绍一个可替换方案:一个与之类似的开源框架。 CAMeshTransform 当我第一次看见 iOS 运行时库的头文件时我不禁为之痴迷。有这么多的私有类、隐藏属性让人大开眼界。其中最有趣的一个发现就是 CAMeshTransform 以及 CALayer 的 meshTransform 属性。有一股强烈的求知欲望让我非要把搞清楚直到最近我终于吃透了它。它看起来非常复杂但网格转换的底层概念还是很容易搞懂的。CAMeshTransform 有一个构造方法是这个样子的 (instancetype)meshTransformWithVertexCount:(NSUInteger)vertexCountvertices:(CAMeshVertex *)verticesfaceCount:(NSUInteger)faceCountfaces:(CAMeshFace *)facesdepthNormalization:(NSString *)depthNormalization;12345 这个方法清楚地描述了网格转换的基本构成——顶点、面和一个字符串用于描述 depth normalization。我们接下来会逐一讨论它们。 注不幸的是结构体内部的字段名被编译后无法看到因此我不得不用自己的理解进行描述。原始的字段名可能不一样但意思应该是一致的。 顶点 Vertex 一个顶点是一个拥有两个字段属性的结构 typedef struct CAMeshVertex {CGPoint from;CAPoint3D to; } CAMeshVertex;1234 CAPoint3D 和普通的 CGPoint 非常像——只是增加了一个 z 坐标 typedef struct CAPoint3D {CGFloat x;CGFloat y;CGFloat z; } CAPoint3D;12345 这样CAMeshVertex 的用途就不难猜出了它描述了一个 layer 平面上的二维点到 3D 空间中的点的映射。CAMeshVertex 定义了这样的行为“获取 layer 上的点并将这个点移动到指定位置。”因为 CAPoint3D 由 x、y、z 字段构成因此网格转换注定不会是平面的 平面 Face CAMeshFace 也很简单 typedef struct CAMeshFace {unsigned int indices[4];float w[4]; } CAMeshFace;1234 indecies 数组保存了一个平面上的 4 个顶点。因为 CAMeshTransform 中也包含了一个顶点数组因此一个 CAMeshFace 可以通过顶点在这个数组中的索引来引用这些顶点。这中计算机图形学中的标准范式有一个好处——多个 Face 有可能引用同一个顶点。这不仅解决了数据复制的问题而且要修改所有相邻平面的形状更加方便了 平面由它们的顶点所定义对于 CAMeshFace 的 w 字段这将在后面进行讨论。 坐标 看过顶点和平面之后我们仍然不是很清楚我们应该在一个 CAMeshVertex 中放入什么。在 CALayer 中许多属性是以点 Point 的形式定义的有的使用了单元坐标系比如 anchorPoint 就是最常见的一个。CAMeshVertex 也使用单元坐标系。点 {0.0, 0.0}对应于 layer 的左上角而点 {1.0, 1.0} 对应于 layer 的右下角。下面的点 to 使用了同一坐标系 顶点用单元坐标系进行定义使用单元坐标系的原因是在 Core Animation Programming Guide 中有叙述 使用单元坐标系是为了不和屏幕坐标系进行绑定因为每个值都是相对于其他值的。 单元坐标系的最大好处在于它们的大小不会改变。你可以在小视图和大视图上都使用相同的网格效果并无二致。我认为这才是在 CAMeshTransform 使用单元坐标系的最大原因。 修改网格变形 创建一个普通 CAMeshTransform 的坏处是它是不可变的所有顶点和平面必须在变形创建之前就定义。幸运的是它有一个可变的子类叫做 CAMutableMeshTransform允许我们随时添加、删除、替换顶点和平面。 两个网格变形的类都有一个相同的 subdivisionSteps 属性指定当 layer 绘制在屏幕上时需要切分成多少部分。这个值是一个指数设置为 3表示每边被分成 8 片。默认值是 -1这会让网格接近平滑。我觉得它会自动调整网格数以保证最终结果不会太糟糕。 不太明确的一点是当 subdivisionSteps 不为零时所产生的网格不会完全通过它的所有顶点。 切分后的网格形状和它的顶点事实上顶点是一个平面的控制点通过观察它们是如何对几何形状产生影响我发现 CAMeshTransform 实际上定义了一个三次 NURBS 曲面。这就不得不提到 CAMeshFace 的 w 字段了。将这个值设置为 w 数组中的 4 个索引中的一个时似乎会影响到对应顶点的权重。这个系数并不像是 NURBS 公式中的 weight 系数。不幸的是尽管我搜遍了几百行浮点汇编代码还是没有什么收获。 尽管 NURBS 曲面极其强大它们也无法让遍历顶点的过程变快。在我定义自己的网格时我需要完全的控制所产生的网格最终是什么样子因此我将 subdivisionSteps 属性设置为 0。 应用网格变形 光光是创建一个 CAMeshTransform 是没有意义的我们需要将它赋给一个 CALayer 的私有属性 property (copy) CAMeshTransform *meshTransform;1 下列代码创建了一个波浪形的网格变形。代码非常冗长因为我们想完整演示整个流程。只需要定义几个便利函数就可以将代码缩减到几行代码. - (CAMeshTransform *)wavyTransform {const float Waves 3.0;const float Amplitude 0.15;const float DistanceShrink 0.3;const int Columns 40;CAMutableMeshTransform *transform [CAMutableMeshTransform meshTransform];for (int i 0; i Columns; i) {float t (float)i / Columns;float sine sin(t * M_PI * Waves);CAMeshVertex topVertex {.from {t, 0.0},.to {t, Amplitude * sine * sine DistanceShrink * t, 0.0}};CAMeshVertex bottomVertex {.from {t, 1.0},.to {t, 1.0 - Amplitude Amplitude * sine * sine - DistanceShrink * t, 0.0}};[transform addVertex:topVertex];[transform addVertex:bottomVertex];}for (int i 0; i Columns; i) {unsigned int topLeft 2 * i 0;unsigned int topRight 2 * i 2;unsigned int bottomRight 2 * i 3;unsigned int bottomLeft 2 * i 1;[transform addFace:(CAMeshFace){.indices {topLeft, topRight, bottomRight, bottomLeft}}];}transform.subdivisionSteps 0;return transform; }1234567891011121314151617181920212223242526272829303132333435363738394041 这段代码对一个 UILabel 使用了网格变形 值得一提的是在模拟器和设备上运行会得到不同的结果。因为 iOS 模拟器的 Core Animation 版本在绘制 3D 图形时使用的是软件模拟软件模拟的渲染器和 OpenGL ES 的渲染器是不同的。对于贴图纹理来说尤为明显。 抽象漏洞 当你在 retina 屏上仔细观察经过网格变形的 UILabel 时你会发现它的文字质量有一点模糊。这可以用下面一句代码来解决 label.layer.rasterizationScale [UIScreen mainScreen].scale;1 这可能是底层机制上的一个疏漏。CALayer 和它的 sublayer 上的内容被栅格化为单一纹理然后应用到顶点网格上。理论上栅格化能够将所变形的 CALayer 的 sublayer 很好地放置在 superlayer 上从而避免产生不正确的网格。而且在一般情况下sublayer 的顶点会被放置在父 CALayer 的顶点之间这回导致一个糟糕的 z-fighting 现象Z 缓冲冲突。栅格化是一种很好的解决方案。 我还发现另外一个问题来自于硬件。CAMeshTransform 提供了一个对平面的抽象其实就是一个四边形。但是现代 GPU 只认三角形。四边形在发送给 GPU 之前必须被切分成两个三角形。这种切分会有两种不同的方式进行 将一个四边形分成两个三角形的不同方法表面上这不会产生什么大问题但在执行同一个变形时会导致结果大不相同 同一个网格导致不同的结果注意网格变形的形状是完全对称的但是它们最终形成的结果却完全不是。左边的网格只有一个三角形被变形。右边的网格两个三角形都变形了。不难猜到为什么 Core Animation 要使用四方形进行切分了。注意当你改变组成平面的顶点的索引顺序时也会导致同样的效果。 尽管栅格化和三角形的抽象漏洞会带来一些问题而且这些问题确实不可忽略但一些列解决这些问题的复杂性被掩盖了。 添加深度 单元坐标系对于宽高来说适合的。但是我们无法定义第三维——CALayer 的 bounds 的 size 属性中只有两维。一个宽度单位刚好等于 bounds.size.width 个像素而高度也是类似的。但深度为 1 表示几个像素Core Animation 的缔造者们用一种非常简单但极其有效的方式解决了这个问题。 CAMeshTransform 的 depthNoramlization 属性是一个字符串它可能取值为下述 6 个常量之一 extern NSString * const kCADepthNormalizationNone; extern NSString * const kCADepthNormalizationWidth; extern NSString * const kCADepthNormalizationHeight; extern NSString * const kCADepthNormalizationMin; extern NSString * const kCADepthNormalizationMax; extern NSString * const kCADepthNormalizationAverage;123456 分别说明如下 CAMeshTransform 将 depthNormalization 当成是其他两维的一个函数。这些常量的含义和其字面意义相同我们举例进行说明。如果将 depthNoramlization 设为 kCADepthNormalizationAverage而 CALayer 的 bounds 为 GRectMake(0.0, 0.0, 100.0, 200.0)。由于我们使用平均 normalization深度的 1 个单位等于 150.0 像素。如果 CAMeshVertext 的坐标为 {1.0, 0.5, 1.5} 转换成 3D 坐标系等于 {100.0, 100.0, 225.0}: 单位转换为点为什么要进行单位坐标到像素点的转换因为 CALayer 的 transform 属性的类型是 CATransform3D。CATranform3D 的属性是以点为单位定义的。实际上你可以在 CALayer 上使用任意变形它都会影响到它的顶点。注意 z 坐标移动和透视变换会得益于这个特性。 这里我们看另一个例子让 depthNormalization 不等于默认的 kCADepthNormalizationNone 就行。这会导致令人意外的结果——所有东西都是平面的。深度和顶点 z 坐标相加是非常令人难以置信的。我们先跳过这个步骤讨论一个新的组件这个组件会增强网格的斜度和曲率——阴影。 遭遇普罗米修斯 既然我们已经打开了私有 Core Animation 类的潘多拉之盒那么我们还可以使用另一个私有API。不出意外也有一个类叫做 CALight它非常有用因为 CALayer 还有一个私有的数组类型的 lights 属性。 CALight 用 (id)lightWithType:(NSString *)lightType 创建lightType 参数可能取值如下 extern NSString * const kCALightTypeAmbient; extern NSString * const kCALightTypeDirectional; extern NSString * const kCALightTypePoint; extern NSString * const kCALightTypeSpot;1234 我不会介绍 CALight 太多我们直接就上例子。这次我们将使用两个自定义的 CAMutableMeshTransform 便利方法。第一个 是 identityMeshTransformWithNumberOfRows:numberOfColumns:会用均匀分布的顶点创建一个网格不带任何干扰纹。我们会用 mapVerticesUsingBlock: 方法修改顶点这个方法将所有顶点转换为另一个顶点。 CALight *light [CALight new]; // directional light by default [label.superview.layer setLights:[light]]; // has to be applied to superlayerCAMutableMeshTransform *meshTransform [CAMutableMeshTransform identityMeshTransformWithNumberOfRows:50 numberOfColumns:50]; [meshTransform mapVerticesUsingBlock:^CAMeshVertex(CAMeshVertex vertex, NSUInteger vertexIndex) {float x vertex.from.x - 0.5f;float y vertex.from.y - 0.5f;float r sqrtf(x * x y * y);vertex.to.z 0.05 * sinf(r * 2.0 * M_PI * 4.0);return vertex; }]; label.layer.meshTransform meshTransform;CATransform3D transform CATransform3DMakeRotation(-M_PI_4, 1, 0, 0); transform.m34 -1.0/800.0; // some perspective label.layer.transform transform; 1234567891011121314151617181920 这是对一个正方形 UILabel 应用这段代码后的效果 CALight, CAMeshTransform, 和 CATransform3D 一起使用灯光看起来有点粗劣但重要的是只需要很轻松的方式就能创造十分复杂的效果。 可以修改 CALight 的环境光、漫反射和镜面反射强度——标准的 Phong 反射模型中的参数。同时CALayer 还有一堆表面反射属性。我对它们进行了短时间的尝试结果一无所获。但我浏览了这些私有头文件因此要测试 Core Animation 的灯光并不难。 为什么这些 API 是私有的 将一个 API 定义为私有的一个最主要的原因是它并不可靠CAMeshTransform 当然也是这样。有几个证据足以说明。 首先将 subdivisionSteps 设置为 20 就能轻易让设备重启。控制台中输出一堆内存警告清晰地表明这是为什么。这确实很糟心但也很容易避免——不要碰这个属性或者将它设置为 0。 如果你定义的某个平面发生退化比如它的索引指向同一个顶点你会让设备挂起。一切都会停止响应包括硬件按钮唯一能做的只有硬启动长按 home 键电源按钮。这个框架似乎无法处理输入错误的情况。 为什么会这样这是因为 backboard —— 另外一个进程充当 Core Animation 的渲染服务器。严格来说是系统而不是 app 让系统崩溃的这是 iOS 核心组件因为错误使用而导致问题。 缺失的特性 一个能够进行网格变形的 CALayer 的通常的目的非常复杂以至于 Core Animation 团队无法考虑到方方面面并忽略了一些潜在特性。 Core Animation 允许网格变形的 CALayer 拥有 alpha 通道。要正确绘制半透明对象根本不成问题。这是画笔程序常见的功能。z-排序步骤不难实现实际上代码类似于进行基数排序排序非常快因为基数排序可以对浮点数进行排序。但是却无法对三角形进行排序因为三角形有可能相交或重叠。 对于这个问题通常的办法是切分三角形以便所有边都会被删除。这部分算法似乎未实现。幸好一个正确的、格式良好的网格基本上不会出现交叠但偶尔会出现这时网格变形的 CALayer 看起来会出现一些显示问题。 另一个被完全忽略掉的问题是 hit testing——CALayer 好像是从来没有被网格变形过一样。因为无论是 CALayer 还是 UIView 的 hitTest: 方法都不知道网格所以整个控件的 hit test 区域都无法和它们的可视化外观进行匹配 UISwitch 的 hit tes 区域不受网格变形的影响这个问题的解决方式是发出一根射线计算所击中的三角形是哪些将点击点从 3D 空间投射到 2D 空间然后进行普通的 hit testing。这是可行的但不容易。 替换私有 API 考虑到 CAMeshTransform 的这些缺陷大家可能会统一它是一个失败的产品。当然不是。它仍然有它的魅力。它打开了一个全新的 iOS 动画和交互的窗口。和过去痛苦的老旧的转换、渐入和模糊相比这是一股清新空气。我想在每一样东西上使用网格转换但我无法容忍要调用那么多的私有 API。因此我写了一个开源的、与之相近的替代物。 受 CAMeshTransform 的激发我创建了一个 BCMeshTransform它几乎重现了原类的所有功能。我的意图非常简单如果 CAMeshTransform 中已经有的方法你可以在任何 CALayer 上使用基本相同的网格变换函数并达到非常类似的效果当然 CAMeshTransform 中没有方法另当别论。这样你只需要将所有的 BC 类前缀替换为 CA 即可。 Transform 类已经有了剩下的事情就是进行网格变形。为此我创建了 BCMeshTransformView它是一个 UIView 的子类拥有一个 meshTransform 属性。 没有直接公开地访问 Core Animation 渲染服务器实现时我强制使用了 OpenGL。这不是最佳方案因为它会带来一些原类所没有的缺陷但这是目前唯一可行的解决方案。 几点提示 当我创建这个类时我遇到了几个坑这不妨碍我谈谈它们的解决办法。 UIView 的 Animation 块 编写一个类的可动画的自定义属性并不难。David Rönnqvist在presentation on UIView animations中提到,CALayer 在任何其可动画属性被赋值时会询问它的委托对象一个 UIView 拥有这个 CALayer。 如果我们在动画块中当 actionForKey: 方法调用时UIView 会返回一个 animation 对象。通过这个 CAAnimation我们可以访问它的属性以获得动画参数并基于这些参数进行动画。 我最初的实现是这样的 - (void)setMeshTransform:(BCMeshTransform *)meshTransform {CABasicAnimation *animation [self actionForLayer:self.layer forKey:opacity];if ([animation isKindOfClass:[CABasicAnimation class]]) {// were inside an animation blockNSTimeInterval duration animation.duration;...}... }12345678910 很快我就知道这样是不行的——这个完成块永远不会被触发。当一个基于动画的块被创建时UIKit 会创建一个 UIViewAnimationState 实例并赋给块中创建的 CAAnimation 的委托。我的猜测也被验证了UIViewAnimationState 等它所有的 animation 完成或取消后才会调用这个完成块。为了读取 animation 的属性我引用了这个 animation但是它没有被添加到任何 CALayer 中因此它永远不会完成。 解决办法比我想象的更简单。我为 BCMeshTransformView 创建了一个 subview 作为它的“替代品”。这是我目前的实现 - (void)setMeshTransform:(BCMeshTransform *)meshTransform {[self.dummyAnimationView.layer removeAllAnimations];self.dummyAnimationView.layer.opacity 1.0;self.dummyAnimationView.layer.opacity 0.0;CAAnimation *animation [self.dummyAnimationView.layer animationForKey:opacity];if ([animation isKindOfClass:[CABasicAnimation class]]) {// were inside UIView animation block}... }123456789101112 对 opacity 属性进行两次赋值是必要的这样才能保证这个属性的值发生了变化。animation 不会被加到 CALayer如果它已经是目标状态的话。同时CALayer 必须存在于 UIView 或 UIWindow 的视图树中才行否则它的属性不会动画。 因为要对网格进行动画需要让 Core Animation 插入浮点数这就需要将这些数转换成 NSNumber放进数组实现 needsDisplayForKey: 类方法并在 setValue:forKey: 方法中负责显示 CALayer 的改变。在获得便利的同时这些方法有严重的性能问题。一个 25x25 个平面的网格就无法在 60 FPS 下进行动画哪怕是用 iPad Air。封包和解包的代价太大了。 替代 Core Animation 的方法我使用一个非常简单的基于 CADisplayLink 的动画引擎。这获得了更好的性能100x100 的平面仍然能够在 60 FPS 下流畅地动画。这不是最佳解决方案我们因此失去了许多 CAAnimation 带来的便利但 16 倍速度的好处完全可以忽略这些。 渲染内容 BCMeshTransformView 的目的是呈现它的网格变形的 subview。在提交给 OpenGL 之前 UIView 层次必须被渲染成纹理。然后这个纹理化的顶点网格用 GLKView 显示出来而后者是 BCMeshTransformView 的核心。从高度抽象的层次看非常简单但不等不提到一个将 subview 层次进行截图问题。 我们不想对 GLKView 进行截取因为这会导致一个镜面隧道效应。另外我们不想直接显示其他 subview ——它们的作用主要是在 OpenGL 中可见但在 UIKit 视图层次中不可见。它们不能放在 GLKView 下因为它们必须是不透明的。要解决这个问题我使用了 contentView 的概念就像 UITableViewCell 管理它的 subview 一样。这个视图层次类似于下图所示 BCMesthTransformView 的视图树contentView 嵌到一个 containerView 中。containerView 的 frame 为 CGRectZeroclipsToBounds 为 YES这样它就隐藏了但它仍然存在于 BCMeshTransformView 中。每个需要进行网格变形的 subview 都必须添加到 contentView 中。 contentView 的内容通过 drawViewHierarchyInRect:afterScreenUpdates: 方法渲染到纹理中。截取并上传纹理的整个过程是非常快的但不幸的是对于较大的视图会花去 16 毫秒以上的时间。对于每帧需要绘制一次视图树来说这就太长了。尽管 BCMeshTransformView 会自动观察 contentView 的 subview 的改变并重新绘制其纹理它也不支持对网格化的 subview 的动画。 结束 毫无疑问网格变形是一个神奇的概念然而仍然有太多秘密未被人们所知。它也给一成不变的屏幕带来了更多的乐趣。事实上你可以立即体验一把网格变形的威力。在你的 iOS 设备上点开 Game Center观察气泡的细微变化。这正是 CAMeshTransform 的力量。 我建议你下载 BCMeshTranformView 的示例 app。它包含了几个将网格变换用于丰富界面交互的例子比如简单但强大的 Dribble。要想体验更多关于网格的精彩创意Experiments by Marcus Eckert 是一个不错的地方。 我真心希望 BCMeshTransformView 在 WWDC 2014 的第一天被废弃。Core Animation 能够实现网格变形的更多功能并紧密集成到系统中。尽管目前它还不能正确地处理某些边缘情况还有一些需要完善的地方。希望 6 月 2 号能有好消息传来。 技术交流、商务合作请直接联系博主或者扫码或搜索猿说python
http://www.zqtcl.cn/news/323334/

相关文章:

  • 河南造价信息网官网为什么要做网站优化
  • 网站做个seo要多少钱做公司网站开发的公司
  • 企业网站html模板下载安装的字体wordpress
  • 庙行镇seo推广网站朋友圈的广告推广怎么弄
  • 网站打不开怎么办html怎么做网站背景
  • 厦门网站排名网络服务类型有哪些
  • 如何选择制作网站公司心雨在线高端网站建设专业
  • 山西做网站如何选择2万元最简单装修
  • 广丰区建设局网站友情链接发布网
  • 沧州做网站的专业公司python做网站视频
  • 管理外贸网站模板下载大数据营销优势
  • 做网站的小图标硬盘做网站空间
  • 微信网站界面设计宁波网站优化公司推荐
  • 深圳商城网站开发七冶建设集团网站
  • 广州旅游网站建设设计公司wordpress长文章分页代码
  • 手机营销网站网站的字体
  • 设计网站大全软件互动营销用在哪些推广上面
  • 建设银行网站怎样查询贷款信息吗台州网站制作 外贸
  • 建设网站的步骤知乎app开发定制公司
  • 怎样自己做刷赞网站专业网站设计服务
  • 云主机建站如何让自己做的博客网站上线
  • 目前我们的网站正在建设中做网站违反广告法
  • 有没有做美食的规模网站怎么做国外的网站吗
  • 竭诚网络网站建设开发杭州百度推广
  • 怎样购买起名软件自己做网站小程序制作收费
  • 制作企业网站欢迎界面素材cuntlove wordpress
  • 适合建设网站的国外服务器人工智能培训机构
  • 怎么套网站潜江资讯网招聘信息
  • 网站建设 微信公众号建设网站需要
  • 做房产经纪的那些网站可以进客网站关键词排名如何做