SeniorUI1004_小船破浪效果

本文详细介绍了如何使用PathMeasure和Animation结合贝塞尔曲线在自定义View中实现波浪动画效果。通过具体代码示例,展示了如何创建波浪路径,利用PathMeasure获取坐标斜率信息,并据此绘制动态图片。

SeniorUI_目录
SeniorUI1001_PathMeasure语法

一、Rendering

在这里插入图片描述

二、Principe

  • Path利用贝塞尔曲线画波浪
  • Animation实现动画间隔值
  • PathMeasure利用Animation的值获取对应位置坐标斜率信息
  • 利用获取的信息绘制图片

三、Core Code

public class WaveView extends View {

    private static final int INT_WAVE_LENGTH = 1000;
    private static final String TAG = "WaveView";

    private Path mPath;
    private Paint mPaint;

    private int mDeltaX;
    private Bitmap mBitMap;
    private PathMeasure mPathMeasure;
    private float[] pos;
    private float[] tan;
    private Matrix mMatrix;
    private float faction;

    public WaveView(Context context) {
        super(context);
        init();
        
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);

        mPath = new Path();
        pos = new float[2];
        tan = new float[2];
        mMatrix = new Matrix();

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize =  2;
        mBitMap = BitmapFactory.decodeResource(getResources(), R.drawable.timg,options);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPath.reset();
        int orginY = 800;
        int halfWaveLength = INT_WAVE_LENGTH / 2;
        mPath.moveTo(-INT_WAVE_LENGTH + mDeltaX, orginY);
        for(int i = -INT_WAVE_LENGTH ; i < getWidth() + INT_WAVE_LENGTH;
            i += INT_WAVE_LENGTH){
            mPath.rQuadTo(halfWaveLength/2,60,halfWaveLength,0);
            mPath.rQuadTo(halfWaveLength/2,-60,halfWaveLength,0);
        }
        mPath.lineTo(getWidth(),getHeight());
        mPath.lineTo(0,getHeight());
        mPath.close();



        canvas.drawPath(mPath,mPaint);

        mPathMeasure = new PathMeasure(mPath,false);
        float length = mPathMeasure.getLength();
        mMatrix.reset();
        boolean posTan = mPathMeasure.getPosTan(length*faction,pos,tan);
        Log.d(TAG,"pos[0] = " + pos[0] + "pos[1] = " +pos[1]);
        Log.d(TAG,"tan[0] = " + tan[0] + "tan[1] = " +tan[1]);
        if(posTan){
            // 方案一 :自己计算
            // 将tan值通过反正切函数得到对应的弧度,在转化成对应的角度度数
            /*float degrees = (float) (Math.atan2(tan[1],tan[0])*180f / Math.PI);
            mMatrix.postRotate(degrees, mBitMap.getWidth()/2, mBitMap.getHeight() / 2);
            mMatrix.postTranslate(pos[0]- mBitMap.getWidth() / 2,pos[1] - mBitMap.getHeight());
            canvas.drawBitmap(mBitMap,mMatrix,mPaint);*/

            // 方案一 :直接使用API
            mPathMeasure.getMatrix(length*faction, mMatrix, PathMeasure.TANGENT_MATRIX_FLAG | PathMeasure.POSITION_MATRIX_FLAG);
            mMatrix.preTranslate(- mBitMap.getWidth() / 2, - mBitMap.getHeight());
            canvas.drawBitmap(mBitMap,mMatrix,mPaint);
        }

        //

    }

    public void startAnimation(){
        /*ValueAnimator animator = ValueAnimator.ofInt(0,INT_WAVE_LENGTH);
        animator.setDuration(1000);
        animator.setInterpolator(new LinearInterpolator());
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mDeltaX = (int) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        animator.start();*/

        ValueAnimator animator = ValueAnimator.ofFloat(0,1);
        animator.setDuration(25000);
        animator.setInterpolator(new LinearInterpolator());
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                faction  = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        animator.start();
    }

}

四、Demo

WaveViewActivity

【事件触发一致性】研究多智能体网络如何通过分布式事件驱动控制实现有限时间内的共识(Matlab代码实现)内容概要:本文围绕多智能体网络中的事件触发一致性问题,研究如何通过分布式事件驱动控制实现有限时间内的共识,并提供了相应的Matlab代码实现方案。文中探讨了事件触发机制在降低通信负担、提升系统效率方面的优势,重点分析了多智能体系统在有限时间收敛的一致性控制策略,涉及系统模型构建、触发条件设计、稳定性与收敛性分析等核心技术环节。此外,文档还展示了该技术在航空航天、电力系统、机器人协同、无人机编队等多个前沿领域的潜在应用,体现了其跨学科的研究价值和工程实用性。; 适合人群:具备一定控制理论基础和Matlab编程能力的研究生、科研人员及从事自动化、智能系统、多智能体协同控制等相关领域的工程技术人员。; 使用场景及目标:①用于理解和实现多智能体系统在有限时间内达成一致的分布式控制方法;②为事件触发控制、分布式优化、协同控制等课题提供算法设计与仿真验证的技术参考;③支撑科研项目开发、学术论文复现及工程原型系统搭建; 阅读建议:建议结合文中提供的Matlab代码进行实践操作,重点关注事件触发条件的设计逻辑与系统收敛性证明之间的关系,同时可延伸至其他应用场景进行二次开发与性能优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值