当前位置: 首页 > news >正文

仿饿了么加入购物车旋转控件 - 自带闪转腾挪动画 的按钮

, mWidth - mCircleWidth, mHeight - mCircleWidth);

canvas.drawRoundRect(rectF, mHintBgRoundValue, mHintBgRoundValue, mHintPaint);

//前景文字

mHintPaint.setColor(mHintFgColor);

// 计算Baseline绘制的起点X轴坐标

int baseX = (int) (mWidth / 2 - mHintPaint.measureText(mHintText) / 2);

// 计算Baseline绘制的Y坐标

int baseY = (int) ((mHeight / 2) - ((mHintPaint.descent() + mHintPaint.ascent()) / 2));

canvas.drawText(mHintText, baseX, baseY, mHintPaint);

} else {

//左边

//背景 圆

if (mCount > 0) {

mDelPaint.setColor(mDelEnableBgColor);

} else {

mDelPaint.setColor(mDelDisableBgColor);

}

mDelPaint.setStrokeWidth(mCircleWidth);

mDelPath.reset();

mDelPath.addCircle(mLeft + mRadius, mTop + mRadius, mRadius, Path.Direction.CW);

mDelRegion.setPath(mDelPath, new Region(mLeft, mTop, mWidth - getPaddingRight(), mHeight - getPaddingBottom()));

canvas.drawPath(mDelPath, mDelPaint);

//前景 -

if (mCount > 0) {

mDelPaint.setColor(mDelEnableFgColor);

} else {

mDelPaint.setColor(mDelDisableFgColor);

}

mDelPaint.setStrokeWidth(mLineWidth);

canvas.drawLine(-mRadius / 2, 0,

+mRadius / 2, 0,

mDelPaint);

//数量

//是没有动画的普通写法,x left, y baseLine

canvas.drawText(mCount + “”, mLeft + mRadius * 2, mTop + mRadius - (mFontMetrics.top + mFontMetrics.bottom) / 2, mTextPaint);

//右边

//背景 圆

if (mCount < mMaxCount) {

mAddPaint.setColor(mAddEnableBgColor);

} else {

mAddPaint.setColor(mAddDisableBgColor);

}

mAddPaint.setStrokeWidth(mCircleWidth);

float left = mLeft + mRadius * 2 + mGapBetweenCircle;

mAddPath.reset();

mAddPath.addCircle(left + mRadius, mTop + mRadius, mRadius, Path.Direction.CW);

mAddRegion.setPath(mAddPath, new Region(mLeft, mTop, mWidth - getPaddingRight(), mHeight - getPaddingBottom()));

canvas.drawPath(mAddPath, mAddPaint);

//前景 +

if (mCount < mMaxCount) {

mAddPaint.setColor(mAddEnableFgColor);

} else {

mAddPaint.setColor(mAddDisableFgColor);

}

mAddPaint.setStrokeWidth(mLineWidth);

canvas.drawLine(left + mRadius / 2, mTop + mRadius, left + mRadius / 2 + mRadius, mTop + mRadius, mAddPaint);

canvas.drawLine(left + mRadius, mTop + mRadius / 2, left + mRadius, mTop + mRadius / 2 + mRadius, mAddPaint);

}

}

根据isHintMode 布尔值变量,区分是绘制第二层(Hint层)或者第一层(加减按钮层)。

绘制第二层时没啥好说的,就是利用canvas.drawRoundRect,绘制圆角矩形,然后canvas.drawText绘制hint。

(如果圆角的值足够大,矩形的宽度足够小,就变成了圆形。)

绘制第一层时,要根据当前的数量选择不同的颜色,注意在绘制加减按钮的圆圈时,我们是用Path绘制的,这是因为我们还需要用Path构建Region类,这个类就是我们监听点击区域的重点

点击事件的监听


在讲解动画之前,我们先说说如何监听点击的区域,因为本控件的动画是和加减数量息息相关的,而数量的加减是由点击相应”+ - 按钮”区域触发的。

所以我们的监听按钮的点击事件,其实就是监听相应的”+ - 按钮”区域

上一节中,我们在绘制”+ - 按钮”区域时,通过Path,构建了两个Region类,Region类有个contains(int x, int y)方法如下,通过传入对应触摸的x、y坐标,就可知道知否点击了相应区域

/**

  • Return true if the region contains the specified point

*/

public native boolean contains(int x, int y);

知道了这一点,再写这部分代码就相当简单了:

@Override

public boolean onTouchEvent(MotionEvent event) {

int action = event.getAction();

switch (action) {

case MotionEvent.ACTION_DOWN:

//hint模式

if (isHintMode) {

onAddClick();

return true;

} else {

if (mAddRegion.contains((int) event.getX(), (int) event.getY())) {

onAddClick();

return true;

} else if (mDelRegion.contains((int) event.getX(), (int) event.getY())) {

onDelClick();

return true;

}

}

break;

case MotionEvent.ACTION_MOVE:

break;

case MotionEvent.ACTION_UP:

case MotionEvent.ACTION_CANCEL:

break;

}

return super.onTouchEvent(event);

}

hint模式时,我们可以认为控件所有范围都是“+”的有效区域

而在非hint模式时,根据上一节构建的mAddRegionmDelRegion去判断。

判断确认点击后,具体的操作,要根据业务的不同来编写了,设计到实际的购物车可能还有写数据库操作,或者请求接口等,要操作成功后才执行动画、或者修改count,这一块代码每个人写法可能不同。

使用时,可以重写onDelClick()onAddClick()方法,并在合适的时机回调onCountAddSuccess()onCountDelSuccess()以执行动画。

本文如下编写:

protected void onDelClick() {

if (mCount > 0) {

mCount–;

onCountDelSuccess();

}

}

protected void onAddClick() {

if (mCount < mMaxCount) {

mCount++;

onCountAddSuccess();

} else {

}

}

/**

  • 数量增加成功后,使用者回调

*/

public void onCountAddSuccess() {

if (mCount == 1) {

cancelAllAnim();

mAnimReduceHint.start();

} else {

mAnimFraction = 0;

invalidate();

}

}

/**

  • 数量减少成功后,使用者回调

*/

public void onCountDelSuccess() {

if (mCount == 0) {

cancelAllAnim();

mAniDel.start();

} else {

mAnimFraction = 0;

invalidate();

}

}

动画的实现


这里会用到两个变量:

//动画的基准值 动画:减 0~1, 加 1~0

// 普通状态下是0

protected float mAnimFraction;

//提示语收缩动画 0-1 展开1-0

//普通模式时,应该是1, 只在 isHintMode true 才有效

protected float mAnimExpandHintFraction;

依次分析有哪些动画:

Hint动画

主要是圆角矩形的展开、收缩

固定right、bottom,当展开时,不断减少矩形的左起点left坐标值,则整个矩形宽度变大,呈现展开。收缩时相反。

代码:

//背景

mHintPaint.setColor(mHintBgColor);

RectF rectF = new RectF(mLeft + (mWidth - mRadius * 2) * mAnimExpandHintFraction, mTop

, mWidth - mCircleWidth, mHeight - mCircleWidth);

canvas.drawRoundRect(rectF, mHintBgRoundValue, mHintBgRoundValue, mHintPaint);

减按钮动画

看起来是旋转、位移、透明度

那么对于背景的圆圈来说,我们只需要位移、透明度。因为它本身是个圆,就不要旋转了。

代码:

//动画 mAnimFraction :减 0~1, 加 1~0 ,

//动画位移Max,

float animOffsetMax = (mRadius * 2 +mGapBetweenCircle);

//透明度动画的基准

int animAlphaMax = 255;

int animRotateMax = 360;

//左边

//背景 圆

mDelPaint.setAlpha((int) (animAlphaMax * (1 - mAnimFraction)));

mDelPath.reset();

//改变圆心的X坐标,实现位移

mDelPath.addCircle(animOffsetMax * mAnimFraction + mLe​
ft + mRadius, mTop + mRadius, mRadius, Path.Direction.CW);

canvas.drawPath(mDelPath, mDelPaint);

对于前景的“-”号来说,旋转、位移、透明度都需要做。

这里我们利用canvas.translate() canvas.rotate 做旋转和位移动画,别忘了 canvas.save()canvas.restore()恢复画布的状态。(透明度在上面已经设置过了。)

//前景 -

//旋转动画

canvas.save();

canvas.translate(animOffsetMax * mAnimFraction + mLeft + mRadius, mTop + mRadius);

canvas.rotate((int) (animRotateMax * (1 - mAnimFraction)));

canvas.drawLine(-mRadius / 2, 0,

+mRadius / 2, 0,

mDelPaint);

canvas.restore();

数量的动画

看起来也是旋转、位移、透明度。同样是利用canvas.translate() canvas.rotate 做旋转和位移动画。

//数量

canvas.save();

//平移动画

canvas.translate(mAnimFraction * (mGapBetweenCircle / 2 - mTextPaint.measureText(mCount + “”) / 2 + mRadius), 0);

//旋转动画,旋转中心点,x 是绘图中心,y 是控件中心

canvas.rotate(360 * mAnimFraction,

mGapBetweenCircle / 2 + mLeft + mRadius * 2 ,

mTop + mRadius);

//透明度动画

mTextPaint.setAlpha((int) (255 * (1 - mAnimFraction)));

//是没有动画的普通写法,x left, y baseLine

canvas.drawText(mCount + “”, mGapBetweenCircle / 2 - mTextPaint.measureText(mCount + “”) / 2 + mLeft + mRadius * 2, mTop + mRadius - (mFontMetrics.top + mFontMetrics.bottom) / 2, mTextPaint);

canvas.restore();

动画的定义:

动画是在View初始化时就定义好的,执行顺序:

  • 数量增加,0-1时,先收缩Hint(第二层)mAnimReduceHint执行,完毕后执行减按钮(第一层)进入的动画mAnimAdd

  • 数量减少,1-0时,先执行减按钮退出的动画mAniDel,再伸展Hint动画mAnimExpandHint,完毕后,显示hint文字。

代码如下:

//动画 +

mAnimAdd = ValueAnimator.ofFloat(1, 0);

mAnimAdd.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

mAnimFraction = (float) animation.getAnimatedValue();

invalidate();

}

});

mAnimAdd.setDuration(350);

//提示语收缩动画 0-1

mAnimReduceHint = ValueAnimator.ofFloat(0, 1);

mAnimReduceHint.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

mAnimExpandHintFraction = (float) animation.getAnimatedValue();

invalidate();

}

});

mAnimReduceHint.addListener(new AnimatorListenerAdapter() {

@Override

public void onAnimationEnd(Animator animation) {

if (mCount == 1) {

//然后底色也不显示了

isHintMode = false;

}

if (mCount == 1) {

Log.d(TAG, “现在还是1 开始收缩动画”);

if (mAnimAdd != null && !mAnimAdd.isRunning()) {

mAnimAdd.start();

}

}

}

@Override

public void onAnimationStart(Animator animation) {

if (mCount == 1) {

//先不显示文字了

isShowHintText = false;

}

}

});

mAnimReduceHint.setDuration(350);

//动画 -

mAniDel = ValueAnimator.ofFloat(0, 1);

mAniDel.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

mAnimFraction = (float) animation.getAnimatedValue();

invalidate();

}

});

//1-0的动画

mAniDel.addListener(new AnimatorListenerAdapter() {

@Override

public void onAnimationEnd(Animator animation) {

if (mCount == 0) {

Log.d(TAG, “现在还是0onAnimationEnd() called with: animation = [” + animation + “]”);

if (mAnimExpandHint != null && !mAnimExpandHint.isRunning()) {

mAnimExpandHint.start();

}

}

}

});

mAniDel.setDuration(350);

//提示语展开动画

//分析这个动画,最初是个圆。 就是left 不断减小

mAnimExpandHint = ValueAnimator.ofFloat(1, 0);

mAnimExpandHint.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

mAnimExpandHintFraction = (float) animation.getAnimatedValue();

invalidate();

}

});

mAnimExpandHint.addListener(new AnimatorListenerAdapter() {

@Override

public void onAnimationEnd(Animator animation) {

if (mCount == 0) {

isShowHintText = true;

}

}

@Override

public void onAnimationStart(Animator animation) {

if (mCount == 0) {

isHintMode = true;

}

}

});

mAnimExpandHint.setDuration(350);

针对复用机制的处理


因为我们的购物车控件肯定会用在列表中,不管你用ListView还是RecyclerView,都会涉及到复用的问题。

复用给我们带来一个麻烦的地方就是,我们要处理好一些属性状态值,否则UI上会有问题。

可以从两处下手处理:

onMeasure

列表复用时,依然会回调onMeasure()方法,所以在这里初始化一些UI显示的参数。

这里顺带将适配wrap_content 的代码也一同贴上:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int wMode = MeasureSpec.getMode(widthMeasureSpec);

int wSize = MeasureSpec.getSize(widthMeasureSpec);

int hMode = MeasureSpec.getMode(heightMeasureSpec);

int hSize = MeasureSpec.getSize(heightMeasureSpec);

switch (wMode) {

case MeasureSpec.EXACTLY:

break;

case MeasureSpec.AT_MOST:

//不超过父控件给的范围内,自由发挥

int computeSize = (int) (getPaddingLeft() + mRadius * 2 +mGapBetweenCircle + mRadius * 2 + getPaddingRight() + mCircleWidth * 2);

wSize = computeSize < wSize ? computeSize : wSize;

break;

case MeasureSpec.UNSPECIFIED:

//自由发挥

computeSize = (int) (getPaddingLeft() + mRadius * 2 + mGapBetweenCircle + mRadius * 2 + getPaddingRight() + mCircleWidth * 2);

wSize = computeSize;

break;

}

switch (hMode) {

case MeasureSpec.EXACTLY:

break;

case MeasureSpec.AT_MOST:

int computeSize = (int) (getPaddingTop() + mRadius * 2 + getPaddingBottom() + mCircleWidth * 2);

hSize = computeSize < hSize ? computeSize : hSize;

break;

case MeasureSpec.UNSPECIFIED:

computeSize = (int) (getPaddingTop() + mRadius * 2 + getPaddingBottom() + mCircleWidth * 2);

hSize = computeSize;

break;

}

setMeasuredDimension(wSize, hSize);

//复用时会走这里,所以初始化一些UI显示的参数

mAnimFraction = 0;

initHintSettings();

}

/**

  • 根据当前count数量 初始化 hint提示语相关变量

*/

private void initHintSettings() {

if (mCount == 0) {

isHintMode = true;

isShowHintText = true;

mAnimExpandHintFraction = 0;

} else {

isHintMode = false;

isShowHintText = false;

mAnimExpandHintFraction = 1;

}

}

在改变count时

一般在onBindViewHolder()或者getView()时,都会对本控件重新设置count值,count改变时,当然也是需要根据count进行属性值的调整。

且此时如果View正在做动画,应该停止这些动画。

/**

  • 设置当前数量

  • @param count

  • @return

*/

public AnimShopButton setCount(int count) {

mCount = count;

//先暂停所有动画

if (mAnimAdd != null && mAnimAdd.isRunning()) {

mAnimAdd.cancel();

}

if (mAniDel != null && mAniDel.isRunning()) {

mAniDel.cancel();

}

//复用机制的处理

if (mCount == 0) {

// 0 不显示 数字和-号

mAnimFraction = 1;

} else {

mAnimFraction = 0;

}

initHintSettings();

return this;

}

总结

代码传送门:喜欢的话,随手点个star。多谢

https://github.com/mcxtzhang/AnimShopButton

经济上支持我 or 想通过视频看我是怎么实现的:

http://edu.csdn.net/course/detail/3898

我在实现这个控件时,觉得难度相对大的地方在于做动画时,“-”按钮和数量的旋转动画,如何确定正确的坐标值。因为将text绘制的居中本身就有一些注意事项在里面,再涉及到动画,难免蒙圈。需要多计算,多试验

还有就是观察饿了么的效果,将hint区域的动画利用改变RoundRect的宽度去实现。起初没有想到,也是思考了一会如何去做。这是属于分析、拆解动画遇到的问题。

除了绘制以外的重点是:

  • 利用Region监听区域点击事件

  • 复用的列表,如何正确显示UI。

  • 动画次序以及考虑到复用时,在合适的地方取消动画

最后

小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取
imFraction = 0;

}

initHintSettings();

return this;

}

总结

代码传送门:喜欢的话,随手点个star。多谢

https://github.com/mcxtzhang/AnimShopButton

经济上支持我 or 想通过视频看我是怎么实现的:

http://edu.csdn.net/course/detail/3898

我在实现这个控件时,觉得难度相对大的地方在于做动画时,“-”按钮和数量的旋转动画,如何确定正确的坐标值。因为将text绘制的居中本身就有一些注意事项在里面,再涉及到动画,难免蒙圈。需要多计算,多试验

还有就是观察饿了么的效果,将hint区域的动画利用改变RoundRect的宽度去实现。起初没有想到,也是思考了一会如何去做。这是属于分析、拆解动画遇到的问题。

除了绘制以外的重点是:

  • 利用Region监听区域点击事件

  • 复用的列表,如何正确显示UI。

  • 动画次序以及考虑到复用时,在合适的地方取消动画

最后

小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

[外链图片转存中…(img-RbTcTwdo-1719097483595)]一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取

相关文章:

仿饿了么加入购物车旋转控件 - 自带闪转腾挪动画 的按钮

, mWidth - mCircleWidth, mHeight - mCircleWidth); canvas.drawRoundRect(rectF, mHintBgRoundValue, mHintBgRoundValue, mHintPaint); //前景文字 mHintPaint.setColor(mHintFgColor); // 计算Baseline绘制的起点X轴坐标 int baseX (int) (mWidth / 2 - mHintPaint.m…...

Docker部署nacos集群

docker拉取nacos镜像&#xff0c;本文使用nacos2.0.3 三台服务器都要执行以下命令 docker pull nacos/nacos-server:v2.2.0准备挂载的日志目录和配置文件目录 日志&#xff1a;mkdir /usr/local/software/nacos/logs 配置文件&#xff1a;/usr/local/software/nacos/conf在配…...

centos查找文件 及 操作写入的进程

du -sh * 查看目录空间占用、发现大文件&#xff0c;确定进程&#xff0c;结束 yum install lsof 安装lsof 查看文件写入的 进程 2. lsof /root/.influxdbv2/engine/data/bab49411e5f7cbce/autogen/1/000000036-000000002.tsm COMMAND PID USER FD TYPE …...

构建高可用Java微服务架构的秘籍

构建高可用Java微服务架构的秘籍 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 随着云计算和分布式系统的快速发展&#xff0c;微服务架构已成为构建大型应用…...

VBA学习(18):VBA制作任意工作表均可使用的聚光灯

在需要制作聚光的工作簿&#xff0c;按<ALTF11>组合键&#xff0c;打开VBE编辑器。在右侧[工程资源管理器窗格]选中ThisWorkbook模块&#xff0c;将以下代码复制粘贴到该模块的代码窗口。 Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target …...

【STM32-启动文件 startup_stm32f103xe.s】

STM32-启动文件 startup_stm32f103xe.s ■ STM32-启动文件■ STM32-启动文件主要做了以下工作&#xff1a;■ STM32-启动文件指令■ STM32-启动文件代码详解■ 栈空间的开辟■ 栈空间大小 Stack_Size■ .map 文件的详细介绍■ 打开map文件 ■ 堆空间■ PRESERVE8 和 THUMB 指令…...

51学习记录(一)——51介绍及震动感应灯

文章目录 前言一、STC89C522.内部结构及引脚 二、继电器原理及震动传感器原理三、项目搭建及实现 前言 一个学习嵌入式的小白~ 有问题评论区或私信指出 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、STC89C52 1.简介 所属系列&#xff1a;51单…...

2024GLEE生活暨教育(上海)博览会,8月20-22日,国家会展中心(上海)

2024GLEE生活暨教育(上海)博览会将于8月20-22日在中国国家会展中心&#xff08;上海&#xff09;举行&#xff0c;博览会总面积近万平方米&#xff0c;设有美好生活和教育产品两大主力展区&#xff0c;全面覆盖婴幼儿、学龄前、小学、初中、高中、大学、中年、老年各个年龄段的…...

debug调试高级功能 断点、布局 及Android Studio常用快捷按键使用详情

文章目录 debug断点篇&#xff1a;打临时断点&#xff08;只用一次&#xff09;&#xff1a;alt断点条件断点&#xff1a;在断点上&#xff0c;点击右键&#xff0c;在Condition那里&#xff0c;设置我们需要的值&#xff0c;循环就会自动停到我们设置的那个值那里依赖断点&…...

51单片机STC89C52RC——6.1 中断系统

一&#xff0c;文字层面理解 反正我看下面的几段文字时脑壳没有正常运转。一个头几个大 中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。 当中央处理机CPU正在处理某件事的时候外界发生了紧急事件请求&#xff0c;要求CPU暂停当前的工作&#xff0c;转而去处理这…...

Redis源码学习:高性能Hash表的设计与实现

哈希表&#xff08;Hash&#xff09;是Redis数据库的数据类型之一&#xff0c;理解哈希表的实现对于掌握Redis非常重要。这篇文章&#xff0c;从哈希冲突和哈希扩展这两个角度&#xff0c;来一步步讲解Redis哈希表的工作原理。 什么是哈希表&#xff1f; 哈希表是一种通过哈希…...

如何防范常见的数据库安全问题

随着数据量的增加和系统的复杂性提高,数据库可能面临多种安全威胁,包括未授权访问、数据泄露、注入攻击等。 1. 未授权访问 未授权访问是指,未经授权的用户对数据库的内容进行访问。这会导致数据泄露、数据篡改或其他安全事故。 针对未授权访问的防范措施如下。 (1)强化…...

[Day 19] 區塊鏈與人工智能的聯動應用:理論、技術與實踐

區塊鏈的數據透明性 區塊鏈技術作為一種分布式賬本技術&#xff0c;因其去中心化、不可篡改和高度透明的特性&#xff0c;已經在各行各業中得到了廣泛應用。在本文中&#xff0c;我們將深入探討區塊鏈的數據透明性&#xff0c;包括其原理、實現方法及相關代碼示例&#xff0c;…...

【Hadoop学习笔记】认识Hadoop

认识Hadoop 从网上找的课程做的笔记&#xff0c;有些图是自己理解画的&#xff0c;可能不正确&#xff0c;可以作为参考&#xff0c;有疑问的地方请直接指出&#xff0c;共同交流。 Hadoop是由Apache基金会开发的一个分布式系统基础架构&#xff0c;主要解决海量数据的存储和海…...

CISP-PTE综合靶机-WinServer2003

1.收集网站的地址和开放的端口,完成前期信息收集。10分 2.访问站点,找出站点的敏感文件,利用返回数据找到相关敏感信 息,完成网站结构的信息收集。10分 3.利用文件包含漏洞读取敏感文件,找出数据库连接凭证,利用此 凭证连接数据库。10分 4.网站后台提权:找出后台管理员登…...

sklearn之各类朴素贝叶斯原理

sklearn之贝叶斯原理 前言1 高斯朴素贝叶斯1.1 对连续变量的处理1.2 高斯朴素贝叶斯算法原理 2 多项式朴素贝叶斯2.1 二项分布和多项分布2.2 详细原理2.3 如何判断是否符合多项式贝叶斯 3 伯努利朴素贝叶斯4 类别贝叶斯4 补充朴素贝叶斯4.1 核心原理4.2 算法流程 前言 如果想看…...

年薪50w+的项目经理,手把手教你如何复盘

复盘是一种重要的学习和改进工具&#xff0c;对于项目经理来说&#xff0c;能帮助识别项目中的成功与失败&#xff0c;为未来的项目管理提供宝贵经验。 理论部分 定义目标。在开始复盘之前&#xff0c;明确复盘的目标是什么。是为了找出项目中的问题并提出解决方案&#xff0c…...

Web3新视野:Lumoz节点的潜力与收益解读

摘要&#xff1a;低估值、高回报、无条件退款80%...... Lumoz正通过其 zkVerifier 节点销售活动&#xff0c;引领一场ZK计算革命。 长期以来&#xff0c;加密市场以其独特的波动性和增长潜力&#xff0c;持续吸引着全球投资者的目光。而历史数据表明&#xff0c;市场往往在一年…...

【shell脚本速成】mysql备份脚本

文章目录 案例需求脚本应用场景&#xff1a;解决问题脚本思路实现代码 &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f388;欢迎踏入我的博客世界&#xff0c;能与您在此邂逅&#xff0c;真是缘分使然&#xff01;&#x1f60a; &#x1f338;愿您在此停留的每一刻…...

高考志愿填报,理科生如何分析选专业?

理科生选择专业的范围更大一些&#xff0c;相比文科说理工科的院校也更多&#xff0c;如何选择适合自己的专业&#xff0c;这是一个比较重要的课题&#xff0c;毕竟大学专业直接关系到职业&#xff0c;是一辈子的大事。 那么理科究竟如何选择专业呢&#xff1f;需要从什么地方…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...