广告
返回顶部
首页 > 资讯 > 移动开发 >Android实现炫酷的CheckBox效果
  • 722
分享到

Android实现炫酷的CheckBox效果

checkboxAndroid 2022-06-06 07:06:00 722人浏览 八月长安
摘要

首先贴出实现的效果图: gif的效果可能有点过快,在真机上运行的效果会更好一些。我们主要的思路就是利用属性动画来动态地画出选中状态以及对勾的绘制过程。看到上面的效果图,相信大

首先贴出实现的效果图:

gif的效果可能有点过快,在真机上运行的效果会更好一些。我们主要的思路就是利用属性动画来动态地画出选中状态以及对勾的绘制过程。看到上面的效果图,相信大家都迫不及待地要跃跃欲试了,那就让我们开始吧。

自定义View的第一步:自定义属性。


<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="SmoothCheckBox">
 <!-- 动画持续时间 -->
 <attr name="duration" fORMat="integer"></attr>
 <!-- 边框宽度 -->
 <attr name="strikeWidth" format="dimension|reference"></attr>
 <!-- 边框颜色 -->
 <attr name="borderColor" format="color|reference"></attr>
 <!-- 选中状态的颜色 -->
 <attr name="trimColor" format="color|reference"></attr>
 <!-- 对勾颜色 -->
 <attr name="tickColor" format="color|reference"></attr>
 <!-- 对勾宽度 -->
 <attr name="tickWidth" format="dimension|reference"></attr>
 </declare-styleable>
</resources>

我们把CheckBox取名为SmoothCheckBox,定义了几个等等要用到的属性。这一步很简单,相信大家都熟练了。

接下来看一看onMeasure(int widthMeasureSpec, int heightMeasureSpec):


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 int widthSize = MeasureSpec.getSize(widthMeasureSpec);
 int widthMode = MeasureSpec.getMode(widthMeasureSpec);
 if (widthMode == MeasureSpec.EXACTLY) {
  mWidth = widthSize;
 } else {
  mWidth = 40;
 }
 int heightSize = MeasureSpec.getSize(heightMeasureSpec);
 int heightMode = MeasureSpec.getMode(heightMeasureSpec);
 if (heightMode == MeasureSpec.EXACTLY) {
  mHeight = heightSize;
 } else {
  mHeight = 40;
 }
 setMeasuredDimension(mWidth, mHeight);
 int size = Math.min(mWidth, mHeight);
 center = size / 2;
 mRadius = (int) ((size - mStrokeWidth) / 2 / 1.2f);
 startPoint.set(center * 14 / 30, center * 28 / 30);
 breakPoint.set(center * 26 / 30, center * 40 / 30);
 endPoint.set(center * 44 / 30, center * 20 / 30);
 downLength = (float) Math.sqrt(Math.pow(startPoint.x - breakPoint.x, 2f) + Math.pow(startPoint.y - breakPoint.y, 2f));
 upLength = (float) Math.sqrt(Math.pow(endPoint.x - breakPoint.x, 2f) + Math.pow(endPoint.y - breakPoint.y, 2f));
 totalLength = downLength + upLength;
}

一开始是测量了SmoothCheckBox的宽、高度,默认的宽高度随便定义了一个,当然你们可以自己去修改和完善它。然后就是设置半径之类的,最后的startPoint、breakPoint、endPoint分别对应着选中时对勾的三个点(至于为何是这几个数字,那完全是经验值);downLength就是startPoint和breakPoint的距离,而相对应的upLength就是breakPoint和endPoint的距离。即以下图示:

在看onDraw(canvas canvas)之前我们先来看两组动画,分别是选中状态时的动画以及未选中状态的动画:


// 由未选中到选中的动画
private void checkedAnimation() {
 animatedValue = 0f;
 tickValue = 0f;
 // 选中时底色的动画
 mValueAnimator = ValueAnimator.ofFloat(0f, 1.2f, 1f).setDuration(2 * duration / 5);
 mValueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
 // 对勾的动画
 mTickValueAnimator = ValueAnimator.ofFloat(0f, 1f).setDuration(3 * duration / 5);
 mTickValueAnimator.setInterpolator(new LinearInterpolator());
 mTickValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  @Override
  public void onAnimationUpdate(ValueAnimator valueAnimator) {
 // 得到动画执行进度
   tickValue = (float) valueAnimator.getAnimatedValue();
   postInvalidate();
  }
 });
 mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  @Override
  public void onAnimationUpdate(ValueAnimator valueAnimator) {
 // 得到动画执行进度
   animatedValue = (float) valueAnimator.getAnimatedValue();
   postInvalidate();
  }
 });
 mValueAnimator.addListener(new AnimatorListenerAdapter() {
  @Override
  public void onAnimationEnd(Animator animation) {
 //当底色的动画完成后再开始对勾的动画
   mTickValueAnimator.start();
   Log.i(TAG," mTickValueAnimator.start();");
  }
 });
 mValueAnimator.start();
}
// 由选中到未选中的动画
private void uncheckedAnimation() {
 animatedValue = 0f;
 mValueAnimator = ValueAnimator.ofFloat(1f, 0f).setDuration(2 * duration / 5);
 mValueAnimator.setInterpolator(new AccelerateInterpolator());
 mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  @Override
  public void onAnimationUpdate(ValueAnimator valueAnimator) {
   animatedValue = (float) valueAnimator.getAnimatedValue();
   postInvalidate();
  }
 });
 mValueAnimator.start();
}

这两组动画在点击SmoothCheckBox的时候会调用。相似的,都是在动画执行中得到动画执行的进度,再来调用postInvalidate();让SmoothCheckBox重绘。看完这个之后就是终极大招onDraw(Canvas canvas)了:


@Override
protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 canvas.save();
 drawBorder(canvas);
 drawTrim(canvas);
 if (isChecked) {
  drawTick(canvas);
 }
 canvas.restore();
}
// 画对勾
private void drawTick(Canvas canvas) {
 // 得到画对勾的进度
 float temp = tickValue * totalLength;
 Log.i(TAG, "temp:" + temp + "downlength :" + downLength);
 //判断是否是刚开始画对勾的时候,即等于startPoint
 if (Float.compare(tickValue, 0f) == 0) {
  Log.i(TAG, "startPoint : " + startPoint.x + ", " + startPoint.y);
  path.reset();
  path.moveTo(startPoint.x, startPoint.y);
 }
 // 如果画对勾的进度已经超过breakPoint的时候,即(breakPoint,endPoint]
 if (temp > downLength) {
  path.moveTo(startPoint.x, startPoint.y);
  path.lineTo(breakPoint.x, breakPoint.y);
  Log.i(TAG, "endPoint : " + endPoint.x + ", " + endPoint.y);
  path.lineTo((endPoint.x - breakPoint.x) * (temp - downLength) / upLength + breakPoint.x, (endPoint.y - breakPoint.y) * (temp - downLength) / upLength + breakPoint.y);
 } else {
 //画对勾的进度介于startPoinit和breakPoint之间,即(startPoint,breakPoint]
  Log.i(TAG, "down x : " + (breakPoint.x - startPoint.x) * temp / downLength + ",down y: " + (breakPoint.y - startPoint.y) * temp / downLength);
  path.lineTo((breakPoint.x - startPoint.x) * temp / downLength + startPoint.x, (breakPoint.y - startPoint.y) * temp / downLength + startPoint.y);
 }
 canvas.drawPath(path, tickPaint);
}
// 画边框
private void drawBorder(Canvas canvas) {
 float temp;
 // 通过animatedValue让边框产生一个“OverShooting”的动画
 if (animatedValue > 1f) {
  temp = animatedValue * mRadius;
 } else {
  temp = mRadius;
 }
 canvas.drawCircle(center, center, temp, borderPaint);
}
// 画checkbox内部
private void drawTrim(Canvas canvas) {
 canvas.drawCircle(center, center, (mRadius - mStrokeWidth) * animatedValue, trimPaint);
}

onDraw(Canvas canvas)代码中的逻辑基本都加了注释,主要就是原理搞懂了就比较简单了。在绘制对勾时要区分当前处于绘制对勾的哪种状态,然后对应做处理画出线条,剩下的就简单了。关于SmoothCheckBox的讲解到这里就差不多了。

下面就贴出SmoothCheckBox的完整代码:


public class SmoothCheckBox extends View implements View.OnClickListener {
 // 动画持续时间
 private long duration;
 // 边框宽度
 private float mStrokeWidth;
 // 对勾宽度
 private float mTickWidth;
 // 内饰画笔
 private Paint trimPaint;
 // 边框画笔
 private Paint borderPaint;
 // 对勾画笔
 private Paint tickPaint;
 // 默认边框宽度
 private float defaultStrikeWidth;
 // 默认对勾宽度
 private float defaultTickWidth;
 // 宽度
 private int mWidth;
 // 高度
 private int mHeight;
 // 边框颜色
 private int borderColor;
 // 内饰颜色
 private int trimColor;
 // 对勾颜色
 private int tickColor;
 // 半径
 private int mRadius;
 // 中心点
 private int center;
 // 是否是选中
 private boolean isChecked;
 //对勾向下的长度
 private float downLength;
 //对勾向上的长度
 private float upLength;
 // 对勾的总长度
 private float totalLength;
 // 监听器
 private OnCheckedChangeListener listener;
 private ValueAnimator mValueAnimator;
 private ValueAnimator mTickValueAnimator;
 private float animatedValue;
 private float tickValue;
 // 对勾开始点
 private Point startPoint = new Point();
 // 对勾转折点
 private Point breakPoint = new Point();
 // 对勾结束点
 private Point endPoint = new Point();
 private static final String TAG = "SmoothCheckBox";
 private static final String KEY_INSTANCE_STATE = "InstanceState";
 private Path path = new Path();
 public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
  this.listener = listener;
 }
 public SmoothCheckBox(Context context) {
  this(context, null);
 }
 public SmoothCheckBox(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }
 public SmoothCheckBox(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.SmoothCheckBox);
  duration = a.getInt(R.styleable.SmoothCheckBox_duration, 600);
  defaultStrikeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
  mStrokeWidth = a.getDimension(R.styleable.SmoothCheckBox_strikeWidth, defaultStrikeWidth);
  defaultTickWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getResources().getDisplayMetrics());
  mTickWidth = a.getDimension(R.styleable.SmoothCheckBox_tickWidth, defaultTickWidth);
  borderColor = a.getColor(R.styleable.SmoothCheckBox_borderColor, getResources().getColor(Android.R.color.darker_gray));
  trimColor = a.getColor(R.styleable.SmoothCheckBox_trimColor, getResources().getColor(android.R.color.holo_green_light));
  tickColor = a.getColor(R.styleable.SmoothCheckBox_tickColor, getResources().getColor(android.R.color.white));
  a.recycle();
  trimPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  trimPaint.setStyle(Paint.Style.FILL);
  trimPaint.setColor(trimColor);
  borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  borderPaint.setStrokeWidth(mStrokeWidth);
  borderPaint.setColor(borderColor);
  borderPaint.setStyle(Paint.Style.STROKE);
  tickPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  tickPaint.setColor(tickColor);
  tickPaint.setStyle(Paint.Style.STROKE);
  tickPaint.setStrokeCap(Paint.Cap.ROUND);
  tickPaint.setStrokeWidth(mTickWidth);
  setOnClickListener(this);
 }
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  int widthSize = MeasureSpec.getSize(widthMeasureSpec);
  int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  if (widthMode == MeasureSpec.EXACTLY) {
   mWidth = widthSize;
  } else {
   mWidth = 40;
  }
  int heightSize = MeasureSpec.getSize(heightMeasureSpec);
  int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  if (heightMode == MeasureSpec.EXACTLY) {
   mHeight = heightSize;
  } else {
   mHeight = 40;
  }
  setMeasuredDimension(mWidth, mHeight);
  int size = Math.min(mWidth, mHeight);
  center = size / 2;
  mRadius = (int) ((size - mStrokeWidth) / 2 / 1.2f);
  startPoint.set(center * 14 / 30, center * 28 / 30);
  breakPoint.set(center * 26 / 30, center * 40 / 30);
  endPoint.set(center * 44 / 30, center * 20 / 30);
  downLength = (float) Math.sqrt(Math.pow(startPoint.x - breakPoint.x, 2f) + Math.pow(startPoint.y - breakPoint.y, 2f));
  upLength = (float) Math.sqrt(Math.pow(endPoint.x - breakPoint.x, 2f) + Math.pow(endPoint.y - breakPoint.y, 2f));
  totalLength = downLength + upLength;
 }
 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  canvas.save();
  drawBorder(canvas);
  drawTrim(canvas);
  if (isChecked) {
   drawTick(canvas);
  }
  canvas.restore();
 }
 @Override
 protected Parcelable onSaveInstanceState() {
  Bundle bundle = new Bundle();
  bundle.putParcelable(KEY_INSTANCE_STATE, super.onSaveInstanceState());
  bundle.putBoolean(KEY_INSTANCE_STATE, isChecked);
  return bundle;
 }
 @Override
 protected void onRestoreInstanceState(Parcelable state) {
  if (state instanceof Bundle) {
   Bundle bundle = (Bundle) state;
   boolean isChecked = bundle.getBoolean(KEY_INSTANCE_STATE);
   setChecked(isChecked);
   super.onRestoreInstanceState(bundle.getParcelable(KEY_INSTANCE_STATE));
   return;
  }
  super.onRestoreInstanceState(state);
 }
 // 切换状态
 private void toggle() {
  isChecked = !isChecked;
  if (listener != null) {
   listener.onCheckedChanged(this, isChecked);
  }
  if (isChecked) {
   checkedAnimation();
  } else {
   uncheckedAnimation();
  }
 }
 // 由未选中到选中的动画
 private void checkedAnimation() {
  animatedValue = 0f;
  tickValue = 0f;
  mValueAnimator = ValueAnimator.ofFloat(0f, 1.2f, 1f).setDuration(2 * duration / 5);
  mValueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
  mTickValueAnimator = ValueAnimator.ofFloat(0f, 1f).setDuration(3 * duration / 5);
  mTickValueAnimator.setInterpolator(new LinearInterpolator());
  mTickValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
   @Override
   public void onAnimationUpdate(ValueAnimator valueAnimator) {
    tickValue = (float) valueAnimator.getAnimatedValue();
    postInvalidate();
   }
  });
  mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
   @Override
   public void onAnimationUpdate(ValueAnimator valueAnimator) {
    animatedValue = (float) valueAnimator.getAnimatedValue();
    postInvalidate();
   }
  });
  mValueAnimator.addListener(new AnimatorListenerAdapter() {
   @Override
   public void onAnimationEnd(Animator animation) {
    mTickValueAnimator.start();
    Log.i(TAG," mTickValueAnimator.start();");
   }
  });
  mValueAnimator.start();
 }
 // 由选中到未选中的动画
 private void uncheckedAnimation() {
  animatedValue = 0f;
  mValueAnimator = ValueAnimator.ofFloat(1f, 0f).setDuration(2 * duration / 5);
  mValueAnimator.setInterpolator(new AccelerateInterpolator());
  mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
   @Override
   public void onAnimationUpdate(ValueAnimator valueAnimator) {
    animatedValue = (float) valueAnimator.getAnimatedValue();
    postInvalidate();
   }
  });
  mValueAnimator.start();
 }
 // 画对勾
 private void drawTick(Canvas canvas) {
  float temp = tickValue * totalLength;
  Log.i(TAG, "temp:" + temp + "downlength :" + downLength);
  if (Float.compare(tickValue, 0f) == 0) {
   Log.i(TAG, "startPoint : " + startPoint.x + ", " + startPoint.y);
   path.reset();
   path.moveTo(startPoint.x, startPoint.y);
  }
  if (temp > downLength) {
   path.moveTo(startPoint.x, startPoint.y);
   path.lineTo(breakPoint.x, breakPoint.y);
   Log.i(TAG, "endPoint : " + endPoint.x + ", " + endPoint.y);
   path.lineTo((endPoint.x - breakPoint.x) * (temp - downLength) / upLength + breakPoint.x, (endPoint.y - breakPoint.y) * (temp - downLength) / upLength + breakPoint.y);
  } else {
   Log.i(TAG, "down x : " + (breakPoint.x - startPoint.x) * temp / downLength + ",down y: " + (breakPoint.y - startPoint.y) * temp / downLength);
   path.lineTo((breakPoint.x - startPoint.x) * temp / downLength + startPoint.x, (breakPoint.y - startPoint.y) * temp / downLength + startPoint.y);
  }
  canvas.drawPath(path, tickPaint);
 }
 // 画边框
 private void drawBorder(Canvas canvas) {
  float temp;
  if (animatedValue > 1f) {
   temp = animatedValue * mRadius;
  } else {
   temp = mRadius;
  }
  canvas.drawCircle(center, center, temp, borderPaint);
 }
 // 画checkbox内部
 private void drawTrim(Canvas canvas) {
  canvas.drawCircle(center, center, (mRadius - mStrokeWidth) * animatedValue, trimPaint);
 }
 @Override
 public void onClick(View view) {
  toggle();
 }
 
 public boolean isChecked() {
  return isChecked;
 }
 
 public void setChecked(boolean isChecked) {
  this.setChecked(isChecked, false);
 }
 
 public void setChecked(boolean isChecked, boolean isAnimation) {
  this.isChecked = isChecked;
  if (isAnimation) {
   if (isChecked) {
    checkedAnimation();
   } else {
    uncheckedAnimation();
   }
  } else {
   animatedValue = isChecked ? 1f : 0f;
   tickValue = 1f;
   invalidate();
  }
  if (listener != null) {
   listener.onCheckedChanged(this, isChecked);
  }
 }
 public interface OnCheckedChangeListener {
  void onCheckedChanged(SmoothCheckBox smoothCheckBox, boolean isChecked);
 }
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

您可能感兴趣的文章:Android RecycleView使用(CheckBox全选、反选、单选)Android中CheckBox复选框控件使用方法详解Android开发之CheckBox的简单使用与监听功能示例Android 中CheckBox多项选择当前的position信息提交的示例代码Android中ListView + CheckBox实现单选、多选效果Android中ListView绑定CheckBox实现全选增加和删除功能(DEMO)Android开发中CheckBox的简单用法示例详解Android Checkbox的使用方法Android中自定义Checkbox组件实例Android CheckBox中设置padding无效解决办法


--结束END--

本文标题: Android实现炫酷的CheckBox效果

本文链接: https://www.lsjlt.com/news/23688.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android实现炫酷的CheckBox效果
    首先贴出实现的效果图: gif的效果可能有点过快,在真机上运行的效果会更好一些。我们主要的思路就是利用属性动画来动态地画出选中状态以及对勾的绘制过程。看到上面的效果图,相信大...
    99+
    2022-06-06
    checkbox Android
  • js实现炫酷的烟花效果
    本文实例为大家分享了js实现炫酷的烟花效果的具体代码,供大家参考,具体内容如下 我们要理清整个流程的思路。 首先建立一块画布,用于展示烟花的效果,然后就要去思考烟花燃放的流程,我们都...
    99+
    2022-11-12
  • Android中怎么实现一个炫酷进度条效果
    这期内容当中小编将会给大家带来有关Android中怎么实现一个炫酷进度条效果,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。HorizontalProgressbarWithProgress的代码impor...
    99+
    2023-05-30
    android
  • 超酷炫的Android碎纸机效果推荐
    在Android开发中,有时候可能会要用到碎纸机的效果,今天小编为大家整理好代码,一起来看看吧。 首先来看下效果图 实例代码 xml <com.ldouble...
    99+
    2022-06-06
    Android
  • CSS如何实现炫酷的文字效果
    今天小编给大家分享一下CSS如何实现炫酷的文字效果的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一...
    99+
    2022-10-19
  • 原生JS实现酷炫分页效果
    本文实例为大家分享一个如下效果的JS分页特效,是不是很酷炫。  以下是代码实现: <!DOCTYPE html> <html> <h...
    99+
    2022-11-12
  • CSS如何实现炫酷打字效果
    本篇内容主要讲解“CSS如何实现炫酷打字效果”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“CSS如何实现炫酷打字效果”吧!代码如下:.asprint {  &nbs...
    99+
    2023-07-04
  • 基于Three.js实现酷炫3D地图效果
    目录实现效果前言使用1.修改整体的背景图可以使用颜色或用贴图改材质2. 取消地图上柱状图显示3.更换地图、更换省份、市 4.修改相机的视角,页面展示的远近角度5....
    99+
    2022-11-13
    Three.js 3D地图 Three.js 地图
  • CSS3+JavaScript如何实现炫酷呼吸效果
    这篇文章给大家分享的是有关CSS3+JavaScript如何实现炫酷呼吸效果的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。用css3动画实现的一个简单炫酷效果,最终的效果图如下:页面结构(index.html):...
    99+
    2023-06-08
  • Android实现单页显示3个Item的ViewPager炫酷切换效果
    单页显示3个Item的ViewPager炫酷切换效果,适用于Banner等。效果图Rotate YRotate DownRotate UpAlphaScaleInScaleIn + Alpha + Rotate Down使用###(1)引入...
    99+
    2023-05-30
    android viewpager 切换
  • Android实现酷炫的顶部栏
    AppBarLayout 是继承LinerLayout实现的一个ViewGroup容器组件,它是为了Material Design设计的App Bar,支持手势滑动操作的,不过...
    99+
    2022-06-06
    Android
  • 实现炫酷滚动效果的CSS属性技巧
    实现炫酷滚动效果的CSS属性技巧,需要具体代码示例CSS是网页设计中不可或缺的一部分,通过CSS可以实现各种各样的效果来提升网页的交互体验。其中,滚动效果是一种非常常见也非常炫酷的效果,它可以使网页元素以流畅的动画效果滚动到指定位置。本文将...
    99+
    2023-11-18
    技巧 滚动效果 CSS属性
  • 基于canvas实现超炫酷的流水灯效果
    本文实例为大家分享了基于canvas实现超炫酷的流水灯效果的具体代码,供大家参考,具体内容如下 <!DOCTYPE html> <html> &l...
    99+
    2022-11-12
  • JavaScript+Canvas实现酷炫的粒子和流星效果
    目录一:粒子效果二:流星效果一:粒子效果 <html> <head> <meta charset="utf-8"> <title&...
    99+
    2023-01-31
    JavaScript实现粒子效果 JavaScript实现流星效果 JavaScript 粒子 JavaScript 流星
  • css如何实现登录按钮炫酷效果
    这篇文章主要介绍了css如何实现登录按钮炫酷效果的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇css如何实现登录按钮炫酷效果文章都会有所收获,下面我们一起来看看吧。分析我们抛开before不谈的话;其实原理和就...
    99+
    2023-07-05
  • vue中使用animate.css实现炫酷动画效果
    目录1.安装(在vscode终端中,使用npm安装)2.引入3.代码实现animate.css 是一个来自国外的 CSS3 动画库,它提供了抖动(shake)、闪烁(flash)、弹...
    99+
    2022-11-13
  • JavaScript利用canvas实现炫酷的碎片切图效果
    目录前言需求分析实现过程坐标系切割绘制切割&渲染动画前言 今天分享一个炫酷的碎片式切图效果,这个其实在自己的之前的博客上有实现过,本人觉得这个效果还是挺炫酷的,这次还是用我们...
    99+
    2022-11-13
    JavaScript canvas碎片切图效果 JavaScript canvas 碎片切图 JavaScript canvas 切图
  • CSS3怎么实现超酷炫的粘性气泡效果
    今天小编给大家分享一下CSS3怎么实现超酷炫的粘性气泡效果的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起...
    99+
    2022-10-19
  • react-three-fiber实现炫酷3D粒子效果首页
    目录背景Three.js工作原理场景(Scene)相机(Camera)渲染器(renderer)网格对象(mesh)react-three-fiber画布(Canvas)3D粒子模型...
    99+
    2022-11-13
  • Android 开发之BottomBar+ViewPager+Fragment实现炫酷的底部导航效果
    BottomBar   BottomBar是Github上的一个开源框架,因为从1.3.3开始不支持fragments了,要自己配置,弄了很久,不管是app的fragmen...
    99+
    2022-06-06
    viewpager fragment Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作