paint.setColor(Color.RED);
paint.setStrokeWidth(5);
drawPoint(canvas, carBodyOrigPos, paint);
canvas.restore();
//变化点
canvas.save();
canvas.translate(1000,50);
canvas.drawBitmapMesh(bitmapCarBody, carBodyWidthPart, carBodyHeightPart, carBodyNewsPos, 0, null, 0, paint);
paint.setColor(Color.RED);
paint.setStrokeWidth(5);
drawPoint(canvas, carBodyNewsPos, paint);
canvas.restore();
}
- 左边的是原始点所画出来的,右边是变化后所画出来的,因为这里没有对点进行偏移所以左右是一样的。还有要注意的一点,绘制drawBitmapMesh是没有传入绘制的起始点,因为他默认是从原始点开始绘制,所以这里有把坐标移动的代码。
4. 尝试加点扭曲
既然要形变要扭曲,那么我们先对carBodyNewsPos这个点集进行肆意妄为地操作一下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.setDrawFilter(paintFlagsDrawFilter);
//原始点
canvas.save();
canvas.translate(50,50);
canvas.drawBitmapMesh(bitmapCarBody, carBodyWidthPart, carBodyHeightPart, carBodyOrigPos, 0, null, 0, paint);
paint.setColor(Color.RED);
paint.setStrokeWidth(5);
drawPoint(canvas, carBodyOrigPos, paint);
canvas.restore();
//遍历交点,修改
for (int i = 0; i < carBodyPartCount; i++) {
int x = i * 2;
int y = x + 1;
carBodyNewsPos[x] = carBodyOrigPos[x] * (changeFactor * 1.0f / 100 + 1);
}
//变化点
canvas.save();
canvas.translate(1000,50);
canvas.drawBitmapMesh(bitmapCarBody, carBodyWidthPart, carBodyHeightPart, carBodyNewsPos, 0, null, 0, paint);
paint.setColor(Color.RED);
paint.setStrokeWidth(5);
drawPoint(canvas, carBodyNewsPos, paint);
canvas.restore();
}
我们对每一个点应用了:carBodyNewsPos[x] = carBodyOrigPos[x] * (changeFactor * 1.0f / 100 + 1)
:
5. 车厢的扭曲实现
仔细观察车厢的动画,发现有几点细节:
- 扭曲可以分解为x,y轴的扭曲,其叠加一起就是车厢的动画
- 车厢和车顶的扭曲一样,不用的是扭曲度
- x轴的扭曲,以车厢的中心轴为分界线,左边向左扭曲,右边向右扭曲
- x轴方向的拉伸,离x中心轴线越近变化越小,离顶部(y=0)越近,变化也越小
- y轴的扭曲,是以y=0为中心轴,离x中心轴线越近变化越大,离顶部(y=0)越近,变化也越小
因为我们是依次遍历点集,就是从i=0一直到i=posCount,那么我们来实现一下上面的变化:
- 设定两个因子:xFactor和yFactor,控制x,y轴方向的最大扭曲度。
- 设定变化因子changeFactor,带动扭曲度随着时间而变化
- 当点的x在x中心轴的左边,其x坐标应该是原始坐标减去扭曲度,反之亦然
大致得到X方向的扭曲度:changeFactor*Math.abs((widthPart+1)/2-i%(widthPart+1))*(origPos[y]/bitmap.getHeight()) * xFactor;
- xFactor是控制整个扭曲度的大小
- 顶部(y=0)越近,变化也越小,而因为是从y=0开始绘制,所以,
bitmap.getHeight()
就是y轴的最大值,那么,origPos[y]/bitmap.getHeight()
就是当前点所占y轴的百分比,也就是,离y=0越近,origPos[y]/bitmap.getHeight()
的值越小。 - 离x周轴线越近变化越小,
Math.abs((widthPart+1)/2-i%(widthPart+1))
如上图,红色为x的中心轴,而我们遍历的i(点的个数)值是从0-N,而,i=0,i=4的时候最大,i=1,i=3次小,如此类推。 (widthPart+1)/2
是算出中心轴的坐标相对位置,例如图中,算出应该是2,那么中心轴的相对位置则为2,而i%(widthPart+1)
,在图中就是,0-4的取值,跟中心轴的相对位置2相减取绝对值,就是一个离中心轴的变化量的大小了。
Y方向的扭曲度,也是一样的。这里就不说了。。。最后得出的扭曲函数如下:
/**
- 改变车厢的Points
- @param bitmap bitmap
- @param posCount 点的个数
- @param widthPart 横向分割的份数
- @param heightPart 纵向分割的份数
- @param newPos 新点集合
- @param origPos 原始点集合
- @param xFactor 变化因子
- @param yFactor 变化因子
/
protected void changeCarBodyPoint(Bitmap bitmap, int posCount, int widthPart, int heightPart, float[] newPos, float[] origPos, float xFactor, float yFactor) {
//遍历交点,修改
for (int i = 0; i < posCount; i++) {
int x = i2;
int y = x + 1;
//x方向的拉伸,离x周轴线越近变化越小,离顶部(y=0)越近,变化也越小
if (newPos[x]<centralAxisX) {
newPos[x] = origPos[x] - changeFactorMath.abs((widthPart+1)/2-i%(widthPart+1))(origPos[y]/bitmap.getHeight()) * xFactor;
}
else if (newPos[x]>centralAxisX) {
newPos[x] = origPos[x] + changeFactorMath.abs((widthPart+1)/2-i%(widthPart+1))(origPos[y]/bitmap.getHeight()) * xFactor;
}
//y方向的拉伸,离x周轴线越近变化越大,离顶部(y=0)越近,变化也越小
newPos[y] = origPos[y] + changeFactor * (widthPart*heightPart/(heightPart+1)+1) * (1 - Math.abs(origPos[x]-centralAxisX)/bitmap.getWidth()) * yFactor;
}
}
把上面的函数应用上去:
是吧,效果差不多就得了吧!(呕心沥血,我的40米长刀呢!)
6. 总结
- 通过这个自定义动画,熟悉了
drawBitmapMesh
的使用 - 车顶也是同样的扭曲动画,只是要调
xFactor
和yFactor
- Demo在这里
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
尾声
最后,我再重复一次,如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究。
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。
最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。
当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。
以上进阶BATJ大厂学习资料可以免费分享给大家,需要完整版的朋友,点这里可以看到全部内容。
-
自行下载直达领取链接:【GitHub】
进阶学习视频
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
69018025)]
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)