【iOS】用Layer创建一个三维模型以及拖动

three.js 指定在某一平面上拖拽。拖拽吸附在某个平面 使用的api DragControls 该接口作用为:拖拽时会在摄像机视角垂直的平面上移动,即以摄像机视角方向为法向量的一个平面。 它是如何实现的在摄像机对着的屏幕移动的 文件位置:three/examples/jsm/controls/DragControls 内部代码 //新建一个平面 const _plane = new Plane(); ... //鼠标按下 function onPointerDown( event ){ ... //设置平面的法向量和点 //将摄像机(_camera)的世界 阅读详情


关于CALayer的介绍以及基本属性,在这篇博客中有交代:CoreAnimation —— CALayer


这篇博客讲述简单的通过对layer的transform属性的设置一个CATransform3D来进行自定义三维图形,甚至后续的处理。

通常简单的仿射变换我们也是通过对其的transform属性进行设置。不过这里设置的是一个3D变换类。如果线性代数很好的话,那应该能够理解内部具体做了如何的矩阵运算。


首先我子类化一个UIView对象,把图形的绘制在这个自定义View上进行。


接口方面

@property (nonatomic, assign, readonly) CGFloat side;
@property (nonatomic, assign, readonly) BOOL autoAnimate;

/**
 *  创建一个正方体对象
 *
 *  @param frame   位置
 *  @param side    边长
 *  @param animate 创建后是否自动旋转展示
 *
 *  @return 正方体对象视图
 */
+ (HRCube *)cube3DWithFrame:(CGRect)frame side:(CGFloat)side autoAnimate:(BOOL)animate;

工厂方法的实现就是快速实例化并设置属性

+ (HRCube *)cube3DWithFrame:(CGRect)frame side:(CGFloat)side autoAnimate:(BOOL)animate
{
    HRCube *cube3D = [[HRCube alloc] initWithFrame:frame];
    cube3D.side = side;
    cube3D.autoAnimate = animate;
    
    return cube3D;
}


类别中有两个内部成员

CALayer *_cubeLayer; //main layer
GLKMatrix4 _rotMatrix;


第一个是我们需要绘制正方体的layer。

第二个是在导入GLKit框架后,从中引入的一个矩阵变换类,我们在触摸屏幕拖动时,需要使用到这个类对正方体进行旋转处理。


初始化主layer

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        _cubeLayer = [CALayer layer];
        _cubeLayer.frame = self.bounds;
        _cubeLayer.contentsScale = [UIScreen mainScreen].scale;
    }
    return self;
}


正式绘制正方体

- (void)setSide:(CGFloat)side
{
    _side = side;
    
//    NSLog(@"%@", NSStringFromCGRect(_cubeLayer.bounds));
    
    //正
    [self addCubeLayer:@[@0, @0, @(_side/2), @0, @0, @0, @0]];
    //背
    [self addCubeLayer:@[@0, @0, @(-_side/2), @(M_PI), @0, @0, @0]];
    //左
    [self addCubeLayer:@[@(-_side/2), @0, @0, @(-M_PI_2), @0, @1, @0]];
    //右
    [self addCubeLayer:@[@(_side/2), @0, @0, @(M_PI_2), @0, @1, @0]];
    //上
    [self addCubeLayer:@[@0, @(-_side/2), @0, @(-M_PI_2), @1, @0, @0]];
    //下
    [self addCubeLayer:@[@0, @(_side/2), @0, @(M_PI_2), @1, @0, @0]];
    
    CATransform3D transform3D = CATransform3DIdentity;
    transform3D.m34 = -1.0/2000;
    _cubeLayer.sublayerTransform = transform3D;
    
    [self.layer addSublayer:_cubeLayer];
}

这里的m34不是星体- -,3D变形矩阵的m34通常应该设置为-1/EYE_DISTANCE,这里设置为2000已经足够好。


addCubeLayer的实现

//添加sublayers
- (void)addCubeLayer:(NSArray *)params
{
    CAGradientLayer *gradient = [CAGradientLayer layer];
    gradient.contentsScale = [UIScreen mainScreen].scale;
    gradient.bounds = CGRectMake(0, 0, _side, _side);
    gradient.position = self.center;
    gradient.colors = @[(id)kGrayColor, (id)kBlackColor];
    gradient.locations = @[@0, @1];
    gradient.startPoint = CGPointMake(0, 0);
    gradient.endPoint = CGPointMake(0, 1);
    //抗锯齿
    gradient.shouldRasterize = YES;
    
    CATransform3D trans3D = CATransform3DMakeTranslation([params[0] floatValue], [params[1] floatValue], [params[2] floatValue]);
    CATransform3D rotate3D = CATransform3DRotate(trans3D , [params[3] floatValue], [params[4] floatValue], [params[5] floatValue], [params[6] floatValue]);
    CATransform3D transform3D = rotate3D;
//    CATransform3D transform3D = CATransform3DRotate(trans3D, [params[3] floatValue], [params[4] floatValue], [params[5] floatValue], [params[6] floatValue]);
    
    gradient.transform = transform3D;
    
    [_cubeLayer addSublayer:gradient];
}

这里为了更方便观察,使用的是渐变Layer,颜色为宏,可以自由修改。

注意给其抗锯齿设为了YES。通常我们还可以在整个项目的info.plist文件中设置该内容,不过设置会对整个项目的性能产生不好的影响,所以一般来说,需要的时候再设置也是一个不错的选择。


这样我们就简单的创建好了一个正方体,不过当前摆放很正,所以只能看到一个正方形平面,下面我们给他设置自动旋转后给他一个沿着坐标轴的角度偏转,再无限围着y轴转就OK了。

//添加自定义旋转展示动画
- (void)addAnimation
{
    _cubeLayer.sublayerTransform = CATransform3DRotate(_cubeLayer.sublayerTransform, M_PI/9.0, 0.5, 0.5, 0.5);
    
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"sublayerTransform.rotation.y"];
    animation.toValue = @(MAXFLOAT);
    animation.duration = MAXFLOAT;
    [_cubeLayer addAnimation:animation forKey:@"rotation"];
}

这时运行程序我们就能看到一个旋转的三维正方体了



下面给其扩展一个拖动收拾旋转功能

首先给view增加一个拖动收拾,然后在Action中实现

#pragma mark - PanGesture
- (void)panRotate:(UIPanGestureRecognizer *)ges
{
    static CGPoint start;
    if (ges.state == UIGestureRecognizerStateBegan) {
        start = [ges locationInView:self];
    } else if (ges.state == UIGestureRecognizerStateChanged) {
        CATransform3D transform = _cubeLayer.sublayerTransform;
        _rotMatrix = GLKMatrix4MakeWithArray((void *)&transform);
        
        CGPoint loc = [ges locationInView:self];
        CGPoint diff = CGPointMake(start.x-loc.x, start.y-loc.y);
        
        float rotX = 1 * GLKMathDegreesToRadians(diff.y/2.0);
        float rotY = -1 * GLKMathDegreesToRadians(diff.x/2.0);
        
        bool isInvertible;
        GLKVector3 xAxis = GLKMatrix4MultiplyVector3(GLKMatrix4Invert(_rotMatrix, &isInvertible),
                                                     GLKVector3Make(1, 0, 0));
        _rotMatrix = GLKMatrix4Rotate(_rotMatrix, rotX, xAxis.x, xAxis.y, xAxis.z);
        GLKVector3 yAxis = GLKMatrix4MultiplyVector3(GLKMatrix4Invert(_rotMatrix, &isInvertible),
                                                     GLKVector3Make(0, 1, 0));
        _rotMatrix = GLKMatrix4Rotate(_rotMatrix, rotY, yAxis.x, yAxis.y, yAxis.z);
        
        _cubeLayer.sublayerTransform = *((CATransform3D *)&_rotMatrix);
        
        start = loc;
    }
}

经过对矩阵的实时处理后,我们可以使用拖动收拾来在视图中实时的调整3D正方体的旋转了。


Demo源码:

优快云:点击打开链接

GitHub:Rannie / HRCube3D

喜欢的话可以去点个星:)



以上就是本篇博客全部内容,欢迎指正和交流。转载注明出处~


iOS使用动画连贯过渡界面转换 本博向大家演示如何通过添加动画,为原有界面元素变换增加连贯的过渡效果.为UI代码一丝动态与活力感. 缘起 第三方的一个图片裁剪器,拿过来做了几点修改: 将其封装到动态库中,方便集成 扩充了一些功能,比如等待菊花和是否允许进行裁剪等 用封装好的动态库创建了一个ImageCropRow类,这样就可以在Eureka中方便的使用了 大致就是如此,细节不必深究,现在的效果是这个样子的: 总体符合本... 阅读详情

相关推荐

实现鼠标动态吸附线条的js代码

这个js文件实现了鼠标放在页面上,就可以动态吸附线条的动画效果,将js文件放在<body></body>里面引入[removed][removed]就可以实现效果了

学习ios Metal(5)—三维模型线框图WireFrame的绘制

       metal的基础知识入门,首推Metal By Example系列:http://metalbyexample.com/。博主的相关文章,主要给出工程实际遇到的典型问题及其解决方案。                                                                                      (a)无遮挡        ...

sjy234sjy234的博客 1472

iOS-3D模型展示

关于iOS的3D模型展示Demo, 可以直接使用,直接下载就好了

three模型吸附

three模型吸附.将两个模型或多个模型拼装成一个模型然后导出

weixin_45299046的博客 1217

LayaMiniGame:LayaBox小游戏框架,更加方便简洁

迷你游戏 介绍 Laya小游戏框架 简化了LayaBox的工作流程,更加方便的使用各个工具开发小游戏。 参与贡献 YaYaLuoYa: :

基于WebGL/Threejs技术 模型测量项目实战

针对webgl的库threejs框架的模型测量功能实战项目详细的讲解,带大家一起开发实用的功能,在项目中能真正能应用的功能,主要包括三维中模型的距离测量、角度测量、面积测量、体积测量和功能的交互测量值实时显示测量值单位转换等等。

three js捕捉对齐

u012483043的博客 1340

可拖动图片弹出层插件layer.js.zip

可拖动图片弹出层插件layer.js

d3.js 旋转图形_从简单到复杂三维图形渲染管线

一、什么是三维图形渲染管线3D Graphics Rendering Pipeline1、三维3D,三维空间的简称。在笛卡尔空间坐标系内,一般使用x、y、z三个分量表示一个位置。2、图形图形:Graphic,用一组指令集合来描述内容,如描述构成该图的各种图元几何数据、绘制方法等。因为图形对象中有丰富的结构、形状和造型数据,图形对象可以进行丰富的变换而不会失真。图像:Image,用有限的像素栅格及颜...

weixin_39553904的博客 577

SDR实战(四)-AD9361使用手册(三)

本节定义了并行数据端口和串行外设接口(SPI),它们使得AD9361与基带处理器(BBP)之间能够传输数据和控制/状态信息。图63展示了这些接口,并提供了AD9361和BBP在宽带无线系统中使用方式的高级概述。数据接口以两种模式之一运行:兼容标准CMOS模式或兼容低压差分信号(LVDS)模式。每个接口都具有以下部分描述的独特特性。使用CMOS模式时:保持了单端-CMOS逻辑兼容性。可以使用一个或两个数据端口。使用两个端口可以提高数据吞吐量。

hutx0924的博客 6245

视频预处理--经典方法卷积3D

在三维卷积操作中,卷积核不仅在空间维度上滑动,还在时间维度上滑动,从而同时捕捉时间和空间上的特征。通过合理设置步长和填充,可以灵活控制输出特征图的大小和特征提取的效果。你的理解非常准确:三维卷积核就像是一个长度为 3 的滑动窗口,每次选取 3 个连续的帧进行卷积操作,而步长和填充则进一步优化了这一过程。

m0_73359068的博客 1649

IOS端拖动的问题

解决bootstrap-table在IOS端不能X轴拖动的问题

追风少年的博客 1245

R链式中介:如何一次性生成4个变量所有可能的链式中介结果?(含结果解读与粗略作图)#bruceR#ggplot2

一次性生成4个变量所能生成的24种链式中介并作图

weixin_64183017的博客 3236

图片折叠效果:Layer的contentsRect属性和渐变层

图片折叠效果:Layer的contentsRect属性和渐变层 2015-07-22 08:59 编辑: suiling 分类:iOS开发 来源:啊崢的简书 作者:@吖了个峥 授权本站转载。 前言 此次文章,讲述的是Layer的一个属性contentsRect,利用它可以控制图层内容的展示,然后还有利用渐变层(CAGradientLayer)做阴影效

qq_29810535的博客 693

开源ISP实战(1)——基于Zynq7020的Vivado工程移植与调试

本文详细介绍了将开源ISP项目移植到正点原子Zynq7020开发板的实战过程。重点阐述了在Vivado中进行工程创建、IP核导入、Block Design框架搭建、时钟配置与管脚约束修改等关键步骤,并提供了系统联调与常见问题的排查思路,为FPGA图像处理开发者提供了完整的移植与调试指南。

weixin_29191081的博客 200

用VINS-Fusion跑通EuRoC数据集:Ubuntu22.04+ROS2环境下的保姆级评测指南

本文详细介绍了在Ubuntu22.04和ROS2 Humble环境下使用VINS-Fusion处理EuRoC数据集的完整流程。从环境配置、数据集转换到参数调优和性能评估,提供了一套全面的多传感器融合分析方案,帮助开发者在无人机精准定位场景中实现高效部署与优化。

weixin_29212867的博客 517

去除layer改变frame的动画效果

我的view有添加layer层,我在拖动tableview时需要动态改变这个view的大小,此时它的layer会出现动画效果  这与view的大小改变搭起来十分不协调。[CATransaction begin]; [CATransaction setDisableActions:YES]; _myLayer.frame = xxxxx; [CATransaction commit];...

同酱 3008

偏最小二乘结构方程(PLS-SEM)_TomatoSCI分析日记

①模型整体拟合指标(Goodness-of-Fit, GOF),这个可以看做整体的R方了,上限是1;②指标载荷的具体值;然而,当数据中包含潜变量(即由多个观测指标组合而成的综合概念)时,贝叶斯结构方程不太适用。指标过少(1-2 个)会削弱潜变量的解释力,而指标过多可能增加噪声,影响模型稳定性。如果指标较多,可考虑进一步划分潜变量,但应确保每个指标有意义。掌握这两类方法后,在处理多变量、因果或路径分析研究时,可以根据数据特点与研究需求灵活选择。对于一般的多变量研究,这两类结构方程均为常用且有效的分析方案。

qq_44684643的博客 2011

拖动层并播放动画

拖动层并播放动画 在下面的示例中,用手势拖动Layer转动,当手势结束时,会播放动画继续让Layer沿着圆的轨道转动一会儿。 这里包括两个动作,以及针对这两个动作的处理。即: pan手势,即拖动,这时不播放动画,要确保Layer的运动是按照圆的轨迹来移动,而不是拖动到哪里到哪里pan手势的结束,其实应该用swipe手势,这里是简单的监控到pan手势

leewolf 936

京东豆自动领取脚本配置教程

腾讯云/阿里云服务器(Docker环境):全自动跑脚本领京豆(无需本地代理,使用加速源)

AIOT魔法师 860

【tessy】软件环境配置:Keil C51 Keil uVision UVSC (Default)

本文详细说明了tessy软件如何配置【Keil C51 Keil uVision UVSC (Default)】环境,具体操作步骤和注意事项

qq_37282365的博客 600

ios Image裁剪成圆形的方法

1、通过image mask来操作,需要添加mask目标图片。 mask方法 + (UIImage*) maskImage:(UIImage*)image withMask:(UIImage*)mask {    CGImageRef imgRef = [image CGImage];CGImageRef maskRef = [mask CGImage];CGImageRef ac

逢个场,作个戏 2308

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

拖动 DIV

<br />以前在网上看到的最简单的拖动对象的代码,忘记作者叫什么了。原始代码在IE下有些小问题,并且声明了文档类型为xhtml 1.0后,在FF等非IE浏览器下无效,对其进行了改进,现在已经可兼容:IE、Firefox、Opera ... <br />以下代码只是演示原理,具体应用请结合你自己的实际需求进行修改。 <br /><html > <br /><head> <br /><title> 代码实例:拖动对象 Drag Object (兼容:IE、Firefox、Opera ... )</title>

YoursLan的专栏 397

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

iOS图片折叠效果:Layer的contentsRect属性和渐变层

http://www.cocoachina.com/ios/20150722/12622.html 作者:@吖了个峥授权本站转载。 前言 此次文章,讲述的是Layer的一个属性contentsRect,利用它可以控制图层内容的展示,然后还有利用渐变层(CAGradientLayer)做阴影效果。 如果喜欢我的文章,可以关注我,随着后续不断学习Swift中,陆续还会有更新ing.......

weixin_30827565的博客 191

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

上一篇: CoreImage的使用及常见滤镜工具(一)
下一篇: UIImage常用的分类
RannieR
博客等级 码龄14年 180粉丝 68原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值