二阶贝塞尔曲线实现自定义动态原点


//先上效果图



//这个是圆的自定义view类 AdhesionCircleLoader

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import java.util.ArrayList;
import java.util.List;

/**
 * @author linzewu
 * @date 2016/5/29
 */
public class AdhesionCircleLoader extends View{
    
    /**
     * 宽度
     */
    private int mWidth;

    /**
     * 高度
     */
    private int mHeight;

    /**
     * 大圆
     */
    private Circle mBigCircle = new Circle();

    /**
     * 大圆半径
     */
    private int mBigCircleRadius = 50;

    /**
     * 当前的静态圆半径
     */
    private float mCurrentStaticCircleRadius = mBigCircleRadius / 5;

    /**
     * 静态圆变化半径的最大比率
     */
    private float mMaxStaticCircleRadiusScaleRate = 0.4f;

    /**
     * 静态圆个数
     */
    private static int mStaticCircleCount = 8;

    /**
     * 最大粘连长度
     */
    private float mMaxAdherentLength = 2.5f  * mCurrentStaticCircleRadius;

    /**
     * 静态圆
     */
    private Circle mStaticCircle;

    /**
     * 动态圆
     */
    private Circle mDynamicCircle = new Circle();

    /**
     * 维护静态圆容器
     */
    private List<Circle> mStaticCircles = new ArrayList<Circle>();

    /**
     * 画笔
     */
    private Paint mPaint = new Paint();

    /**
     * 路径
     */
    private Path mPath = new Path();

    /**
     * 默认颜色
     */
    private int mColor = 0xFF4DB9FF;

    /**
     * 构造函数
     *
     * @param context
     */
    public AdhesionCircleLoader(Context context) {
        super(context);
        init();
    }

    /**
     * 构造函数
     *
     * @param context
     * @param attrs
     */
    public AdhesionCircleLoader(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    /**
     * 构造函数
     *
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public AdhesionCircleLoader(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * 初始化
     */
    private void init() {
        
        /* 画笔 */
        mPaint.setColor(mColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAntiAlias(true);

        /* 宽度、高度 */
        mWidth = mHeight = (int)(2 * (mBigCircleRadius + mCurrentStaticCircleRadius * (1 + mMaxStaticCircleRadiusScaleRate)));
        
        /* 大圆 */
        mBigCircle.x = mWidth / 2;
        mBigCircle.y = mHeight / 2;
        mBigCircle.radius = mBigCircleRadius;
        
        /* 动态圆 */
        mDynamicCircle.radius = mCurrentStaticCircleRadius * 3 / 4;;
        mDynamicCircle.x = mBigCircle.x;
        mDynamicCircle.y = mCurrentStaticCircleRadius * (1 + mMaxStaticCircleRadiusScaleRate);

        
        /* 静态圆 */
        for (int i = 0; i < mStaticCircleCount; i++) {
            mStaticCircle = new Circle();
            mStaticCircle.radius = mCurrentStaticCircleRadius;
            mStaticCircle.x = (float)(mBigCircle.x + mBigCircleRadius * Math.cos(Math.toRadians(45 * i)));
            mStaticCircle.y = (float)(mBigCircle.y + mBigCircleRadius * Math.sin(Math.toRadians(45 * i)));
            mStaticCircles.add(mStaticCircle);
        }
        
        /* 开始动画 */
        startAnim();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(resolveSizeAndState(mWidth, widthMeasureSpec, MeasureSpec.UNSPECIFIED), resolveSizeAndState(mHeight, heightMeasureSpec, MeasureSpec.UNSPECIFIED));
    }

    @Override
    protected void onDraw(Canvas canvas) {

        /* 动态圆 */
        canvas.drawCircle(mDynamicCircle.x, mDynamicCircle.y, mDynamicCircle.radius, mPaint);
        
        /* 静态圆 */
        for (int i = 0; i < mStaticCircleCount; i++) {
            mStaticCircle = mStaticCircles.get(i);
            
            /* 判断哪个圆可以作贝塞尔曲线 */
            if (doAdhere(i)) {
                canvas.drawCircle(mStaticCircle.x, mStaticCircle.y, mCurrentStaticCircleRadius, mPaint);
                //drawAdherentBody(canvas, i);
                Path path = Adhesion.drawAdhesionBody(mStaticCircle.x,mStaticCircle.y,
                        mCurrentStaticCircleRadius,45,
                        mDynamicCircle.x, mDynamicCircle.y, mDynamicCircle.radius,45);
                canvas.drawPath(path, mPaint);
            } else {
                canvas.drawCircle(mStaticCircle.x, mStaticCircle.y, mStaticCircle.radius, mPaint);
            }
        }
    }
    
    /**
     * 判断粘连范围,动态改变静态圆大小
     *
     * @param position
     * @return
     */
    private boolean doAdhere(int position) {

        mStaticCircle = mStaticCircles.get(position);
        
        /* 半径变化 */
        float distance = (float) Math.sqrt(Math.pow(mDynamicCircle.x - mStaticCircle.x, 2) + Math.pow(mDynamicCircle.y - mStaticCircle.y, 2));
        float scale = mMaxStaticCircleRadiusScaleRate -  mMaxStaticCircleRadiusScaleRate * (distance / mMaxAdherentLength);
        mCurrentStaticCircleRadius = mStaticCircle.radius * (1 + scale);
        
        /* 判断是否可以作贝塞尔曲线 */
        if (distance < mMaxAdherentLength)
            return true;
        else
            return false;
    }

    /**
     * 开始动画
     */
    private void startAnim() {
        /* 角度 */
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(-90, 270);
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.setDuration(2500);
        valueAnimator.setRepeatCount(Animation.INFINITE);
        valueAnimator.start();
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float angle = (float) animation.getAnimatedValue();
                mDynamicCircle.x = (float)(mBigCircle.x + mBigCircleRadius * Math.cos(Math.toRadians(angle)));
                mDynamicCircle.y = (float)(mBigCircle.y + mBigCircleRadius * Math.sin(Math.toRadians(angle)));
                invalidate();
            }
        });
    }

    public void setColor(int color) {
        mColor = color;
        mPaint.setColor(mColor);
    }

    /**
     * 圆类
     */
    private class Circle {
        public float x;
        public float y;
        public float radius;
    }

}


//这个是横线的类

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import java.util.ArrayList;
import java.util.List;
public class AdhesionCircleLoader extends View{
    
    /**
     * 宽度
     */
    private int mWidth;

    /**
     * 高度
     */
    private int mHeight;

    /**
     * 大圆
     */
    private Circle mBigCircle = new Circle();

    /**
     * 大圆半径
     */
    private int mBigCircleRadius = 50;

    /**
     * 当前的静态圆半径
     */
    private float mCurrentStaticCircleRadius = mBigCircleRadius / 5;

    /**
     * 静态圆变化半径的最大比率
     */
    private float mMaxStaticCircleRadiusScaleRate = 0.4f;

    /**
     * 静态圆个数
     */
    private static int mStaticCircleCount = 8;

    /**
     * 最大粘连长度
     */
    private float mMaxAdherentLength = 2.5f  * mCurrentStaticCircleRadius;

    /**
     * 静态圆
     */
    private Circle mStaticCircle;

    /**
     * 动态圆
     */
    private Circle mDynamicCircle = new Circle();

    /**
     * 维护静态圆容器
     */
    private List<Circle> mStaticCircles = new ArrayList<Circle>();

    /**
     * 画笔
     */
    private Paint mPaint = new Paint();

    /**
     * 路径
     */
    private Path mPath = new Path();

    /**
     * 默认颜色
     */
    private int mColor = 0xFF4DB9FF;

    /**
     * 构造函数
     *
     * @param context
     */
    public AdhesionCircleLoader(Context context) {
        super(context);
        init();
    }

    /**
     * 构造函数
     *
     * @param context
     * @param attrs
     */
    public AdhesionCircleLoader(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    /**
     * 构造函数
     *
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public AdhesionCircleLoader(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * 初始化
     */
    private void init() {
        
        /* 画笔 */
        mPaint.setColor(mColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAntiAlias(true);

        /* 宽度、高度 */
        mWidth = mHeight = (int)(2 * (mBigCircleRadius + mCurrentStaticCircleRadius * (1 + mMaxStaticCircleRadiusScaleRate)));
        
        /* 大圆 */
        mBigCircle.x = mWidth / 2;
        mBigCircle.y = mHeight / 2;
        mBigCircle.radius = mBigCircleRadius;
        
        /* 动态圆 */
        mDynamicCircle.radius = mCurrentStaticCircleRadius * 3 / 4;;
        mDynamicCircle.x = mBigCircle.x;
        mDynamicCircle.y = mCurrentStaticCircleRadius * (1 + mMaxStaticCircleRadiusScaleRate);

        
        /* 静态圆 */
        for (int i = 0; i < mStaticCircleCount; i++) {
            mStaticCircle = new Circle();
            mStaticCircle.radius = mCurrentStaticCircleRadius;
            mStaticCircle.x = (float)(mBigCircle.x + mBigCircleRadius * Math.cos(Math.toRadians(45 * i)));
            mStaticCircle.y = (float)(mBigCircle.y + mBigCircleRadius * Math.sin(Math.toRadians(45 * i)));
            mStaticCircles.add(mStaticCircle);
        }
        
        /* 开始动画 */
        startAnim();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(resolveSizeAndState(mWidth, widthMeasureSpec, MeasureSpec.UNSPECIFIED), resolveSizeAndState(mHeight, heightMeasureSpec, MeasureSpec.UNSPECIFIED));
    }

    @Override
    protected void onDraw(Canvas canvas) {

        /* 动态圆 */
        canvas.drawCircle(mDynamicCircle.x, mDynamicCircle.y, mDynamicCircle.radius, mPaint);
        
        /* 静态圆 */
        for (int i = 0; i < mStaticCircleCount; i++) {
            mStaticCircle = mStaticCircles.get(i);
            
            /* 判断哪个圆可以作贝塞尔曲线 */
            if (doAdhere(i)) {
                canvas.drawCircle(mStaticCircle.x, mStaticCircle.y, mCurrentStaticCircleRadius, mPaint);
                //drawAdherentBody(canvas, i);
                Path path = Adhesion.drawAdhesionBody(mStaticCircle.x,mStaticCircle.y,
                        mCurrentStaticCircleRadius,45,
                        mDynamicCircle.x, mDynamicCircle.y, mDynamicCircle.radius,45);
                canvas.drawPath(path, mPaint);
            } else {
                canvas.drawCircle(mStaticCircle.x, mStaticCircle.y, mStaticCircle.radius, mPaint);
            }
        }
    }
    
    /**
     * 判断粘连范围,动态改变静态圆大小
     *
     * @param position
     * @return
     */
    private boolean doAdhere(int position) {

        mStaticCircle = mStaticCircles.get(position);
        
        /* 半径变化 */
        float distance = (float) Math.sqrt(Math.pow(mDynamicCircle.x - mStaticCircle.x, 2) + Math.pow(mDynamicCircle.y - mStaticCircle.y, 2));
        float scale = mMaxStaticCircleRadiusScaleRate -  mMaxStaticCircleRadiusScaleRate * (distance / mMaxAdherentLength);
        mCurrentStaticCircleRadius = mStaticCircle.radius * (1 + scale);
        
        /* 判断是否可以作贝塞尔曲线 */
        if (distance < mMaxAdherentLength)
            return true;
        else
            return false;
    }

    /**
     * 开始动画
     */
    private void startAnim() {
        /* 角度 */
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(-90, 270);
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.setDuration(2500);
        valueAnimator.setRepeatCount(Animation.INFINITE);
        valueAnimator.start();
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float angle = (float) animation.getAnimatedValue();
                mDynamicCircle.x = (float)(mBigCircle.x + mBigCircleRadius * Math.cos(Math.toRadians(angle)));
                mDynamicCircle.y = (float)(mBigCircle.y + mBigCircleRadius * Math.sin(Math.toRadians(angle)));
                invalidate();
            }
        });
    }

    public void setColor(int color) {
        mColor = color;
        mPaint.setColor(mColor);
    }

    /**
     * 圆类
     */
    private class Circle {
        public float x;
        public float y;
        public float radius;
    }

}

//要实现效果,他们里面都要调用这个类   Adhesion


import android.graphics.Path;

/**
 * 粘合体(二阶贝塞尔曲线)
 * @author linzewu
 * @date 2016/5/23
 */
public class Adhesion {

    /**
     * 知识点:
     *   1弧度=180/π度
     *   Math.toDegrees(double) 转换以弧度为单位测得的角度大致相等的角度,以度衡量。   弧度->角度
     *   Math.toRadians(double) 转换为度大致相等的角度,以弧度为单位的角度。          角度->弧度
     *
     *   注意:Math.sin(double)、Math.cos(double)、Math.tan(double)、Math.atan(double)等方法的参数
     *        均为弧度,所以如果传值来的数为角度,应该先转化为弧度
     *
     *
     *
     *   由于偏移角度为45,因为无论两个圆之间的角度(degree)如何变化
     *   (x1,y1)与(x3,y3)两个点之间的角度差永远为45*2(90)
     *
     */
    
    /**
     * 画粘连体
     * @param cx1     圆心x1
     * @param cy1     圆心y1
     * @param r1      圆半径r1
     * @param offset1 贝塞尔曲线偏移角度offset1
     * @param cx2     圆心x2
     * @param cy2     圆心y2
     * @param r2      圆半径r2
     * @param offset2 贝塞尔曲线偏移角度offset2
     * @return
     */
    public static Path drawAdhesionBody(float cx1, float cy1, float r1, float offset1, float 
            cx2, float cy2, float r2, float offset2) {
        
        /* 求三角函数 */
        float degrees =(float) Math.toDegrees(Math.atan(Math.abs(cy2 - cy1) / Math.abs(cx2 - cx1)));
        
        /* 根据圆1与圆2的相对位置求四个点 */
        float differenceX = cx1 - cx2;
        float differenceY = cy1 - cy2;

        /* 两条贝塞尔曲线的四个端点 */
        float x1,y1,x2,y2,x3,y3,x4,y4;
        
        /* 圆1在圆2的下边 */
        if (differenceX == 0 && differenceY > 0) {
            x2 = cx2 - r2 * (float) Math.sin(Math.toRadians(offset2));
            y2 = cy2 + r2 * (float) Math.cos(Math.toRadians(offset2));
            x4 = cx2 + r2 * (float) Math.sin(Math.toRadians(offset2));
            y4 = cy2 + r2 * (float) Math.cos(Math.toRadians(offset2));
            x1 = cx1 - r1 * (float) Math.sin(Math.toRadians(offset1));
            y1 = cy1 - r1 * (float) Math.cos(Math.toRadians(offset1));
            x3 = cx1 + r1 * (float) Math.sin(Math.toRadians(offset1));
            y3 = cy1 - r1 * (float) Math.cos(Math.toRadians(offset1));
        }
        /* 圆1在圆2的上边 */
        else if (differenceX == 0 && differenceY < 0) {
            x2 = cx2 - r2 * (float) Math.sin(Math.toRadians(offset2));
            y2 = cy2 - r2 * (float) Math.cos(Math.toRadians(offset2));
            x4 = cx2 + r2 * (float) Math.sin(Math.toRadians(offset2));
            y4 = cy2 - r2 * (float) Math.cos(Math.toRadians(offset2));
            x1 = cx1 - r1 * (float) Math.sin(Math.toRadians(offset1));
            y1 = cy1 + r1 * (float) Math.cos(Math.toRadians(offset1));
            x3 = cx1 + r1 * (float) Math.sin(Math.toRadians(offset1));
            y3 = cy1 + r1 * (float) Math.cos(Math.toRadians(offset1));
        }
        /* 圆1在圆2的右边 */
        else if (differenceX > 0 && differenceY == 0) {
            x2 = cx2 + r2 * (float) Math.cos(Math.toRadians(offset2));
            y2 = cy2 + r2 * (float) Math.sin(Math.toRadians(offset2));
            x4 = cx2 + r2 * (float) Math.cos(Math.toRadians(offset2));
            y4 = cy2 - r2 * (float) Math.sin(Math.toRadians(offset2));
            x1 = cx1 - r1 * (float) Math.cos(Math.toRadians(offset1));
            y1 = cy1 + r1 * (float) Math.sin(Math.toRadians(offset1));
            x3 = cx1 - r1 * (float) Math.cos(Math.toRadians(offset1));
            y3 = cy1 - r1 * (float) Math.sin(Math.toRadians(offset1));
        } 
        /* 圆1在圆2的左边 */
        else if (differenceX < 0 && differenceY == 0 ) {
            x2 = cx2 - r2 * (float) Math.cos(Math.toRadians(offset2));
            y2 = cy2 + r2 * (float) Math.sin(Math.toRadians(offset2));
            x4 = cx2 - r2 * (float) Math.cos(Math.toRadians(offset2));
            y4 = cy2 - r2 * (float) Math.sin(Math.toRadians(offset2));
            x1 = cx1 + r1 * (float) Math.cos(Math.toRadians(offset1));
            y1 = cy1 + r1 * (float) Math.sin(Math.toRadians(offset1));
            x3 = cx1 + r1 * (float) Math.cos(Math.toRadians(offset1));
            y3 = cy1 - r1 * (float) Math.sin(Math.toRadians(offset1));
        }
        /* 圆1在圆2的右下角 */
        else if (differenceX > 0 && differenceY > 0) {
            x2 = cx2 - r2 * (float) Math.cos(Math.toRadians(180 - offset2 - degrees));
            y2 = cy2 + r2 * (float) Math.sin(Math.toRadians(180 - offset2 - degrees));
            x4 = cx2 + r2 * (float) Math.cos(Math.toRadians(degrees - offset2));
            y4 = cy2 + r2 * (float) Math.sin(Math.toRadians(degrees - offset2));
            x1 = cx1 - r1 * (float) Math.cos(Math.toRadians(degrees - offset1));
            y1 = cy1 - r1 * (float) Math.sin(Math.toRadians(degrees - offset1));
            x3 = cx1 + r1 * (float) Math.cos(Math.toRadians(180 - offset1 - degrees));
            y3 = cy1 - r1 * (float) Math.sin(Math.toRadians(180 - offset1 - degrees));
        }
        /* 圆1在圆2的左上角 */
        else if (differenceX < 0 && differenceY < 0) {
            x2 = cx2 - r2 * (float) Math.cos(Math.toRadians(degrees - offset2));
            y2 = cy2 - r2 * (float) Math.sin(Math.toRadians(degrees - offset2));
            x4 = cx2 + r2 * (float) Math.cos(Math.toRadians(180 - offset2 - degrees));
            y4 = cy2 - r2 * (float) Math.sin(Math.toRadians(180 - offset2 - degrees));
            x1 = cx1 - r1 * (float) Math.cos(Math.toRadians(180 - offset1 - degrees));
            y1 = cy1 + r1 * (float) Math.sin(Math.toRadians(180 - offset1 - degrees));
            x3 = cx1 + r1 * (float) Math.cos(Math.toRadians(degrees - offset1));
            y3 = cy1 + r1 * (float) Math.sin(Math.toRadians(degrees - offset1));
        }
        /* 圆1在圆2的左下角 */
        else if (differenceX < 0 && differenceY > 0) {
            x2 = cx2 - r2 * (float) Math.cos(Math.toRadians(degrees - offset2));
            y2 = cy2 + r2 * (float) Math.sin(Math.toRadians(degrees - offset2));
            x4 = cx2 + r2 * (float) Math.cos(Math.toRadians(180 - offset2 - degrees));
            y4 = cy2 + r2 * (float) Math.sin(Math.toRadians(180 - offset2 - degrees));
            x1 = cx1 - r1 * (float) Math.cos(Math.toRadians(180 - offset1 - degrees));
            y1 = cy1 - r1 * (float) Math.sin(Math.toRadians(180 - offset1 - degrees));
            x3 = cx1 + r1 * (float) Math.cos(Math.toRadians(degrees - offset1));
            y3 = cy1 - r1 * (float) Math.sin(Math.toRadians(degrees - offset1));
        }
        /* 圆1在圆2的右上角 */
        else {
            x2 = cx2 - r2 * (float) Math.cos(Math.toRadians(180 - offset2 - degrees));
            y2 = cy2 - r2 * (float) Math.sin(Math.toRadians(180 - offset2 - degrees));
            x4 = cx2 + r2 * (float) Math.cos(Math.toRadians(degrees - offset2));
            y4 = cy2 - r2 * (float) Math.sin(Math.toRadians(degrees - offset2));
            x1 = cx1 - r1 * (float) Math.cos(Math.toRadians(degrees - offset1));
            y1 = cy1 + r1* (float) Math.sin(Math.toRadians(degrees - offset1));
            x3 = cx1 + r1 * (float) Math.cos(Math.toRadians(180 - offset1 - degrees));
            y3 = cy1 + r1 * (float) Math.sin(Math.toRadians(180 - offset1 - degrees));
        }
        
        /* 贝塞尔曲线的控制点 */
        float anchorX1,anchorY1,anchorX2,anchorY2;
        
        /* 圆1大于圆2 */
        if (r1 > r2) {
            anchorX1 = (x2 + x3) / 2;
            anchorY1 = (y2 + y3) / 2;
            anchorX2 = (x1 + x4) / 2;
            anchorY2 = (y1 + y4) / 2;
        }
        /* 圆1小于或等于圆2 */
        else {
            anchorX1 = (x1 + x4) / 2;
            anchorY1 = (y1 + y4) / 2;
            anchorX2 = (x2 + x3) / 2;
            anchorY2 = (y2 + y3) / 2;
        }
        
        /* 画粘连体 */
        Path path = new Path();
        path.reset();
        path.moveTo(x1, y1);
        path.quadTo(anchorX1, anchorY1, x2, y2);
        path.lineTo(x4, y4);
        path.quadTo(anchorX2, anchorY2, x3, y3);
        path.lineTo(x1, y1);
        return path;
    }
}

//最后Main调用

//只需要在布局中调用一下,就是一个自定义view,不用写其他代码,

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.chenqq.Main2Activity">

    <com.example.chenxuqq.progress.AdhesionCircleLoader
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="30dp"/>
    <com.example.chenxuqq.progress.AdhesionHorizontalLoader
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="30dp"/>

</LinearLayout>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值