android 翻页动态效果,android酷炫翻页效果+图形分析

packagesf.hmg.turntest;importandroid.content.Context;importandroid.graphics.Bitmap;importandroid.graphics.Canvas;importandroid.graphics.ColorMatrix;importandroid.graphics.ColorMatrixColorFilter;importandroid.graphics.Matrix;importandroid.graphics.Paint;importandroid.graphics.Path;importandroid.graphics.PointF;importandroid.graphics.Region;importandroid.graphics.drawable.GradientDrawable;importandroid.view.MotionEvent;importandroid.view.View;importandroid.widget.Scroller;publicclassPageWidgetextendsView {privatestaticfinalString TAG="hmg";privateintmWidth=480;privateintmHeight=800;privateintmCornerX=0;//拖拽点对应的页脚privateintmCornerY=0;privatePath mPath0;privatePath mPath1;

Bitmap mCurPageBitmap=null;//当前页Bitmap mNextPageBitmap=null;

PointF mTouch=newPointF();//拖拽点PointF mBezierStart1=newPointF();//贝塞尔曲线起始点PointF mBezierControl1=newPointF();//贝塞尔曲线控制点PointF mBeziervertex1=newPointF();//贝塞尔曲线顶点PointF mBezierEnd1=newPointF();//贝塞尔曲线结束点PointF mBezierStart2=newPointF();//另一条贝塞尔曲线PointF mBezierControl2=newPointF();

PointF mBeziervertex2=newPointF();

PointF mBezierEnd2=newPointF();floatmMiddleX;floatmMiddleY;floatmDegrees;floatmTouchToCornerDis;

ColorMatrixColorFilter mColorMatrixFilter;

Matrix mMatrix;float[] mMatrixArray={0,0,0,0,0,0,0,0,1.0f};booleanmIsRTandLB;//是否属于右上左下floatmMaxLength=(float) Math.hypot(mWidth, mHeight);int[] mBackShadowColors;int[] mFrontShadowColors;

GradientDrawable mBackShadowDrawableLR;

GradientDrawable mBackShadowDrawableRL;

GradientDrawable mFolderShadowDrawableLR;

GradientDrawable mFolderShadowDrawableRL;

GradientDrawable mFrontShadowDrawableHBT;

GradientDrawable mFrontShadowDrawableHTB;

GradientDrawable mFrontShadowDrawableVLR;

GradientDrawable mFrontShadowDrawableVRL;

Paint mPaint;

Scroller mScroller;publicPageWidget(Context context) {super(context);//TODO Auto-generated constructor stubmPath0=newPath();

mPath1=newPath();

createDrawable();

mPaint=newPaint();

mPaint.setStyle(Paint.Style.FILL);

ColorMatrix cm=newColorMatrix();floatarray[]={0.55f,0,0,0,80.0f,0,0.55f,0,0,80.0f,0,0,0.55f,0,80.0f,0,0,0,0.2f,0};

cm.set(array);

mColorMatrixFilter=newColorMatrixColorFilter(cm);

mMatrix=newMatrix();

mScroller=newScroller(getContext());

mTouch.x=0.01f;//不让x,y为0,否则在点计算时会有问题mTouch.y=0.01f;

}/*** Author : hmg25 Version: 1.0 Description : 计算拖拽点对应的拖拽脚*/publicvoidcalcCornerXY(floatx,floaty) {if(x<=mWidth/2)

mCornerX=0;elsemCornerX=mWidth;if(y<=mHeight/2)

mCornerY=0;elsemCornerY=mHeight;if((mCornerX==0&&mCornerY==mHeight)||(mCornerX==mWidth&&mCornerY==0))

mIsRTandLB=true;elsemIsRTandLB=false;

}publicbooleandoTouchEvent(MotionEvent event) {//TODO Auto-generated method stubif(event.getAction()==MotionEvent.ACTION_MOVE) {

mTouch.x=event.getX();

mTouch.y=event.getY();this.postInvalidate();

}if(event.getAction()==MotionEvent.ACTION_DOWN) {

mTouch.x=event.getX();

mTouch.y=event.getY();//calcCornerXY(mTouch.x, mTouch.y);//this.postInvalidate();}if(event.getAction()==MotionEvent.ACTION_UP) {if(canDragOver()) {

startAnimation(1200);

}else{

mTouch.x=mCornerX-0.09f;

mTouch.y=mCornerY-0.09f;

}this.postInvalidate();

}//return super.onTouchEvent(event);returntrue;

}/*** Author : hmg25 Version: 1.0 Description : 求解直线P1P2和直线P3P4的交点坐标*/publicPointF getCross(PointF P1, PointF P2, PointF P3, PointF P4) {

PointF CrossP=newPointF();//二元函数通式: y=ax+bfloata1=(P2.y-P1.y)/(P2.x-P1.x);floatb1=((P1.x*P2.y)-(P2.x*P1.y))/(P1.x-P2.x);floata2=(P4.y-P3.y)/(P4.x-P3.x);floatb2=((P3.x*P4.y)-(P4.x*P3.y))/(P3.x-P4.x);

CrossP.x=(b2-b1)/(a1-a2);

CrossP.y=a1*CrossP.x+b1;returnCrossP;

}privatevoidcalcPoints() {

mMiddleX=(mTouch.x+mCornerX)/2;

mMiddleY=(mTouch.y+mCornerY)/2;

mBezierControl1.x=mMiddleX-(mCornerY-mMiddleY)*(mCornerY-mMiddleY)/(mCornerX-mMiddleX);

mBezierControl1.y=mCornerY;

mBezierControl2.x=mCornerX;

mBezierControl2.y=mMiddleY-(mCornerX-mMiddleX)*(mCornerX-mMiddleX)/(mCornerY-mMiddleY);//Log.i("hmg", "mTouchX  " + mTouch.x + "  mTouchY  " + mTouch.y);//Log.i("hmg", "mBezierControl1.x  " + mBezierControl1.x//+ "  mBezierControl1.y  " + mBezierControl1.y);//Log.i("hmg", "mBezierControl2.x  " + mBezierControl2.x//+ "  mBezierControl2.y  " + mBezierControl2.y);mBezierStart1.x=mBezierControl1.x-(mCornerX-mBezierControl1.x)/2;

mBezierStart1.y=mCornerY;//当mBezierStart1.x  480时//如果继续翻页,会出现BUG故在此限制if(mTouch.x>0&&mTouch.xmWidth) {if(mBezierStart1.x<0)

mBezierStart1.x=mWidth-mBezierStart1.x;floatf1=Math.abs(mCornerX-mTouch.x);floatf2=mWidth*f1/mBezierStart1.x;

mTouch.x=Math.abs(mCornerX-f2);floatf3=Math.abs(mCornerX-mTouch.x)*Math.abs(mCornerY-mTouch.y)/f1;

mTouch.y=Math.abs(mCornerY-f3);

mMiddleX=(mTouch.x+mCornerX)/2;

mMiddleY=(mTouch.y+mCornerY)/2;

mBezierControl1.x=mMiddleX-(mCornerY-mMiddleY)*(mCornerY-mMiddleY)/(mCornerX-mMiddleX);

mBezierControl1.y=mCornerY;

mBezierControl2.x=mCornerX;

mBezierControl2.y=mMiddleY-(mCornerX-mMiddleX)*(mCornerX-mMiddleX)/(mCornerY-mMiddleY);//Log.i("hmg", "mTouchX --> " + mTouch.x + "  mTouchY-->  "//+ mTouch.y);//Log.i("hmg", "mBezierControl1.x--  " + mBezierControl1.x//+ "  mBezierControl1.y -- " + mBezierControl1.y);//Log.i("hmg", "mBezierControl2.x -- " + mBezierControl2.x//+ "  mBezierControl2.y -- " + mBezierControl2.y);mBezierStart1.x=mBezierControl1.x-(mCornerX-mBezierControl1.x)/2;

}

}

mBezierStart2.x=mCornerX;

mBezierStart2.y=mBezierControl2.y-(mCornerY-mBezierControl2.y)/2;

mTouchToCornerDis=(float) Math.hypot((mTouch.x-mCornerX),

(mTouch.y-mCornerY));

mBezierEnd1=getCross(mTouch, mBezierControl1, mBezierStart1,

mBezierStart2);

mBezierEnd2=getCross(mTouch, mBezierControl2, mBezierStart1,

mBezierStart2);//Log.i("hmg", "mBezierEnd1.x  " + mBezierEnd1.x + "  mBezierEnd1.y  "//+ mBezierEnd1.y);//Log.i("hmg", "mBezierEnd2.x  " + mBezierEnd2.x + "  mBezierEnd2.y  "//+ mBezierEnd2.y);/** mBeziervertex1.x 推导

* ((mBezierStart1.x+mBezierEnd1.x)/2+mBezierControl1.x)/2 化简等价于

* (mBezierStart1.x+ 2*mBezierControl1.x+mBezierEnd1.x) / 4*/mBeziervertex1.x=(mBezierStart1.x+2*mBezierControl1.x+mBezierEnd1.x)/4;

mBeziervertex1.y=(2*mBezierControl1.y+mBezierStart1.y+mBezierEnd1.y)/4;

mBeziervertex2.x=(mBezierStart2.x+2*mBezierControl2.x+mBezierEnd2.x)/4;

mBeziervertex2.y=(2*mBezierControl2.y+mBezierStart2.y+mBezierEnd2.y)/4;

}privatevoiddrawCurrentPageArea(Canvas canvas, Bitmap bitmap, Path path) {

mPath0.reset();

mPath0.moveTo(mBezierStart1.x, mBezierStart1.y);

mPath0.quadTo(mBezierControl1.x, mBezierControl1.y, mBezierEnd1.x,

mBezierEnd1.y);

mPath0.lineTo(mTouch.x, mTouch.y);

mPath0.lineTo(mBezierEnd2.x, mBezierEnd2.y);

mPath0.quadTo(mBezierControl2.x, mBezierControl2.y, mBezierStart2.x,

mBezierStart2.y);

mPath0.lineTo(mCornerX, mCornerY);

mPath0.close();

canvas.save();

canvas.clipPath(path, Region.Op.XOR);

canvas.drawBitmap(bitmap,0,0,null);

canvas.restore();

}privatevoiddrawNextPageAreaAndShadow(Canvas canvas, Bitmap bitmap) {

mPath1.reset();

mPath1.moveTo(mBezierStart1.x, mBezierStart1.y);

mPath1.lineTo(mBeziervertex1.x, mBeziervertex1.y);

mPath1.lineTo(mBeziervertex2.x, mBeziervertex2.y);

mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);

mPath1.lineTo(mCornerX, mCornerY);

mPath1.close();

mDegrees=(float) Math.toDegrees(Math.atan2(mBezierControl1.x-mCornerX, mBezierControl2.y-mCornerY));intleftx;intrightx;

GradientDrawable mBackShadowDrawable;if(mIsRTandLB) {

leftx=(int) (mBezierStart1.x);

rightx=(int) (mBezierStart1.x+mTouchToCornerDis/4);

mBackShadowDrawable=mBackShadowDrawableLR;

}else{

leftx=(int) (mBezierStart1.x-mTouchToCornerDis/4);

rightx=(int) mBezierStart1.x;

mBackShadowDrawable=mBackShadowDrawableRL;

}

canvas.save();

canvas.clipPath(mPath0);

canvas.clipPath(mPath1, Region.Op.INTERSECT);

canvas.drawBitmap(bitmap,0,0,null);

canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);

mBackShadowDrawable.setBounds(leftx, (int) mBezierStart1.y, rightx,

(int) (mMaxLength+mBezierStart1.y));

mBackShadowDrawable.draw(canvas);

canvas.restore();

}publicvoidsetBitmaps(Bitmap bm1, Bitmap bm2) {

mCurPageBitmap=bm1;

mNextPageBitmap=bm2;

}publicvoidsetScreen(intw,inth) {

mWidth=w;

mHeight=h;

}

@OverrideprotectedvoidonDraw(Canvas canvas) {

canvas.drawColor(0xFFAAAAAA);

calcPoints();

drawCurrentPageArea(canvas, mCurPageBitmap, mPath0);

drawNextPageAreaAndShadow(canvas, mNextPageBitmap);

drawCurrentPageShadow(canvas);

drawCurrentBackArea(canvas, mCurPageBitmap);

}/*** Author : hmg25 Version: 1.0 Description : 创建阴影的GradientDrawable*/privatevoidcreateDrawable() {int[] color={0x333333,0xb0333333};

mFolderShadowDrawableRL=newGradientDrawable(

GradientDrawable.Orientation.RIGHT_LEFT, color);

mFolderShadowDrawableRL

.setGradientType(GradientDrawable.LINEAR_GRADIENT);

mFolderShadowDrawableLR=newGradientDrawable(

GradientDrawable.Orientation.LEFT_RIGHT, color);

mFolderShadowDrawableLR

.setGradientType(GradientDrawable.LINEAR_GRADIENT);

mBackShadowColors=newint[] {0xff111111,0x111111};

mBackShadowDrawableRL=newGradientDrawable(

GradientDrawable.Orientation.RIGHT_LEFT, mBackShadowColors);

mBackShadowDrawableRL.setGradientType(GradientDrawable.LINEAR_GRADIENT);

mBackShadowDrawableLR=newGradientDrawable(

GradientDrawable.Orientation.LEFT_RIGHT, mBackShadowColors);

mBackShadowDrawableLR.setGradientType(GradientDrawable.LINEAR_GRADIENT);

mFrontShadowColors=newint[] {0x80111111,0x111111};

mFrontShadowDrawableVLR=newGradientDrawable(

GradientDrawable.Orientation.LEFT_RIGHT, mFrontShadowColors);

mFrontShadowDrawableVLR

.setGradientType(GradientDrawable.LINEAR_GRADIENT);

mFrontShadowDrawableVRL=newGradientDrawable(

GradientDrawable.Orientation.RIGHT_LEFT, mFrontShadowColors);

mFrontShadowDrawableVRL

.setGradientType(GradientDrawable.LINEAR_GRADIENT);

mFrontShadowDrawableHTB=newGradientDrawable(

GradientDrawable.Orientation.TOP_BOTTOM, mFrontShadowColors);

mFrontShadowDrawableHTB

.setGradientType(GradientDrawable.LINEAR_GRADIENT);

mFrontShadowDrawableHBT=newGradientDrawable(

GradientDrawable.Orientation.BOTTOM_TOP, mFrontShadowColors);

mFrontShadowDrawableHBT

.setGradientType(GradientDrawable.LINEAR_GRADIENT);

}/*** Author : hmg25 Version: 1.0 Description : 绘制翻起页的阴影*/publicvoiddrawCurrentPageShadow(Canvas canvas) {doubledegree;if(mIsRTandLB) {

degree=Math.PI/4-Math.atan2(mBezierControl1.y-mTouch.y, mTouch.x-mBezierControl1.x);

}else{

degree=Math.PI/4-Math.atan2(mTouch.y-mBezierControl1.y, mTouch.x-mBezierControl1.x);

}//翻起页阴影顶点与touch点的距离doubled1=(float)25*1.414*Math.cos(degree);doubled2=(float)25*1.414*Math.sin(degree);floatx=(float) (mTouch.x+d1);floaty;if(mIsRTandLB) {

y=(float) (mTouch.y+d2);

}else{

y=(float) (mTouch.y-d2);

}

mPath1.reset();

mPath1.moveTo(x, y);

mPath1.lineTo(mTouch.x, mTouch.y);

mPath1.lineTo(mBezierControl1.x, mBezierControl1.y);

mPath1.lineTo(mBezierStart1.x, mBezierStart1.y);

mPath1.close();floatrotateDegrees;

canvas.save();

canvas.clipPath(mPath0, Region.Op.XOR);

canvas.clipPath(mPath1, Region.Op.INTERSECT);intleftx;intrightx;

GradientDrawable mCurrentPageShadow;if(mIsRTandLB) {

leftx=(int) (mBezierControl1.x);

rightx=(int) mBezierControl1.x+25;

mCurrentPageShadow=mFrontShadowDrawableVLR;

}else{

leftx=(int) (mBezierControl1.x-25);

rightx=(int) mBezierControl1.x+1;

mCurrentPageShadow=mFrontShadowDrawableVRL;

}

rotateDegrees=(float) Math.toDegrees(Math.atan2(mTouch.x-mBezierControl1.x, mBezierControl1.y-mTouch.y));

canvas.rotate(rotateDegrees, mBezierControl1.x, mBezierControl1.y);

mCurrentPageShadow.setBounds(leftx,

(int) (mBezierControl1.y-mMaxLength), rightx,

(int) (mBezierControl1.y));

mCurrentPageShadow.draw(canvas);

canvas.restore();

mPath1.reset();

mPath1.moveTo(x, y);

mPath1.lineTo(mTouch.x, mTouch.y);

mPath1.lineTo(mBezierControl2.x, mBezierControl2.y);

mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);

mPath1.close();

canvas.save();

canvas.clipPath(mPath0, Region.Op.XOR);

canvas.clipPath(mPath1, Region.Op.INTERSECT);if(mIsRTandLB) {

leftx=(int) (mBezierControl2.y);

rightx=(int) (mBezierControl2.y+25);

mCurrentPageShadow=mFrontShadowDrawableHTB;

}else{

leftx=(int) (mBezierControl2.y-25);

rightx=(int) (mBezierControl2.y+1);

mCurrentPageShadow=mFrontShadowDrawableHBT;

}

rotateDegrees=(float) Math.toDegrees(Math.atan2(mBezierControl2.y-mTouch.y, mBezierControl2.x-mTouch.x));

canvas.rotate(rotateDegrees, mBezierControl2.x, mBezierControl2.y);floattemp;if(mBezierControl2.y<0)

temp=mBezierControl2.y-mHeight;elsetemp=mBezierControl2.y;inthmg=(int) Math.hypot(mBezierControl2.x, temp);if(hmg>mMaxLength)

mCurrentPageShadow

.setBounds((int) (mBezierControl2.x-25)-hmg, leftx,

(int) (mBezierControl2.x+mMaxLength)-hmg,

rightx);elsemCurrentPageShadow.setBounds(

(int) (mBezierControl2.x-mMaxLength), leftx,

(int) (mBezierControl2.x), rightx);//Log.i("hmg", "mBezierControl2.x   " + mBezierControl2.x//+ "  mBezierControl2.y  " + mBezierControl2.y);mCurrentPageShadow.draw(canvas);

canvas.restore();

}/*** Author : hmg25 Version: 1.0 Description : 绘制翻起页背面*/privatevoiddrawCurrentBackArea(Canvas canvas, Bitmap bitmap) {inti=(int) (mBezierStart1.x+mBezierControl1.x)/2;floatf1=Math.abs(i-mBezierControl1.x);inti1=(int) (mBezierStart2.y+mBezierControl2.y)/2;floatf2=Math.abs(i1-mBezierControl2.y);floatf3=Math.min(f1, f2);

mPath1.reset();

mPath1.moveTo(mBeziervertex2.x, mBeziervertex2.y);

mPath1.lineTo(mBeziervertex1.x, mBeziervertex1.y);

mPath1.lineTo(mBezierEnd1.x, mBezierEnd1.y);

mPath1.lineTo(mTouch.x, mTouch.y);

mPath1.lineTo(mBezierEnd2.x, mBezierEnd2.y);

mPath1.close();

GradientDrawable mFolderShadowDrawable;intleft;intright;if(mIsRTandLB) {

left=(int) (mBezierStart1.x-1);

right=(int) (mBezierStart1.x+f3+1);

mFolderShadowDrawable=mFolderShadowDrawableLR;

}else{

left=(int) (mBezierStart1.x-f3-1);

right=(int) (mBezierStart1.x+1);

mFolderShadowDrawable=mFolderShadowDrawableRL;

}

canvas.save();

canvas.clipPath(mPath0);

canvas.clipPath(mPath1, Region.Op.INTERSECT);

mPaint.setColorFilter(mColorMatrixFilter);floatdis=(float) Math.hypot(mCornerX-mBezierControl1.x,

mBezierControl2.y-mCornerY);floatf8=(mCornerX-mBezierControl1.x)/dis;floatf9=(mBezierControl2.y-mCornerY)/dis;

mMatrixArray[0]=1-2*f9*f9;

mMatrixArray[1]=2*f8*f9;

mMatrixArray[3]=mMatrixArray[1];

mMatrixArray[4]=1-2*f8*f8;

mMatrix.reset();

mMatrix.setValues(mMatrixArray);

mMatrix.preTranslate(-mBezierControl1.x,-mBezierControl1.y);

mMatrix.postTranslate(mBezierControl1.x, mBezierControl1.y);

canvas.drawBitmap(bitmap, mMatrix, mPaint);//canvas.drawBitmap(bitmap, mMatrix, null);mPaint.setColorFilter(null);

canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);

mFolderShadowDrawable.setBounds(left, (int) mBezierStart1.y, right,

(int) (mBezierStart1.y+mMaxLength));

mFolderShadowDrawable.draw(canvas);

canvas.restore();

}publicvoidcomputeScroll() {super.computeScroll();if(mScroller.computeScrollOffset()) {floatx=mScroller.getCurrX();floaty=mScroller.getCurrY();

mTouch.x=x;

mTouch.y=y;

postInvalidate();

}

}privatevoidstartAnimation(intdelayMillis) {intdx, dy;//dx 水平方向滑动的距离,负值会使滚动向左滚动//dy 垂直方向滑动的距离,负值会使滚动向上滚动if(mCornerX>0) {

dx=-(int) (mWidth+mTouch.x);

}else{

dx=(int) (mWidth-mTouch.x+mWidth);

}if(mCornerY>0) {

dy=(int) (mHeight-mTouch.y);

}else{

dy=(int) (1-mTouch.y);//防止mTouch.y最终变为0}

mScroller.startScroll((int) mTouch.x, (int) mTouch.y, dx, dy,

delayMillis);

}publicvoidabortAnimation() {if(!mScroller.isFinished()) {

mScroller.abortAnimation();

}

}publicbooleancanDragOver() {if(mTouchToCornerDis>mWidth/10)returntrue;returnfalse;

}/*** Author : hmg25 Version: 1.0 Description : 是否从左边翻向右边*/publicbooleanDragToRight() {if(mCornerX>0)returnfalse;returntrue;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于 Echarts 实现全国地图的动态效果,可以使用 Echarts 提供的动画和事件绑定功能,结合自己的业务需求进行实现。 下面是一个简单的示例代码: ```javascript // 创建一个 Echarts 实例 var myChart = echarts.init(document.getElementById('main')); // 定义地图的数据 var geoCoordMap = { '北京': [116.46, 39.92], '上海': [121.48, 31.22], '广州': [113.23, 23.16], '深圳': [114.07, 22.62], '杭州': [119.50, 30.25] }; // 定义某些城市的数据 var data = [ {name: '北京', value: 100}, {name: '上海', value: 200}, {name: '广州', value: 300}, {name: '深圳', value: 400}, {name: '杭州', value: 500} ]; // 定义地图的样式 var option = { // 地图的背景色 backgroundColor: '#404a59', // 地图的样式 geo: { map: 'china', label: { emphasis: { show: false } }, roam: true, itemStyle: { normal: { areaColor: '#323c48', borderColor: '#111' }, emphasis: { areaColor: '#2a333d' } } }, // 数据的样式 series: [ { name: '城市', type: 'effectScatter', coordinateSystem: 'geo', data: data.map(function (item) { return { name: item.name, value: geoCoordMap[item.name].concat([item.value]) }; }), symbolSize: function (val) { return val[2] / 10; }, showEffectOn: 'emphasis', rippleEffect: { brushType: 'stroke' }, hoverAnimation: true, label: { normal: { formatter: '{b}', position: 'right', show: true } }, itemStyle: { normal: { color: '#46bee9' } } } ] }; // 设置地图的配置项并渲染地图 myChart.setOption(option); // 地图的动态效果 myChart.on('click', function (params) { // 点击某个城市时的操作 console.log(params); }); ``` 通过设置不同的数据和样式,可以实现各种不同的地图效果。同时,Echarts 还提供了丰富的文档和示例,可以帮助开发者更好地理解和使用它的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值