Android 裁剪 几何变换

canvas.clipRect(left , top ,right,bottom) 裁切函数

canvas.clipPath() // 切割图形

clipOutRect / clipOutPath 切出,切出的是不需要的

clipPath(path) 切出来会有毛边 锯齿,会把指定范围的显示出来,其他的不显示,按像素px进行裁切

如果需要精细显示 可以使用xfermode

canvas 几何变换(改变坐标系)

translate (x,y) 平移 

rotate(degree) 指定角度旋转

scale(x,y) 缩/放

skew(x,y) 侧切

canvas.tranlate

canvas.drawXXX  先变换 移动 再绘制

canvas.rotate

canvas.translate 先旋转再平移,平移不是按照原先的坐标移动 而是沿着旋转方向的x y 移动

这些操作的是canvas

canvas.scale

canvas.drawXXX 先放缩,然后绘制,绘制时放缩后的位置

Matrix 的几何变换

相比于canvas  它有两套写法 比如 preScale  = canvas.scale /postScale

post 基于变换前的坐标系进行变换

Camera类:

rotate(x,y,z) 旋转 // 旋转最好指定轴心,没有轴心默认会是0,0位置

rotateX

rotateY

rotateZ

三维坐标,X不变,Y轴往上是正向,Z轴为交互点,相当于投影

camera.applyToCanvas(canvas) 绑定

canvas.translate
camera.applyToCanvas(canvas)
canvas.translate

先移动canvas 然后 camera完成后 再移动回来 得到正形 ,思路得相反,canvas 轴心会变换

示例:

canvas.translate(BITMAP_PADDING + BITMAP_SIZE /2, BITMAP_PADDING + BITMAP_SIZE /2, )
camera.applyToCanvas(canvas)
canvas.translate(- (BITMAP_PADDING + BITMAP_SIZE /2),- (BITMAP_PADDING + BITMAP_SIZE /2), ) 

会出现弧形效果 需要改变camera的Z值

camera.setLocation(x,y,z)  z默认-8f  英寸为单位 1英寸= 72像素

手机像素不同,所需要调整的Z轴调整的也不同 需要动态计算

clipRect 裁切需要判断是否进行三维变化或者canvas的x y 是否已经变换

cli[pRect后,只保留裁切的,其他的内容都会丢弃,代码也就执行失效,需要canvas.save

package com.example.androidstudiogiraffe.view

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Camera
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.util.AttributeSet
import android.view.View
import com.example.androidstudiogiraffe.R
import com.future.startstudyproject.utils.dp

private val BITMAP_SIZE = 200.dp
private val BITMAP_PADDING = 100.dp


class CameraView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {

    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val bitmap = getBitmap(BITMAP_SIZE.toInt())
    private val camera = Camera()


    private val path = Path().apply {
        addOval(
            BITMAP_PADDING, BITMAP_PADDING, BITMAP_PADDING + BITMAP_SIZE,
            BITMAP_PADDING + BITMAP_SIZE, Path.Direction.CCW
        )
    }


    init {
        camera.rotateX(12f)
        camera.setLocation(0f, 0f, -6 * resources.displayMetrics.density)
    }

    override fun onDraw(canvas: Canvas) {

//        canvas.clipRect(BITMAP_PADDING, BITMAP_PADDING, BITMAP_PADDING + BITMAP_SIZE /2 .toFloat() ,
//            BITMAP_PADDING + BITMAP_SIZE / 2 .toFloat())
//        canvas.clipPath(path)

        //上
        canvas.save()
        canvas.translate(BITMAP_PADDING + BITMAP_SIZE / 2, BITMAP_PADDING + BITMAP_SIZE / 2)
        canvas.rotate(-30f) //旋转回来

        //旋转
//        canvas.clipRect(
//            -BITMAP_SIZE / 2,
//            -BITMAP_SIZE / 2,
//            BITMAP_SIZE / 2,
//             0f
//        )

        //未旋转
        canvas.clipRect(
            -BITMAP_SIZE ,
            -BITMAP_SIZE,
            BITMAP_SIZE,
            0f
        )
        canvas.rotate(30f) //旋转30度
        canvas.translate(-(BITMAP_PADDING + BITMAP_SIZE / 2), -(BITMAP_PADDING + BITMAP_SIZE / 2))
        canvas.drawBitmap(bitmap, BITMAP_PADDING, BITMAP_PADDING, paint)
        canvas.restore()

        //下
        canvas.save()
        canvas.translate(BITMAP_PADDING + BITMAP_SIZE / 2, BITMAP_PADDING + BITMAP_SIZE / 2)
        canvas.rotate(-30f) //旋转回来
        camera.applyToCanvas(canvas)

//        canvas.clipRect(
//            -BITMAP_SIZE / 2,
//            0f,
//            BITMAP_SIZE / 2,
//            BITMAP_SIZE / 2
//        )

        //未旋转
        canvas.clipRect(
            -BITMAP_SIZE ,
            0f,
            BITMAP_SIZE,
            BITMAP_SIZE
        )
        canvas.rotate(30f) //旋转30度
        canvas.translate(-(BITMAP_PADDING + BITMAP_SIZE / 2), -(BITMAP_PADDING + BITMAP_SIZE / 2))
        canvas.drawBitmap(bitmap, BITMAP_PADDING, BITMAP_PADDING, paint)
        canvas.restore()
    }

    private fun getBitmap(width: Int): Bitmap {
        val option = BitmapFactory.Options()
        option.inJustDecodeBounds = true
        BitmapFactory.decodeResource(resources, R.drawable.head_image, option)
        option.inJustDecodeBounds = false
        option.inDensity = option.outWidth
        option.inTargetDensity = width
        return BitmapFactory.decodeResource(resources, R.drawable.head_image, option)
    }
}

你可能感兴趣的:(android,kotlin)