Flutter动画学习二

news2024/12/25 14:00:50

如何在 Flutter 中使用自定义动画和剪裁(clipping)实现一个简单的动画效果。

前置知识点学习

AnimationController

`AnimationController` 是 Flutter 动画框架中的一个核心类,用于控制动画的生命周期和状态。它提供了一种灵活的方式来定义动画的开始、结束、暂停、反向和速度调节等功能。

主要属性

  • `duration`: 定义动画的时长。可以是 `Duration` 类型的值,如 `Duration(milliseconds: 500)`。
  • `vsync`: 一个 `TickerProvider`,用于防止动画在不需要时消耗资源。通常在 `State` 类中通过 `SingleTickerProviderStateMixin` 提供。
  • `value`: 表示动画当前的进度,范围通常是 0.0 到 1.0。
  • `lowerBound` 和 `upperBound`: 定义动画值的范围,默认是 0.0 到 1.0。

主要方法

  • `forward()`: 正向播放动画,从当前值到 `upperBound`。
  • `reverse()`: 反向播放动画,从当前值到 `lowerBound`。
  • `repeat()`: 循环播放动画,可以设置次数和是否反向。
  • `stop()`: 停止动画。
  • `reset()`: 将动画值重置为 `lowerBound`。
  • `dispose()`: 销毁控制器,释放资源。在 `State` 的 `dispose` 方法中调用。

监听器

  • `addListener()`: 添加一个回调函数,每当动画的值改变时调用。
  • `addStatusListener()`: 添加一个回调函数,每当动画的状态改变时调用,比如开始、结束、正向播放、反向播放等。

使用示例

以下是一个简单的例子,演示如何使用 `AnimationController` 创建一个简单的透明度动画:

import 'package:flutter/material.dart';

class MyAnimationControllerExample extends StatefulWidget {
  const MyAnimationControllerExample({super.key});

  @override
  _MyAnimationControllerExampleState createState() {
    return _MyAnimationControllerExampleState();
  }
}

class _MyAnimationControllerExampleState
    extends State<MyAnimationControllerExample>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller =
        AnimationController(vsync: this, duration: const Duration(seconds: 2));

    _controller.addListener(() {
      setState(() {});
    });

    _controller.forward();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('AnimationController Example')),
      body: Center(
        child: Opacity(
          opacity: _controller.value,
          child: Container(
            width: 100,
            height: 100,
            color: Colors.blue,
          ),
        ),
      ),
    );
  }
}

解释

  • `AnimationController`: 控制动画的时长和进度。
  • `SingleTickerProviderStateMixin`: 为 `vsync` 提供 `TickerProvider`,防止不必要的资源消耗。
  • `addListener`: 在动画值改变时更新 UI。
  • `forward`: 使动画从 `lowerBound` 开始到 `upperBound` 结束。

FloatingActionButton

`FloatingActionButton`(FAB)是 Flutter 中一个用于执行主操作的圆形按钮。它通常悬浮在应用界面的某个位置,用户可以通过点击它来触发特定的操作或功能。FAB 是 Material Design 的一部分,常见于各种应用中,用于吸引用户注意并方便地进行交互。

关键属性

  • `child`: 该属性用于指定按钮内部的内容,通常是一个图标(`Icon`)或文本(`Text`)。这个内容会在按钮的中心显示。
  • `onPressed`: 一个回调函数,当用户点击按钮时会被调用。这个属性是必需的,因为它定义了按钮的行为。
  • `tooltip`: 当用户长按按钮时显示的提示文本,通常用于描述按钮的功能。
  • `backgroundColor`: 按钮的背景颜色。
  • `foregroundColor`: 按钮内容(如图标或文本)的颜色。
  • `elevation`: 按钮的阴影深度,影响按钮的浮动效果。
  • `shape`: 定义按钮的形状,默认是圆形,也可以自定义为其他形状。
  • `heroTag`: 用于在页面切换时标识 FAB 的唯一标识符,默认提供避免动画冲突。

使用示例

下面是一个使用 `FloatingActionButton` 的简单示例:

import 'package:flutter/material.dart';

class FloatingActionButtonExample extends StatelessWidget {
  const FloatingActionButtonExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('FloatingActionButton Example'),
        ),
        body: const Center(
          child: Text("Press the button below!"),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            print("FAB clicked!");
          },
          tooltip: 'Increment',
          child: const Icon(Icons.add),
        ),
        floatingActionButtonLocation: FloatingActionButtonLocation.endDocked);
  }
}

解释

  • `Scaffold`: Flutter 提供的一个布局结构,支持 Material Design 的组件,包括 FAB。
  • `floatingActionButton`: `Scaffold` 的一个属性,用于指定屏幕上的 FAB。
  • `onPressed`: 定义当 FAB 被点击时的行为。在这个例子中,它只是打印一条消息。
  • `Icon`: 在 FAB 中展示的内容,在这个例子中是一个加号图标。
  • `floatingActionButtonLocation`: 用于定义 FAB 在屏幕中的位置,如居中、靠右或靠左等。

常见使用场景

  • 主要操作: FAB 通常用于执行应用的主要操作,如在邮件应用中创建新邮件、在社交应用中发布新内容等。
  • 辅助功能: 在一些应用中,FAB 可以用于快速访问某些辅助功能。
  • 动态操作: 在某些应用中,FAB 的功能可能会根据上下文动态变化,比如在不同的页面中执行不同的操作。

通过 `FloatingActionButton`,开发者可以在 Flutter 应用中轻松实现符合 Material Design 指导原则的交互元素。它是一个非常直观且易于使用的组件,用于增强用户体验。

CustomClipper

`CustomClipper` 是 Flutter 提供的一个抽象类,用于创建自定义剪裁(clipping)效果。通过实现 `CustomClipper`,你可以定义任意形状的剪裁路径,应用于组件的外观。

主要方法

`CustomClipper` 包含两个主要方法,你需要在子类中实现它们:

1.`getClip(Size size)`:

  • 返回一个 `Path` 对象,该对象定义了应该如何剪裁组件。
  • `Size` 参数提供了组件的大小,你可以根据这个大小来计算剪裁路径。

2.`shouldReclip(CustomClipper oldClipper)`:

  • 返回一个布尔值,决定是否需要重新剪裁。当剪裁路径依赖于某些动态变化的参数时,你需要在这个方法中进行判断。
  • 通常,如果你的剪裁路径是固定不变的,可以返回 `false`。

使用方法

1.创建一个 `CustomClipper` 子类:

  • 实现 `getClip` 方法来定义剪裁路径。
  • 实现 `shouldReclip` 方法来决定何时重新剪裁。

2.使用 `ClipPath` 或其他 `Clip*` 组件:

  • 将自定义 `CustomClipper` 实例传递给 `ClipPath`、`ClipRect`、`ClipOval` 等组件的 `clipper` 属性。

示例

以下是一个简单的示例,展示如何使用 `CustomClipper` 来创建一个三角形剪裁效果:

import 'package:flutter/material.dart';

class TriangleClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    final path = Path();
    path.moveTo(size.width / 2, 0);
    path.lineTo(size.width, size.height);
    path.lineTo(0, size.height);
    path.close();
    return path;
  }

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    // 如果路径不依赖外部状态,可以返回 false
    return false;
  }
}

class CustomClipperExample extends StatelessWidget {
  const CustomClipperExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('CustomClipper Example'),
      ),
      body: Center(
        child: ClipPath(
          clipper: TriangleClipper(), // 使用自定义的 TriangleClipper
          child: Container(
            width: 200,
            height: 200,
            color: Colors.blue,
          ),
        ),
      ),
    );
  }
}

解释

  • TriangleClipper`: 自定义的剪裁器,实现了一个简单的三角形路径。
  • `getClip` 方法: 定义了一个三角形的路径。
  • `ClipPath`: 使用 `TriangleClipper` 将子组件剪裁成三角形。

使用场景

  • 自定义形状: 当你需要超出标准形状的剪裁效果时,比如特定的波浪形、星形等。
  • 动态剪裁: 如果剪裁形状需要根据某些动态参数变化,可以通过 `shouldReclip` 来控制重新剪裁。
  • 视觉效果: 增强 UI 的视觉效果,通过不规则的形状吸引用户注意力。

lerpDouble函数解析

在 Flutter 中,`lerpDouble` 是一个用于在两个 `double` 值之间进行线性插值的方法。它通常用于动画和其他需要平滑过渡的场景。

主要功能

`lerpDouble` 的主要功能是根据给定的插值因子 `t`,计算出两个 `double` 值之间的中间值。这个过程称为线性插值(linear interpolation),简称 lerp。

方法签名

double? lerpDouble(
  num? a,
  num? b,
  double t,
)

参数

  • `a`: 起始值,可以是 `double` 或 `null`。如果为 `null`,则在计算时视为 0.0。
  • `b`: 结束值,可以是 `double` 或 `null`。如果为 `null`,则在计算时视为 0.0。
  • `t`: 插值因子,是一个介于 0.0 到 1.0 之间的 `double`。当 `t` 为 0.0 时,返回 `a`;当 `t` 为 1.0 时,返回 `b`;在这之间返回 `a` 和 `b` 的插值。

返回值

返回一个 `double` 类型的值,表示 `a` 和 `b` 之间的插值。如果 `a` 和 `b` 都为 `null`,则返回 `null`。

用法示例

以下是一个简单的示例,展示如何使用 `lerpDouble` 计算两个值之间的插值:

import 'dart:ui';

void main() {
  double? start = 10.0;
  double? end = 20.0;

  double t = 0.25; // 插值因子

  double? interpolatedValue = lerpDouble(start, end, t);

  print('Interpolated Value: $interpolatedValue'); // 输出: Interpolated Value: 12.5
}

解释

  • 在上面的例子中,`start` 是 10.0,`end` 是 20.0,`t` 是 0.25。
  • `lerpDouble` 返回两个值之间的 25% 位置上的值,即 12.5。

使用场景

  • 动画: 在动画过程中,计算属性的中间值,比如位置、大小、透明度等。
  • 过渡效果: 在不同状态之间平滑过渡,例如颜色渐变、尺寸变化等。
  • 自定义插值: 在需要自定义插值逻辑的情况下,用于计算中间值。

`lerpDouble` 是一个简单却强大的工具,允许开发者在两个数值之间创建平滑的过渡效果,非常适合用于动画和动态 UI 变化中。

Path

在 Flutter 中,`Path` 是一个用于定义向量形状的类。它允许开发者创建复杂的几何图形,通过一系列的直线和曲线来定义路径。`Path` 类可以用于绘制形状、创建剪裁区域以及生成自定义绘制效果。

基本用法

`Path` 提供了一系列方法,用于定义形状的边界。以下是一些常用的方法:

  • `moveTo(double x, double y)`: 移动当前点到指定的坐标,开始新的子路径。
  • `lineTo(double x, double y)`: 从当前点绘制一条直线到指定的坐标。
  • `arcTo(Rect rect, double startAngle, double sweepAngle, bool forceMoveTo)`: 绘制一个圆弧,基于一个矩形的边界。
  • `quadraticBezierTo(double x1, double y1, double x2, double y2)`: 绘制一个二次贝塞尔曲线。
  • `cubicTo(double x1, double y1, double x2, double y2, double x3, double y3)`: 绘制一个三次贝塞尔曲线。
  • `close()`: 关闭当前子路径,连接最后一个点到第一个点,形成一个封闭的形状。

示例

下面是一个简单的示例,使用 `Path` 绘制一个三角形:

import 'package:flutter/material.dart';

class PathExampleDemo extends StatelessWidget {
  const PathExampleDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Path Example'),
      ),
      body: Center(
        child: CustomPaint(
          size: const Size(200, 200),
          painter: TrianglePainter(),
        ),
      ),
    );
  }
}

class TrianglePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.blue
      ..style = PaintingStyle.fill;

    final path = Path();
    //顶点
    path.moveTo(size.width / 2, 0);
    //右下角
    path.lineTo(size.width, size.height);
    //左下角
    path.lineTo(0, size.height);
    path.close();

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

解释

  • `CustomPainter`: 用于自定义绘制。`paint` 方法中使用 `Canvas` 对象进行绘制。
  • `Path`: 定义路径的形状。在这个例子中,绘制了一个简单的三角形。
  • `Canvas.drawPath`: 使用 `Path` 和 `Paint` 对象在画布上绘制路径。

使用场景

  • 自定义形状: `Path` 可以定义任意形状,用于自定义绘制或剪裁。
  • 复杂图形: 使用贝塞尔曲线和弧形,可以创建复杂的图形和路径。
  • 动画路径: 在动画中,可以使用 `Path` 来定义对象的运动轨迹。

注意事项

  • 路径方向: 在定义路径时,方向(顺时针或逆时针)可能会影响填充规则。
  • 性能: 复杂路径可能会影响性能,尤其是在动画中,请合理使用。

AnimatedBuilder

`AnimatedBuilder` 是 Flutter 动画框架中的一个小部件,用于将动画与 UI 组件进行绑定。它提供了一种高效的方法来重建与动画相关的部分 UI,而无需重建整个 widget 树。

核心概念

`AnimatedBuilder` 通过监听一个 `Listenable` 对象(通常是 `AnimationController` 或其他 `Animation` 对象)来决定何时重建 UI。当动画对象的值发生变化时,`AnimatedBuilder` 会调用其构建方法,从而更新与动画相关的 UI。

主要属性

  • `animation`: 一个 `Listenable` 对象,通常是 `Animation` 或 `AnimationController`。`AnimatedBuilder` 监听这个对象的变化。
  • `builder`: 一个回调函数,接受两个参数:`BuildContext` 和 `Widget`。在这个函数中,你可以根据动画的当前状态来构建和返回一个新的 widget 树。
  • `child`: 一个可选的小部件,当它在动画变化时不需要重建时,可以作为优化传递给 `builder`。这样可以避免不必要的重建。

使用示例

以下是一个使用 `AnimatedBuilder` 的简单示例,展示如何创建一个旋转动画:

import 'package:flutter/material.dart';

class AnimatedBuilderExample extends StatefulWidget {
  const AnimatedBuilderExample({super.key});

  @override
  _AnimatedBuilderExampleState createState() {
    return _AnimatedBuilderExampleState();
  }
}

class _AnimatedBuilderExampleState extends State<AnimatedBuilderExample>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('AnimatedBuilder Example')),
      body: Center(
        child: AnimatedBuilder(
          animation: _controller,
          builder: (context, child) {
            return Transform.rotate(
              angle: _controller.value * 2.0 * 3.14,
              child: child,
            );
          },
          child: Container(
            width: 100,
            height: 100,
            color: Colors.blue,
          ),
        ),
      ),
    );
  }

  @override
  void initState() {
    super.initState();
    _controller =
        AnimationController(vsync: this, duration: const Duration(seconds: 2))
          ..repeat(); //无限循环动画
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

解释

  • `AnimationController`: 控制动画的时长和进度。在这个例子中,`_controller` 在 2 秒内从 0.0 到 1.0 循环。
  • `AnimatedBuilder`: 监听 `_controller` 的变化,并在 `builder` 回调中根据动画的当前值更新 UI。
  • `Transform.rotate`: 根据动画的当前值旋转 `child`,实现旋转效果。
  • `child`: 传递给 `AnimatedBuilder` 的 `child` 是一个蓝色的方块,它在动画期间不会重建。

使用场景

  • 动画优化: 当只有部分 UI 需要随着动画更新时,`AnimatedBuilder` 可以避免整个 widget 树的重建。
  • 复杂动画: 在需要多个动画组合或复杂动画效果时,`AnimatedBuilder` 提供了一种灵活的方式来管理和应用这些动画。

自定义动画代码学习

import 'dart:math';
import 'dart:ui';

import 'package:flutter/material.dart';

class AnimaDemoPage22 extends StatefulWidget {
  const AnimaDemoPage22({super.key});

  @override
  _AnimaDemoPageState22 createState() {
    return _AnimaDemoPageState22();
  }
}

class _AnimaDemoPageState22 extends State<AnimaDemoPage22>
    with SingleTickerProviderStateMixin {
  late AnimationController controller;
  Animation? animation;

  @override
  void initState() {
    super.initState();

    controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
    );

    animation = CurvedAnimation(parent: controller, curve: Curves.easeInSine);
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("AnimaDemoPage22"),
      ),
      body: Container(
        color: Colors.blueGrey,
        child: MyCRAnimation(
          minR: 0,
          maxR: 250,
          offset: Offset(MediaQuery.sizeOf(context).width / 2,
              MediaQuery.sizeOf(context).height / 2),
          animation: animation as Animation<double>?,
          child: Center(
            child: Container(
              alignment: Alignment.center,
              height: 250,
              width: 250,
              color: Colors.greenAccent,
              child: const Text("动画测试"),
            ),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          if (controller.status == AnimationStatus.completed ||
              controller.status == AnimationStatus.forward) {
            controller.reverse();
          } else {
            controller.forward();
          }
        },
        child: const Text("点击"),
      ),
    );
  }
}

class MyCRAnimation extends StatelessWidget {
  final Offset? offset;
  final double? minR;
  final double? maxR;
  final Widget child;

  final Animation<double>? animation;

  const MyCRAnimation(
      {super.key,
      required this.child,
      required this.animation,
      this.offset,
      this.minR,
      this.maxR});

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
        animation: animation!,
        builder: (_, __) {
          return ClipPath(
            clipper: MyAnimationClipper(
                value: animation!.value,
                minR: minR,
                maxR: maxR,
                offset: offset),
            child: child,
          );
        });
  }
}

class MyAnimationClipper extends CustomClipper<Path> {
  final double? value;
  final double? minR;
  final double? maxR;
  final Offset? offset;

  MyAnimationClipper({this.value, this.offset, this.minR, this.maxR});

  @override
  Path getClip(Size size) {
    var path = Path();
    var offset = this.offset ?? Offset(size.width / 2, size.height / 2);
    var maxRadius = minR ?? radiusSize(size, offset);
    var minRadius = maxR ?? 0;

    var radius = lerpDouble(minRadius, maxRadius, value!)!;
    var rect = Rect.fromCircle(center: offset, radius: radius);

    path.addOval(rect);
    return path;
  }

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return true;
  }

  double radiusSize(Size size, Offset offset) {
    final height = max(offset.dy, size.height - offset.dy);
    final width = max(offset.dx, size.width - offset.dx);
    return sqrt(width * width + height * height);
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2265317.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【目标跟踪综述及关键技术】

1.多目标跟踪任务介绍 定义 多目标跟踪旨在将视频序列中感兴趣的目标检测出来&#xff0c;并赋予每个目标单独的编号&#xff0c;在整个序列中形成目标的轨迹。 分类 online&#xff1a;算法在推理目标身份过程中&#xff0c;只能看见当前帧以及之前的帧&#xff08;关联&a…

重温设计模式--模板方法模式

文章目录 一、模板方法模式概述二、模板方法模式UML图三、优点1代码复用性高2可维护性好3扩展性强 四、缺点五、使用场景六、C 代码示例1七、 C 代码示例2 一、模板方法模式概述 定义&#xff1a;定义一个操作中的算法骨架&#xff0c;而降一些步骤延迟到子类中。模板方法使得…

@vue/cli启动异常:ENOENT: no such file or directory, scandir

参考:https://blog.csdn.net/qq_44355188/article/details/122239566 首先异常报错是&#xff1a;ENOENT: no such file or directory, scandir ‘D:\Data\Project\VueProject\hello\node_modulesvue\cli-plugin-eslint\locales’&#xff1b;我的vue/cli版本是 4.5.15 重点是…

Jenkins集成部署(图文教程、超级详细)

一、CI/CD 的概念 ​ CI/CD一般包含三个概念&#xff1a; 持续集成&#xff08;Continuous Integration &#xff0c;CI&#xff09; 持续交付&#xff08;Continuous Delivery&#xff09; 持续部署&#xff08;Continuous Deploy&#xff09; ​ CI/CD 是现代软件开发的重要…

2.在 Vue 3 中使用 ECharts 实现动态时间轴效果

在前端开发中&#xff0c;时间轴&#xff08;Timeline&#xff09;是一种常见且有效的方式来展示时间相关的数据。在本篇文章中&#xff0c;我们将展示如何在 Vue 3 项目中使用 ECharts 创建一个具有动态时间范围的时间轴&#xff0c;并添加了今日时间的标记以及通过按钮来前进…

【EthIf-13】EthIfGeneral容器配置-01

1.EthIfGeneral类图结构 下面是EthIfGeneral配置参数的类图&#xff0c;比较重要的参数就是配置&#xff1a; 接收中断是否打开发送确认中断是否打开EthIf轮询周期 1.EthIfGeneral参数的含义

卓软计量业务管理平台 image.ashx 任意文件读取漏洞复现

0x01 产品简介 卓软计量业务管理平台是一款专为计量测试检定机构设计的信息化管理系统。随着社会经济的不断发展,计量测试检定机构面临的管理规范化、技术水平、检测效率、服务能力以及行业竞争等问题日益增多。卓软计量业务管理平台旨在通过信息化手段,帮助机构实现业务管理…

BCSP-X 2024 Scratch图形化编程 小学低年级组 真题

BCSP-X 2024-2 图形化编程 小学低年级组 真题 题目总数&#xff1a;40 总分数&#xff1a;100 选择题 第 1 题 单选题 在下面各世界顶级的奖项中&#xff0c;为计算机科学与技术领域做出杰出贡献的科学 家设立的奖项是?( ) A. 奥斯卡奖 B. 诺贝尔奖 C. 菲尔兹…

GCP GCA认证考试Case错题库1(JenciMart+Helicopter+EHR)

GCP GCA认证考试Case错题库1(JenciMartHelicopterEHR) 整理by Moshow郑锴https://zhengkai.blog.csdn.net/ JenciMart 在生产和开发资源之间进行管理职责分离的最小权限模型中&#xff0c;最佳实践是每个应用程序的每个阶段都有自己的项目。这种设置确保权限是细化的&#xf…

centos权限大集合,覆盖多种权限类型,解惑权限后有“. + t s”问题!

在 CentOS 系统中&#xff0c;权限管理是操作系统的核心功能之一&#xff0c;确保不同用户和进程对文件、目录以及设备的访问被合理控制。 权限系统主要包括传统的 Unix 权限模型、特殊权限&#xff08;SetUID、SetGID、Sticky 位&#xff09;和更精细的访问控制列表&#xff…

HarmonyOS NEXT 技术实践-基于基础视觉服务实现骨骼点识别

本示例展示了如何在HarmonyOS Next中实现基于基础视觉服务的骨骼点识别功能。骨骼点识别是计算机视觉中的一项重要技术&#xff0c;广泛应用于运动分析、健身监控和增强现实等领域。通过使用HarmonyOS Next提供的视觉API&#xff0c;开发者能够轻松地对人物图像进行骨骼点检测&…

【RAG实战】语言模型基础

语言模型赋予了计算机理解和生成人类语言的能力。它结合了统计学原理和深度神经网络技术&#xff0c;通过对大量的样本数据进行复杂的概率分布分析来学习语言结构的内在模式和相关性。具体地&#xff0c;语言模型可根据上下文中已出现的词序列&#xff0c;使用概率推断来预测接…

workman服务端开发模式-应用开发-vue-element-admin挂载websocket

一、项目根目录main.js添加全局引入 import /utils/websocket 二、在根目录app.vue 中初始化WebSocket连接 <template><div id"app"><router-view /></div> </template><script>import store from ./store export default {n…

2024-12-24 NO1. XR Interaction ToolKit 环境配置

文章目录 1 软件配置2 安装 XRToolKit3 配置 OpenXR4 安装示例场景5 运行测试 1 软件配置 Unity 版本&#xff1a;Unity6000.0.26 ​ 2 安装 XRToolKit 创建新项目&#xff08;URP 3D&#xff09;&#xff0c;点击进入 Asset Store。 进入“Unity Registry”页签&#xff0…

华为手机鸿蒙4.2连接不上adb

1、下载HiSuite华为手机助手 https://consumer.huawei.com/cn/support/hisuite/ 2、安装后点连接 3、就可以adb连接了

GitPuk安装配置指南

GitPuk是一款开源免费的代码管理工具&#xff0c;上篇文章已经介绍了Gitpuk的功能与优势&#xff0c;这篇文章将为大家讲解如何快速安装和配置GitPuk&#xff0c;助力你快速的启动GitPuk管理代码 1. 安装 支持 Windows、Mac、Linux、docker 等操作系统。 1.1 Windows安装 下载…

【从零开始入门unity游戏开发之——C#篇20】C#面向对象的封装——静态成员(`static`)(静态字段、静态方法、静态属性、静态构造函数、静态类)

文章目录 静态成员&#xff08;static&#xff09;1、静态成员的特点&#xff1a;2、为什么可以直接点出来使用&#xff1f;3、不同的静态成员介绍3.1. 静态字段3.2. 静态方法3.3. 静态属性3.4. 静态构造函数3.5. 静态类 4、静态成员的优缺点优点&#xff1a;缺点&#xff1a; …

【Yonghong 企业日常问题 06】上传的文件不在白名单,修改allow.jar.digest属性添加允许上传的文件SH256值?

文章目录 前言问题描述问题分析问题解决1.允许所有用户上传驱动文件2.如果是想只上传白名单的驱动 前言 该方法适合永洪BI系列产品&#xff0c;包括不限于vividime desktop&#xff0c;vividime z-suit&#xff0c;vividime x-suit产品。 问题描述 当我们连接数据源的时候&a…

我的JAVA-Web基础(2)

1.JDBC 防止sql注入 2.JSP JSP的基本语法 基本语法是 <% %> Java代码 <% %> 输出变量 可以转换成${变量}的EL表达式 <%! %>定义变量 JSP的基本语法包括以下几个主要部分&#xff1a; 1. 表达式&#xff08;Expression&#xff09; 表达式用于将…

新闻网站的个性化推荐:机器学习的应用

3.1可行性分析 开发者在进行开发系统之前&#xff0c;都需要进行可行性分析&#xff0c;保证该系统能够被成功开发出来。 3.1.1技术可行性 开发该新闻网站所采用的技术是vue和MYSQL数据库。计算机专业的学生在学校期间已经比较系统的学习了很多编程方面的知识&#xff0c;同时也…