自定义View小船水上漂-PathMeasure实现

193 阅读1分钟

前言

自定义View的时候,有时会碰到一些轨迹移动之类的需求,比如让某个物体沿着特定的路线移动,通常都是使用Path搭配PathMeasure来实现,比如下面的效果图

看起来蛮有意思的,其实很本质简单,就是小船沿着给定的路线运动,路线就是Path,然后就是使用PathMeasure计算Path相关参数,这篇文章就来讲讲关于PathMeasure的内容,不多BB,先上代码

PS:其实我想先贴PathMeasure API的,但感觉这样文章就太长了,就直接放链接吧

PathMeasure官方文档

PathMeasure API 中文

重点关注下文档中的getLength() 、getPosTan(float distance, float[] pos, float[] tan) 、getMatrix(float distance, Matrix matrix, int flags) ,下面的代码会用到

        mMatrix.reset()
        pathMeasure = PathMeasure(path, false)
        length = pathMeasure.length

        /*
        * 因为路径是不规则的,为了让小船在移动的时候,紧贴着路径,所以我们需要移动小船并旋转一定的角度
        * 为了达到目的,有两种方法
        */

        /*
        //方法一:自己计算
        //获取Path指定点的的位置,和正切值tan
        pathMeasure.getPosTan(boatDx, pos, tan)
        //将tan值通过反三角函数得到对应的弧度,然后将弧度转换成度数
		var degrees : Float = ((Math.atan2(tan[1].toDouble(), tan[0].toDouble())*180f/Math.PI).toFloat())
        //旋转
		mMatrix.postRotate(degrees , bitmap.width/2F, bitmap.height/2F)
        //移动
		mMatrix.postTranslate((pos[0]-bitmap.width/2F).toFloat(), (pos[1]-bitmap.height).toFloat())
		*/

        //方法二:使用API
        //getMatrix(),获取Path指定位置的Matrix
        pathMeasure.getMatrix(boatDx, mMatrix, PathMeasure.TANGENT_MATRIX_FLAG
                or PathMeasure.POSITION_MATRIX_FLAG)
        mMatrix.preTranslate((-bitmap.width / 2).toFloat(), (-bitmap.height).toFloat())
        canvas.drawPath(path, paint)
        canvas.drawBitmap(bitmap, mMatrix, paint)

        circleMatrix.reset()
        circlePathMeasure = PathMeasure(circlePath, false)
        circleLength = circlePathMeasure.length
        circlePathMeasure.getMatrix(circleDx, circleMatrix, PathMeasure.TANGENT_MATRIX_FLAG
                or PathMeasure.POSITION_MATRIX_FLAG)
        circleMatrix.preTranslate((-bitmap.width / 2).toFloat(), (-bitmap.height).toFloat())
        canvas.drawPath(circlePath, paint)
        canvas.drawBitmap(bitmap, circleMatrix, paint)

注意:方法一和方法二中的postTranslate()和preTranslate()的区别,这里涉及到矩阵Matrix相关的知识点,可以看着这篇文章Android Matrix 详解

完整项目代码