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

Android中球体碰撞代码分享-kotlin,入门版

* 可以产生形变,回弹的小球
*
* 整个view的核心:
* Scroller函数
* 1.调用scroller.public void startScroll(int startX, int startY, int dx, int dy, int duration);
* 在指定时间范围内,startX,startY,会移动dx,dy距离
*
* 2.然后调用:invalidate(); 系统内部会调用onDraw();
*
* 3.在onDraw方法内部又会调用  computeScrollOffset()函数。
* 所以,实现scroll.computeScrollOffset(); //如果还没有完全移动完成,就执行XXXXX
*
* 4.如果返回true 继续调用 invalidate();
*
* 这样就会在位移的过程中,执行你:  if(scroll.computeScrollOffset()){
* //你自己的方法
* }
*

class BallViewTwo @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null
) : androidx.appcompat.widget.AppCompatImageView(context, attrs) {private var mContext: Context = context//屏幕的宽高private var displayHeight: Int = 0private var displayWidth: Int = 0private var changelength = 30 //第一次形变的大小private var mCurrentDirection = -1 //碰撞后,此时的方向private var mDuration = 450 //变形需要持续的时间/*** flag=-1 正常移动* flag=0 压缩变形* flag=1 恢复压缩形变* flag=2 往相反的方向弹* flag=3 弹回原先的位置*/private var flag = -1private var mShotOver: ShotOver? = null //回调函数private var moveToLeft = 100 //正常状态下,小球移动到x轴的位置private var moveToTop = 100 //正常状态下,小球移动到y轴的位置private val centerX = 180 //小球圆心xprivate val centerY = 180 //小球圆心yprivate val radius = 180 //半径private val bubbleWidth = radius * 2 //小球的宽private val bubbleHeight = radius * 2 //小球的高private var paint: Paint // 画笔private var scroller: Scroller // 整个view的核心private var rectF: RectF? = null //绘制椭圆private var ovalLeft = 0private var ovalTop = 0private var ovalRight = 0private var ovalBottom = 0 //椭圆的左上右下private var currY = 0private var currX = 0private var offset = 0 //发生的移动量private val shotBackDuration = 100 //回弹执行的时间private val shotBackChange = 15 //回弹需要移动的距离private var newOvalLeft = 0private var newOvalTop = 0private var newOvalRight = 0private var newOvalBottom = 0private var isShotBack = true // 是否开启回弹效果init {paint = Paint()paint.color = Color.REDscroller = Scroller(context)rectF = RectF()}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {displayHeight = mContext.resources.displayMetrics.heightPixelsdisplayWidth = mContext.resources.displayMetrics.widthPixelsLog.i("qq", "ballview-------displayHeight=-$displayHeight displayWidth=$displayWidth")super.onMeasure(widthMeasureSpec, heightMeasureSpec)}override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {super.onSizeChanged(w, h, oldw, oldh)}override fun onDraw(canvas: Canvas) {when (flag) {-1 -> {canvas.translate(moveToLeft.toFloat(), moveToTop.toFloat())canvas.drawCircle(centerX.toFloat(), centerY.toFloat(), radius.toFloat(), paint)Log.i("qq", "正常移动小球 小球left=$moveToLeft top=$moveToTop")}0 -> circleToOval(canvas)1 -> ovalToCircle(canvas)2 -> shotBackLeaveBounds(canvas)3 -> shotBackGotoBounds(canvas)}super.onDraw(canvas)}/*** 小球变形完再回弹,靠近边界*/private fun shotBackGotoBounds(canvas: Canvas) {if (scroller.computeScrollOffset()) {ovalLeft = scroller.currXovalTop = scroller.currYcanvas.translate(ovalLeft.toFloat(), ovalTop.toFloat())canvas.drawCircle(centerX.toFloat(), centerY.toFloat(), radius.toFloat(), paint)invalidate()Log.i("shotBack", "远离边界。。moveToLeft=$ovalLeft moveToTop=$ovalTop")} else {Log.i("shotBack", "所有效果都结束")canvas.translate(ovalLeft.toFloat(), ovalTop.toFloat())canvas.drawCircle(centerX.toFloat(), centerY.toFloat(), radius.toFloat(), paint)isShotBack = falsestartChange(shotBackChange)}}/*** 小球变形完再回弹,也就是远离边界*/private fun shotBackLeaveBounds(canvas: Canvas) {if (scroller.computeScrollOffset()) {ovalLeft = scroller.currXovalTop = scroller.currYcanvas.translate(ovalLeft.toFloat(), ovalTop.toFloat())canvas.drawCircle(centerX.toFloat(), centerY.toFloat(), radius.toFloat(), paint!!)invalidate()Log.i("shotBack", "远离边界。。moveToLeft=$ovalLeft moveToTop=$ovalTop")} else {canvas.translate(ovalLeft.toFloat(), ovalTop.toFloat())canvas.drawCircle(centerX.toFloat(), centerY.toFloat(), radius.toFloat(), paint!!)flag = 3finishShotBack()}}/*** 将椭圆恢复成圆形*/private fun ovalToCircle(canvas: Canvas) {if (scroller!!.computeScrollOffset()) {when (mCurrentDirection) {0 -> {currY = scroller!!.currYoffset = newOvalTop - currYovalLeft = newOvalLeft + offsetovalTop = currY + offsetovalRight = newOvalRight - offsetovalBottom = newOvalBottom + offset + offsetrectF!![ovalLeft.toFloat(), ovalTop.toFloat(), ovalRight.toFloat()] =ovalBottom.toFloat()canvas.drawOval(rectF!!, paint!!)Log.i("qq","将椭圆----恢复成圆形,方向向北 currY=$currY offset=$offset")Log.i("qq","将椭圆----恢复成圆形,方向向北 ovalLeft=$ovalLeft ovalTop=$ovalTop ovalRight=$ovalRight ovalBottom=$ovalBottom")}1 -> {currX = scroller!!.currXoffset = newOvalLeft - currXovalLeft = currX - offsetovalTop = newOvalTop + offsetovalRight = newOvalRight + offset - offsetovalBottom = newOvalBottom - offsetrectF!![ovalLeft.toFloat(), ovalTop.toFloat(), ovalRight.toFloat()] =ovalBottom.toFloat()canvas.drawOval(rectF!!, paint!!)}2 -> {currY = scroller!!.currYoffset = newOvalTop - currYovalLeft = newOvalLeft + offsetovalTop = currY - offsetovalRight = newOvalRight - offsetovalBottom = newOvalBottomrectF!![ovalLeft.toFloat(), ovalTop.toFloat(), ovalRight.toFloat()] =ovalBottom.toFloat()canvas.drawOval(rectF!!, paint!!)Log.i("qq","将椭圆----恢复成圆形,方向向南 currY=$currY offset=$offset")Log.i("qq","将椭圆----恢复成圆形,方向向南 ovalLeft=$ovalLeft ovalTop=$ovalTop ovalRight=$ovalRight ovalBottom=$ovalBottom")}3 -> {currX = scroller!!.currXoffset = newOvalLeft - currXovalLeft = currX + offsetovalTop = newOvalTop + offsetovalRight = newOvalRight + offset + offsetovalBottom = newOvalBottom - offsetrectF!![ovalLeft.toFloat(), ovalTop.toFloat(), ovalRight.toFloat()] =ovalBottom.toFloat()canvas.drawOval(rectF!!, paint!!)}}invalidate()} else {canvas.drawOval(rectF!!, paint!!)//如果需要回弹的话if (isShotBack) {flag = 2startShotBack()} else {flag = -1if (mShotOver != null) {mShotOver!!.bubbleShotEnd()}}}}/*** 圆挤压成椭圆*/private fun circleToOval(canvas: Canvas) {if (scroller!!.computeScrollOffset()) {when (mCurrentDirection) {0 -> {currY = scroller!!.currYoffset = currY - ovalTopnewOvalLeft = ovalLeft - offsetnewOvalTop = currY - offsetnewOvalRight = ovalRight + offsetnewOvalBottom = ovalBottom - offset - offsetrectF!![newOvalLeft.toFloat(), newOvalTop.toFloat(), newOvalRight.toFloat()] =newOvalBottom.toFloat()canvas.drawOval(rectF!!, paint!!)}1 -> {currX = scroller!!.currXoffset = currX - ovalLeftnewOvalLeft = currX + offsetnewOvalTop = ovalTop - offsetnewOvalRight = ovalRight - offset + offsetnewOvalBottom = ovalBottom + offsetrectF!![newOvalLeft.toFloat(), newOvalTop.toFloat(), newOvalRight.toFloat()] =newOvalBottom.toFloat()canvas.drawOval(rectF!!, paint!!)}2 -> {currY = scroller!!.currYoffset = currY - ovalTopnewOvalLeft = ovalLeft - offsetnewOvalTop = currY + offsetnewOvalRight = ovalRight + offsetnewOvalBottom = ovalBottomrectF!![newOvalLeft.toFloat(), newOvalTop.toFloat(), newOvalRight.toFloat()] =newOvalBottom.toFloat()canvas.drawOval(rectF!!, paint!!)Log.i("qq", "圆挤压成椭圆,方向向南 currY=$currY offset=$offset")Log.i("qq","圆挤压成椭圆,方向向南 newOvalLeft=$newOvalLeft newOvalTop=$newOvalTop newOvalRight=$newOvalRight newOvalBottom=$newOvalBottom")}3 -> {currX = scroller!!.currXoffset = currX - ovalLeftnewOvalLeft = currX - offsetnewOvalTop = ovalTop - offsetnewOvalRight = ovalRight - offset - offsetnewOvalBottom = ovalBottom + offsetrectF!![newOvalLeft.toFloat(), newOvalTop.toFloat(), newOvalRight.toFloat()] =newOvalBottom.toFloat()canvas.drawOval(rectF!!, paint!!)}}invalidate()} else {canvas.drawOval(rectF!!, paint!!)reverse()}}/*** 碰撞变形结束后,开启弹一弹效果*/fun startShotBack() {when (mCurrentDirection) {0 -> scroller!!.startScroll(ovalLeft, ovalTop, 0, shotBackChange, shotBackDuration)1 -> scroller!!.startScroll(ovalLeft, ovalTop, -shotBackChange, 0, shotBackDuration)2 -> scroller!!.startScroll(ovalLeft, ovalTop, 0, -shotBackChange, shotBackDuration)3 -> scroller!!.startScroll(ovalLeft, ovalTop, shotBackChange, 0, shotBackDuration)}invalidate()}/*** 结束 “弹的一段距离”*/fun finishShotBack() {when (mCurrentDirection) {0 -> scroller!!.startScroll(ovalLeft, ovalTop, 0, -shotBackChange, shotBackDuration)1 -> scroller!!.startScroll(ovalLeft, ovalTop, shotBackChange, 0, shotBackDuration)2 -> scroller!!.startScroll(ovalLeft, ovalTop, 0, shotBackChange, shotBackDuration)3 -> scroller!!.startScroll(ovalLeft, ovalTop, -shotBackChange, 0, shotBackDuration)}invalidate()}/*** 移动小球*/fun moveTo(l: Int, t: Int, direction: Int, duration: Int, shotBack: Boolean) {isShotBack = shotBackmDuration = durationmCurrentDirection = directionmoveToLeft = lmoveToTop = tif (t == 0) {mCurrentDirection = 0startChange(30)} else if (l == displayWidth - bubbleWidth) {mCurrentDirection = 1startChange(30)} else if (t == displayHeight - bubbleHeight) {mCurrentDirection = 2startChange(30)} else if (l == 0) {mCurrentDirection = 3startChange(30)} else {invalidate()}}/*** 开始变形*/private fun startChange(change: Int) {changelength = changeif (mShotOver != null) {mShotOver!!.bubbleShotStart(mCurrentDirection)}flag = 0
//发生变形时,先初始化椭圆刚发生变形时的位置ovalLeft = moveToLeftovalTop = moveToTopovalRight = moveToLeft + bubbleWidthovalBottom = ovalTop + bubbleHeightwhen (mCurrentDirection) {0 -> scroller!!.startScroll(moveToLeft, moveToTop, 0, changelength, mDuration)1 -> scroller!!.startScroll(moveToLeft, moveToTop, changelength, 0, mDuration)2 -> scroller!!.startScroll(moveToLeft, moveToTop, 0, changelength, mDuration)3 -> scroller!!.startScroll(moveToLeft, moveToTop, changelength, 0, mDuration)}Log.i("qq","小球开始变形,方向=$mCurrentDirection 当前小球的坐标ovalLeft=$ovalLeft ovalTop=$ovalTop ovalRight=$ovalRight ovalBottom=$ovalBottom")invalidate()}/*** 回复变形前的状态*/private fun reverse() {flag = 1when (mCurrentDirection) {0 -> scroller!!.startScroll(newOvalLeft, newOvalTop, 0, -changelength, mDuration)1 -> scroller!!.startScroll(newOvalLeft, newOvalTop, -changelength, 0, mDuration)2 -> scroller!!.startScroll(newOvalLeft, newOvalTop, 0, -changelength, mDuration)3 -> scroller!!.startScroll(newOvalLeft, newOvalTop, -changelength, 0, mDuration)}invalidate()}fun setShotOver(shotOver: ShotOver?) {mShotOver = shotOver}/*** 碰撞变形效果完成*/interface ShotOver {fun bubbleShotStart(direction: Int)fun bubbleShotEnd()}/*** (辅助函数)//没有实现效果* 圆挤压成椭圆时,变形加速减少*//*public void circleToOvalAndAcceleratedReduce(Canvas canvas){if(gradient == 0){newOvalLeft = ovalLeft;newOvalTop = ovalTop;newOvalRight = ovalRight;newOvalBottom = ovalBottom;}if((offset - oldOffset) >= 10 && gradient == 0){Log.i("qq", "移动距离大于10时绘制一次");newOvalLeft = ovalLeft - offset;newOvalTop = currY - offset;newOvalRight = ovalRight + offset;newOvalBottom = ovalBottom - offset - offset;rectF.set(newOvalLeft, newOvalTop, newOvalRight, newOvalBottom);canvas.drawOval(rectF, paint);oldOffset = offset;gradient = 1;}else if((offset - oldOffset) >= 7 && gradient == 1){Log.i("qq", "移动距离大于7时绘制一次");newOvalLeft = ovalLeft - offset;newOvalTop = currY - offset;newOvalRight = ovalRight + offset;newOvalBottom = ovalBottom - offset - offset;rectF.set(newOvalLeft, newOvalTop, newOvalRight, newOvalBottom);canvas.drawOval(rectF, paint);gradient = 2;oldOffset = offset;}else if((offset - oldOffset) >= 4 && gradient == 2){Log.i("qq","移动距离大于4时绘制一次");newOvalLeft = ovalLeft - offset;newOvalTop = currY - offset;newOvalRight = ovalRight + offset;newOvalBottom = ovalBottom - offset - offset;rectF.set(newOvalLeft, newOvalTop, newOvalRight, newOvalBottom);canvas.drawOval(rectF, paint);gradient = 3;oldOffset = offset;}else if((offset - oldOffset) >= 2 && gradient == 3){Log.i("qq","移动距离大于2时绘制一次");newOvalLeft = ovalLeft - offset;newOvalTop = currY - offset;newOvalRight = ovalRight + offset;newOvalBottom = ovalBottom - offset - offset;rectF.set(newOvalLeft, newOvalTop, newOvalRight, newOvalBottom);canvas.drawOval(rectF, paint);gradient = -1;oldOffset = offset;}else{Log.i("qq", "移动绘制一次");rectF.set(newOvalLeft, newOvalTop, newOvalRight, newOvalBottom);canvas.drawOval(rectF, paint);}Log.i("qq", "圆挤压成椭圆,方向向北 currY=" + currY + " offset=" + offset);Log.i("qq", "圆挤压成椭圆,方向向北 newOvalLeft=" + newOvalLeft + " newOvalTop=" + newOvalTop + " newOvalRight=" + newOvalRight + " newOvalBottom=" + newOvalBottom);}*/
}

/*** 1.根据重力感应移动小球* 2.一般重力感应使用的重力加速,这样的话每次移动距离不是固定的* 3.此应用,将速度固定。* 4.小球碰撞到边缘时,会发生形变。(小球压缩形变)* 5.可以点击按钮添加,发生形变后回弹效果*/
class AnimationActivity : Activity(), View.OnClickListener {private var sensorManager: SensorManager? = nullprivate var sensor: Sensor? = nullprivate var init = false// 因为布局是填充父窗体的,且设置了出掉状态栏,所有求出的宽高就是屏幕的宽高。private var containerWidth = 0private var containerHeight = 0// 小球的宽高private val ballWidth = 360private val ballHeight = 360// 自定义球private lateinit var ball: BallViewTwo// 小球的起始位置private var ballX = 100fprivate var ballY = 100fprivate var currentState = -1 // 初始方向private var shotDirection = -1 // 小球发生碰撞时的那刻的方向// 初始化 东 西 南 北 四个方向private val NORTH = 0private val EAST = 1private val SOUTH = 2private val WEST = 3private var constantsSpeed = 100 // 每次斜边移动的距离private val SPEED = 10 // 比例private var canMove = true // 小球是否可以移动private val durationPiece = 150 // 执行动画的时间块private var duration = 450 // 初始速度下的执行时间private var isShotBack = false/*** -1: 小球正常移动* 0: 小球正在碰撞* 1: 小球碰撞刚结束*/private var shot = -1/** Called when the activity is first created. */override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN)setContentView(R.layout.activity_animation)// 初始化重力感应sensorManager = getSystemService(SENSOR_SERVICE) as SensorManagersensor = sensorManager!!.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)}private fun init() {val container = findViewById<View>(R.id.ball_container)findViewById<View>(R.id.accelerate).setOnClickListener(this) // 加速移动findViewById<View>(R.id.reduce).setOnClickListener(this) // 减少移动findViewById<View>(R.id.normal).setOnClickListener(this) // 正常速度移动findViewById<View>(R.id.isShowBack).setOnClickListener(this) // 是否弹一弹containerWidth = container.widthcontainerHeight = container.heightball = findViewById(R.id.ball)/*** 碰撞监听*/ball.setShotOver(object : BallViewTwo.ShotOver {override fun bubbleShotStart(direction: Int) {shotDirection = directionshot = 0 // 正在压缩变形canMove = false// Log.i("shotDirection", "小球发生碰撞时的方向==" + shotDirection);}override fun bubbleShotEnd() {shot = 1 // 刚压缩变形结束}})}/*** 移动小球* @param x* @param y*/private fun moveTo(x: Float, y: Float) {ballX += xballY += yif (ballX < 0) {ballX = 0f}if (ballY < 0) {ballY = 0f}if (ballX > containerWidth - ballWidth) {ballX = (containerWidth - ballWidth).toFloat()}if (ballY > containerHeight - ballHeight) {ballY = (containerHeight - ballHeight).toFloat()}ball.moveTo(ballX.toInt(), ballY.toInt(), currentState, duration, isShotBack)}private val listener = object : SensorEventListener {override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {// TODO Auto-generated method stub}override fun onSensorChanged(event: SensorEvent) {if (!init) returncurrentState = calc(event)// 如果当前方向不等于碰撞方向 并且圆刚碰撞结束if (shotDirection != currentState && shot == 1) {canMove = true}Log.i("direction", "当前方向==$currentState canMove=$canMove")// 可以移动的话才计算移动速度,调用移动方法if (canMove) {// 如果刚碰撞结束,根据位置,将其挪动一段距离if (shot == 1) {when (shotDirection) {0 -> moveTo(0f, 20f)1 -> moveTo(-20f, 0f)2 -> moveTo(0f, -20f)3 -> moveTo(20f, 0f)}shot = -1// 直接移动小球} else {constantSpeed(event)}} else {Log.i("qq", "正在执行“弹”,所以先不移动小球")}}}/*** 计算x,y轴应该移动的值(为了使每次移动距离保持不变)* @param event*/private fun constantSpeed(event: SensorEvent) {val x = event.values[SensorManager.DATA_X] * SPEEDval y = event.values[SensorManager.DATA_Y] * SPEEDval tan = x / yval movey: Doubleval movex: Doubleif (x == 0f && y != 0f) {movex = 0.0movey = constantsSpeed.toDouble()} else if (x != 0f && y == 0f) {movex = constantsSpeed.toDouble()movey = 0.0} else if (x == 0f && y == 0f) {movex = 0.0movey = 0.0} else {val temp = constantsSpeed / (tan * tan + 1)movey = Math.sqrt(temp.toDouble()) // 开根号movex = movey * tan}moveTo((if (x < 0) -Math.abs(movex) else Math.abs(movex)).toFloat(),(if (y < 0) -Math.abs(movey) else Math.abs(movey)).toFloat())}// 注册重力感应监听private fun register() {sensorManager?.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_GAME)}// 解除重力感应监听private fun unregister() {sensorManager?.unregisterListener(listener)Log.i("vv", "结束监听")}override fun onWindowFocusChanged(hasFocus: Boolean) {super.onWindowFocusChanged(hasFocus)if (hasFocus && !init) {init()init = true}}/*** 计算当前球的方向*/private fun calc(event: SensorEvent): Int {val x = event.values[0]val y = event.values[1]val tempVertical: Intval tempHorizontal: InttempHorizontal = when {x > 0 -> WESTx < 0 -> EASTelse -> -1}tempVertical = when {y > 0 -> SOUTHy < 0 -> NORTHelse -> -1}currentState = when {tempHorizontal == EAST && tempVertical == NORTH ->if (Math.abs(x) > Math.abs(y)) EAST else NORTHtempHorizontal == EAST && tempVertical == SOUTH ->if (Math.abs(x) > Math.abs(y)) EAST else SOUTHtempHorizontal == WEST && tempVertical == NORTH ->if (Math.abs(x) > Math.abs(y)) WEST else NORTHtempHorizontal == WEST && tempVertical == SOUTH ->if (Math.abs(x) > Math.abs(y)) WEST else SOUTHelse -> currentState}return currentState}override fun onDestroy() {super.onDestroy()unregister()}override fun onPause() {super.onPause()unregister()}override fun onRestart() {super.onRestart()register()}override fun onResume() {super.onResume()register()}override fun onClick(v: View) {when (v.id) {R.id.accelerate -> adjustSpeedAndDuration(5)R.id.reduce -> adjustSpeedAndDuration(-5)R.id.normal -> {constantsSpeed = 10duration = 450}R.id.isShowBack -> isShotBack = !isShotBack}}/*** 改变小球的移动速度和变形时间* 因为移动速度越快,碰撞时间越短*/private fun adjustSpeedAndDuration(change: Int) {constantsSpeed += changeduration = if (change < 0) {duration + durationPiece} else {duration - durationPiece}when {constantsSpeed <= 5 -> {constantsSpeed = 5duration = 750}constantsSpeed >= 25 -> {constantsSpeed = 25duration = 150}}}
}

 xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:tools="http://schemas.android.com/tools"tools:context=".ui.activity.AnimationActivity"><FrameLayoutandroid:id="@+id/ball_container"android:layout_width="match_parent"android:layout_height="match_parent"><com.hjq.demo.animationdemo.BallViewTwoandroid:id="@+id/ball"android:layout_width="360dp"android:layout_height="360dp" /></FrameLayout><Buttonandroid:id="@+id/accelerate"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="加速" /><Buttonandroid:id="@+id/reduce"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/accelerate"android:text="减速" /><Buttonandroid:id="@+id/normal"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/reduce"android:text="正常速度" /><Buttonandroid:id="@+id/isShowBack"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/normal"android:text="是否弹一弹" />
</RelativeLayout>

相关文章:

  • 【数据结构与算法】树的存储,森林 详解
  • @PreAuthorize与@Secured注解的区别是什么?
  • 【Java】已解决java.net.HttpRetryException异常
  • html侧导航栏客服栏
  • 【Nprogress】页面跳转进度条
  • 广告联盟流量变现app开发
  • 搜索进入AI蓝海时代:谁在成为新玩家?
  • 小程序项目业务逻辑回忆1
  • 赶紧收藏!2024 年最常见 20道设计模式面试题(九)
  • 【机器学习300问】129、RNN如何在情感分析任务中起作用的?
  • 信息技术课如何禁止学生玩游戏
  • 【Gradio】Custom Components | Gradio组件关键概念 后端
  • 9.2JavaEE——JDBCTemplate的常用方法(一)excute()方法
  • GenICam标准(三)
  • 【全开源】沃德会务会议管理系统(FastAdmin+ThinkPHP+Uniapp)
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • 78. Subsets
  • Angular2开发踩坑系列-生产环境编译
  • Centos6.8 使用rpm安装mysql5.7
  • Go 语言编译器的 //go: 详解
  • IOS评论框不贴底(ios12新bug)
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • Java小白进阶笔记(3)-初级面向对象
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • nginx 负载服务器优化
  • 简单实现一个textarea自适应高度
  • 爬虫模拟登陆 SegmentFault
  • 前端
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 少走弯路,给Java 1~5 年程序员的建议
  • 突破自己的技术思维
  • 微信小程序实战练习(仿五洲到家微信版)
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • 小而合理的前端理论:rscss和rsjs
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • gunicorn工作原理
  • ionic异常记录
  • ​比特币大跌的 2 个原因
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • $(function(){})与(function($){....})(jQuery)的区别
  • (07)Hive——窗口函数详解
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (ISPRS,2021)具有遥感知识图谱的鲁棒深度对齐网络用于零样本和广义零样本遥感图像场景分类
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (备忘)Java Map 遍历
  • (二)Optional
  • (二)测试工具
  • (附源码)ssm高校实验室 毕业设计 800008
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (推荐)叮当——中文语音对话机器人
  • (游戏设计草稿) 《外卖员模拟器》 (3D 科幻 角色扮演 开放世界 AI VR)
  • .“空心村”成因分析及解决对策122344