iOS:将视图转换为圆柱形
使用Quartz 2D,我们可以在x
, y
和z
轴上转换视图。
在某些情况下,我们甚至可以通过更改矩阵的值使它们看起来像3D。
我想知道是否可以将视图转换为圆柱形状,如下图所示?
请忽略气缸的顶部。 我更好奇地知道是否有可能像图像中的圆柱体那样扭曲UIView
。
这可能只使用Quartz 2D,图层和变换(不是OpenGL)吗? 如果没有,是否有可能至少在CGContext
绘制它以使视图看起来像这样?
你绝对不能用变换做到这一点。 您可以做的是在屏幕外创建UIView,获取视图的上下文,从中获取图像,然后使用非线性映射将图像映射到新图像。
所以:
- 使用UIGraphicsBeginImageContext()创建图像上下文
- 使用view.layer.renderInContext()在那里渲染视图
- 使用CGBitmapContextCreateImage()获取结果的图像
- 编写一个映射函数,该函数采用x / y屏幕坐标并将它们映射到圆柱体上的坐标。
- 创建一个与屏幕视图大小相同的新图像,并调用映射函数将像素从源复制到目标。
- 将目标位图绘制到屏幕上。
这些步骤都不是特别困难,您可能会想出各种简化方法。 例如,您可以只渲染原始视图的条带,根据圆的坐标偏移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; }