如何实现范围裁剪和旋转效果。
日常
我还是希望自己的博客能够存在一些温度,而不是冷冰冰的技术分享,我希望留下专属于我自己的个性,就像鸿洋和郭霖的公众号一样。他们会在自己的博客顶端随便写一下最近的新闻什么的,而我不同,虽然我也对时政比较感兴趣,我还是更加倾向于随便写点什么,比如说自己的爱好,动漫什么的。
前言
具体实现结果就是上述的效果,那么我们应该如何实现上述的效果?一如既往,大象装冰箱,分三步怎么进行操作?分而治之即可。
-
获取图片
-
绘制上半部分
-
绘制下半部分
正文
获取图片
图片的获取其实之前已经提到过好多次了,这里就不赘述了。
在继续说后续的操作之前我们需要明确一些细节。首先,我们需要让自己的图片居中于整个视图的中心,这个时候就需要明确一点,我们并不能无脑的从视图的顶端进行绘制,而是需要根据视图中心的位置和图片的高度来动态的计算出开始绘制视图的起始位置,因为在我们的案例中,图片的高度并不确定。
//存储裁剪的范围
private val rect: Rect = Rect()
override fun onDraw(canvas: Canvas) {super.onDraw(canvas)//获取头像图片val bitmap = R.drawable.avatar.getBitmap(context, width / 2)canvas.save()//根据图片的获取结果来动态地设置裁剪范围rect.apply {left = 0//裁剪的顶部位置是:视图的正中央的高度-图片高度/2top = height / 2 - bitmap.height / 2//因为我们这里的用例比较简单,所以可以粗略地直接根据width进行裁剪right = width//裁剪的底部位置是:视图的正中央高度+图片高度/2bottom = height / 2 + bitmap.height / 2}
绘制图片上半部分区域
前面我们已经提到了,我们获取到了图片上半部分的区域位置,现在,我们根据上半部分的区域位置来对绘制位置进行裁剪,然后进行上半部分的视图的绘制操作。
canvas.save()
rect.apply {left = -width / 2top = -height / 2right = width / 2bottom = 0
}
canvas.clipRect(rect)
canvas.translate(-width / 2f, -height / 2f)
canvas.drawBitmap(bitmap, width / 4f, height / 2f - bitmap.height / 2, paint)
canvas.restore()
绘制图片下半部分区域
前面,我们已经完成了上半部分的图片区域的绘制,现在我们将进行图片下半部分区域的绘制。
之前我们已经提到过,图片下半部分区域的绘制是在图片上半部分区域的基础上添加一层画布的平移和旋转效果。
这里我们就需要重新设置裁剪区域。
同理,我们首先依然是需要根据视图中心的位置和图片高度来完成对于图片下半部分的裁剪区域的设置。
然后我们这里就需要定义一个Camera类,这个类的作用的模拟画布的旋转效果,设置一个相机点来作为“光源”,来将旋转后的画布上的图像投影到x0y平面上。这里需要注意的是,canvas.translate()移动的是画布,而不是画布里面的图片;并且图片的绘制并不是是基于x0y坐标轴来绘制的,而是基于画布的坐标轴来进行绘制的。好,说明这些后,我们继续我们的后续操作。我们的Camera存在默认的坐标轴(0,0,-8),Camera的投影方向默认为z轴正方向。
这样一来,因为我们图片的中心并不是(0,0,0),投影就并不会符合我们的意愿。
这个时候就需要在应用camera的旋转效果之前,先对画布进行移动,使图片的中心刚好位于坐标轴远点,然后进行camera的应用,进行画布的翻转,然后在实际绘制图片之前,将画布移动回原来的位置,一切就完成了。如下:
canvas.save()
rect.apply {left = -width / 2top = 0right = width / 2bottom = height / 2
}
canvas.translate(width / 2f, height / 2f)
camera.applyToCanvas(canvas)
canvas.clipRect(rect)
canvas.translate(-width / 2f, -height / 2f)
canvas.drawBitmap(bitmap, width / 4f, height / 2f - bitmap.height / 2, paint)
canvas.restore()
itmap(bitmap, width / 4f, height / 2f - bitmap.height / 2, paint)
canvas.restore()