Android中的Matrix(矩阵)
大家好,又见面了,我是你们的朋友全栈君。
写在前面
看这篇笔记之前先看一下参考文章,这篇笔记没有系统的讲述矩阵和代码的东西,参考文章写的也有错误的地方,要辨证的看。
矩阵的乘法
比如有矩阵A和矩阵B,他们分别为:
可以看到A为2行3列的矩阵,B为3行2列的矩阵,矩阵乘法符合下面的规则:
- 只有A的列数和B的行数相等,A和B才可以做乘法
- A*B的结果C是2行2列的矩阵,行数等于A的行数,列数等于B的列数
- 结果矩阵C的第一行第一列数值为A的第一行和B的第一列中的数字分别相乘后再相加。其他行列结果依次类推
- 矩阵的乘法不满足交换律,即
A*B != B*A
- 矩阵的乘法满足结合律
M‘ = T*(M*R) = T*M*R = (T*M)*R
详细信息可以看这里:如何计算矩阵乘法
Android中常用的四种矩阵变换
Android中使用3×3的矩阵进行图形的变换,它看起来大概是下面这样:
在Android中,使用一个3×1的矩阵来表示一个点:
x,y分别代表x,y轴上的坐标,而1代表屏幕在z轴上的坐标为默认的。如果将1变大,那么屏幕会拉远, 图形会变小。
平移(Translate)
图例:
错切(Skew)
水平错切
图例:
垂直错切
图例:
复合错切
图例:
旋转(Rotate)
图例:
缩放(Scale)
图例:
Matrix的组合
应用矩阵进行图形变换的主要原因,是因为矩阵是可以通过矩阵的乘法进行组合使用的,如果想对canvas绘制的bitmap时,先平移T(dx, dy),再旋转R(θ),最后缩放S(k1,k2),就可以将三个变换矩阵相乘,M‘ = ABC,再对canvas应用M’矩阵即可。
Matrix的坐标系
矩阵的操作可以看作是以坐标原点为原点的坐标系在三维空间中做的变换,不同于canvas的屏幕坐标系坐标系,矩阵Matrix的坐标系为左手坐标系:
这个坐标系对应的每个轴的旋转方向(从原点看出去,每个轴的旋转方向都是逆时针):
Matrix的操作可以看做是对上面左手坐标系的变换
因为Matrix变换后是对每个canvas的点起作用,其实也可以看做对这个三维坐标系起了作用,canvas绘制的是三维坐标系上的图像对canvas二位坐标系的投影。
所以,可以用自己的左手模拟进行平移旋转等操作,更加直观的想象变换后的效果。
Matrix的左乘和右乘
在Android中,有关矩阵的操作都是成对的,比如preTranslate(float dx, float dy)和postTranslate(float dx, float dy),通过看api的介绍,如果原矩阵为M,那么pre表示的是左乘,post表示右乘:
preTranslate : M’ = M * T(dx, dy) // 左乘 postTranslate: M’ = T(dx, dy) * M // 右乘
因为矩阵的变换是顺序执行的,所以在平时最常用的应该是pre左乘,所有的变换操作都依次执行,比如canvas常用的translate等变换方法其实就是左乘。右乘其实就是在所有操作之前增加一步操作,合理的运用右乘可以方便代码的编写。
比如:图形变换是以左边原点为原点的,所以旋转、缩放等功能应用到canvas.drawBitmap()方法时(因为bitmap常从原点往右下方画),图像表现出来的结果就特别奇怪,需要将canvas的坐标系移动到图像的中心点再操作然后再把坐标系移回去,那么如果只用pre左乘的话,代码是这样的:
Matrix matrix = new Matrix();
matrix.preTranslate(pivotX,pivotY);
// 各种操作,旋转,缩放,错切等,可以执行多次。
matrix.preTranslate(-pivotX, -pivotY);
如果合理使用右乘,那么代码就成了:
Matrix matrix = new Matrix();
// 各种操作,旋转,缩放,错切等,可以执行多次。
matrix.postTranslate(pivotX,pivotY);
matrix.preTranslate(-pivotX, -pivotY);
减少了postTranslate和preTranslate之间的距离。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/155028.html原文链接:https://javaforall.cn
相关文章
- android onresume方法,非静态方法’onResume’Android Studio
- android+制作开机动画,Android 开机动画制作详解
- android开机动画多长时间_Android开机动画及黑屏[通俗易懂]
- android移动点餐系统内容和要求,基于Android云计算的移动点餐系统
- android 混淆不起作用,Android代码混淆的写法总结
- android onresume方法,Android onActivityResult()和onResume()的执行顺序
- Android UI设计
- android 安装p12证书,如何在Android中使用p12证书(客户端证书)
- android sdk根目录,Android SDK位置
- android 定时器实例,Android定时器和Handler用法实例分析
- android短信验证码代码,Android短信验证码自动填写实现代码
- Android Studio Dolphin | 2021.3.1不显示布局XML预览
- Android修改字体_android设置字体样式
- Android平台GB28181设备接入模块摄像头采集方向不对怎么办?
- 深入学习Android
- 【Android 热修复】热修复原理 ( 类加载分析 | 分析 PathClassLoader 源码 | 分析 BaseDexClassLoader 源码 | 分析 PathDexList 源码 )
- 【Android 逆向】启动 DEX 字节码中的 Activity 组件 ( 替换 LoadedApk 中的类加载器 | 加载 DEX 文件中的 Activity 类并启动成功 )
- 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | RawDexFile.cpp 分析 | dvmRawDexFileOpen函数读取 DEX 文件 )
- 【Android UI】贝塞尔曲线 ④ ( 使用 android.graphics.Path 提供的 cubicTo 方法绘制三阶贝塞尔曲线示例 )
- 【Android Gradle 插件】组件化中的 Gradle 构建脚本实现 ⑤ ( 优化 Gradle 构建脚本 | 构建脚本结构 | 闭包定义及用法 | 依赖配置 | android 块配置 )
- 【错误记录】Android Studio 编译报错 ( Could not resolve com.android.tools.build:gradle:7.4.2. )
- Android 程序崩溃 后台handle处理类详解手机开发
- android判断服务是否是运行状态详解编程语言
- 谷歌正在为Android 12原生版开发单手模式 照顾某些小型安卓设备制造商
- Android应当从iOS处窃取的五大最佳功能
- android版本检测Android程序的版本检测与更新实现介绍
- android开发教程之startActivityForResult使用方法