iOS:将视图转换为圆柱形

使用Quartz 2D,我们可以在xyz轴上转换视图。

在某些情况下,我们甚至可以通过更改矩阵的值使它们看起来像3D。

我想知道是否可以将视图转换为圆柱形状,如下图所示?

在此处输入图像描述

请忽略气缸的顶部。 我更好奇地知道是否有可能像图像中的圆柱体那样扭曲UIView

这可能只使用Quartz 2D,图层和变换(不是OpenGL)吗? 如果没有,是否有可能至少在CGContext绘制它以使视图看起来像这样?

你绝对不能用变换做到这一点。 您可以做的是在屏幕外创建UIView,获取视图的上下文,从中获取图像,然后使用非线性映射将图像映射到新图像。

所以:

  1. 使用UIGraphicsBeginImageContext()创建图像上下文
  2. 使用view.layer.renderInContext()在那里渲染视图
  3. 使用CGBitmapContextCreateImage()获取结果的图像
  4. 编写一个映射函数,该函数采用x / y屏幕坐标并将它们映射到圆柱体上的坐标。
  5. 创建一个与屏幕视图大小相同的新图像,并调用映射函数将像素从源复制到目标。
  6. 将目标位图绘制到屏幕上。

这些步骤都不是特别困难,您可能会想出各种简化方法。 例如,您可以只渲染原始视图的条带,根据圆的坐标偏移Y坐标,如果您可以不进行透视变换。

如果您希望视图实际上是交互式的,那么在处理触摸事件时您需要以相反的方向进行转换。

不,你不能使用变换弯曲视图。

变换只能操纵视图的四个角,所以无论你做什么,它仍然是一个平面。

我意识到这超出了Quartz2D …您可以尝试添加SceneKit。

  • 通过UIGraphicsBeginImageContext(),view.layer.renderInContext(),CGBitmapContextCreateImage()获取视图的图像。
  • 创建一个SCNMaterial,其diffuse属性设置为视图的图像
  • 创建一个SCNCylinder并将材料应用于它。
  • 将圆柱体添加到SCNScene。
  • 创建SCNView并设置其场景。
  • 将SCNView添加到视图层次结构中。

参考: 在iOS上使用OpenGL ES 2.0,如何在两点之间绘制圆柱体?

我也为我的一个项目使用了相同的代码:

检查这个提到的地方画锥形 ; 它是过时的,但在适应算法后,它的工作原理。

请参阅下面的代码以获得解 Self表示网格并包含顶点,索引等。

 - (instancetype)initWithOriginRadius:(CGFloat)originRadius atOriginPoint:(GLKVector3)originPoint andEndRadius:(CGFloat)endRadius atEndPoint:(GLKVector3)endPoint withPrecision:(NSInteger)precision andColor:(GLKVector4)color { self = [super init]; if (self) { // normal pointing from origin point to end point GLKVector3 normal = GLKVector3Make(originPoint.x - endPoint.x, originPoint.y - endPoint.y, originPoint.z - endPoint.z); // create two perpendicular vectors - perp and q GLKVector3 perp = normal; if (normal.x == 0 && normal.z == 0) { perp.x += 1; } else { perp.y += 1; } // cross product GLKVector3 q = GLKVector3CrossProduct(perp, normal); perp = GLKVector3CrossProduct(normal, q); // normalize vectors perp = GLKVector3Normalize(perp); q = GLKVector3Normalize(q); // calculate vertices CGFloat twoPi = 2 * PI; NSInteger index = 0; for (NSInteger i = 0; i < precision + 1; i++) { CGFloat theta = ((CGFloat) i) / precision * twoPi; // go around circle and get points // normals normal.x = cosf(theta) * perp.x + sinf(theta) * qx; normal.y = cosf(theta) * perp.y + sinf(theta) * qy; normal.z = cosf(theta) * perp.z + sinf(theta) * qz; AGLKMeshVertex meshVertex; AGLKMeshVertexDynamic colorVertex; // top vertex meshVertex.position.x = endPoint.x + endRadius * normal.x; meshVertex.position.y = endPoint.y + endRadius * normal.y; meshVertex.position.z = endPoint.z + endRadius * normal.z; meshVertex.normal = normal; meshVertex.originalColor = color; // append vertex [self appendVertex:meshVertex]; // append color vertex colorVertex.colors = color; [self appendColorVertex:colorVertex]; // append index [self appendIndex:index++]; // bottom vertex meshVertex.position.x = originPoint.x + originRadius * normal.x; meshVertex.position.y = originPoint.y + originRadius * normal.y; meshVertex.position.z = originPoint.z + originRadius * normal.z; meshVertex.normal = normal; meshVertex.originalColor = color; // append vertex [self appendVertex:meshVertex]; // append color vertex [self appendColorVertex:colorVertex]; // append index [self appendIndex:index++]; } // draw command [self appendCommand:GL_TRIANGLE_STRIP firstIndex:0 numberOfIndices:self.numberOfIndices materialName:@""]; } return self; }