【Flutter】交错动画自定义动画Hero动画

news2024/11/18 1:25:24

🔥 本文由 程序喵正在路上 原创,CSDN首发!
💖 系列专栏:Flutter学习
🌠 首发时间:2024年5月29日
🦋 欢迎关注🖱点赞👍收藏🌟留言🐾

目录

    • 交错动画
    • 自定义动画
      • TweenAnimationBuilder自定义隐式动画
      • AnimatedBuilder自定义显式动画
    • Hero动画
      • Hero动画的应用一
      • Hero动画的应用二
      • 配置Hero动画的执行时间
    • Hero+photo_view实现类似微信朋友圈图片预览
      • photo_view预览单张图片
      • photo_view预览多张图片

交错动画

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomePage(),
    );
  }
}

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

  
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;

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

    _controller.addListener(() {
      print(_controller.value);
    });
  }

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

  void _toggleAnimation() {
    if (_controller.status == AnimationStatus.completed) {
      _controller.reverse();
    } else {
      _controller.forward();
    }
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: _toggleAnimation,
        child: const Icon(Icons.refresh),
      ),
      appBar: AppBar(
        title: const Text('AnimatedIcon'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            SlidingBox(
              controller: _controller,
              color: Colors.blue[200],
              curve: const Interval(0, 0.2),
            ),
            SlidingBox(
              controller: _controller,
              color: Colors.blue[400],
              curve: const Interval(0.2, 0.4),
            ),
            SlidingBox(
              controller: _controller,
              color: Colors.blue[600],
              curve: const Interval(0.4, 0.6),
            ),
            SlidingBox(
              controller: _controller,
              color: Colors.blue[800],
              curve: const Interval(0.6, 0.8),
            ),
            SlidingBox(
              controller: _controller,
              color: Colors.blue[900],
              curve: const Interval(0.8, 1),
            ),
          ],
        ),
      ),
    );
  }
}

class SlidingBox extends StatelessWidget {
  final AnimationController controller;
  final Color? color;
  final Curve curve;
  const SlidingBox(
      {super.key,
      required this.controller,
      required this.color,
      required this.curve});

  
  Widget build(BuildContext context) {
    return SlideTransition(
      position: Tween(begin: const Offset(-0.2, 1), end: const Offset(0.3, 0))
          .chain(CurveTween(curve: Curves.bounceInOut))
          .chain(CurveTween(curve: curve))
          .animate(controller),
      child: Container(
        width: 220,
        height: 60,
        color: color,
      ),
    );
  }
}

在这里插入图片描述

自定义动画

TweenAnimationBuilder自定义隐式动画

每当 Tweenend 发生变化的时候就会触发动画。

大小变化的动画:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomePage(),
    );
  }
}

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

  
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  bool flag = true;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('大小变化'),
      ),
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.refresh),
        onPressed: () {
          setState(() {
            flag = !flag;
          });
        },
      ),
      body: Center(
        child: TweenAnimationBuilder(
          tween: Tween(begin: 100.0, end: flag ? 100.0 : 200.0),
          duration: const Duration(seconds: 1),
          builder: ((context, value, child) {
            return Icon(
              Icons.star,
              color: Colors.red,
              size: value,
            );
          }),
        ),
      ),
    );
  }
}

在这里插入图片描述

效果:点击浮动按钮,五角星的大小会变化。

透明度变化的动画:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomePage(),
    );
  }
}

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

  
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  bool flag = true;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('透明度变化'),
      ),
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.refresh),
        onPressed: () {
          setState(() {
            flag = !flag;
          });
        },
      ),
      body: Center(
        child: TweenAnimationBuilder(
          tween: Tween(begin: 0.0, end: flag ? 0.2 : 1.0),
          duration: const Duration(seconds: 1),
          builder: ((context, value, child) {
            return Opacity(
              opacity: value,
              child: Container(color: Colors.blue, width: 200, height: 200),
            );
          }),
        ),
      ),
    );
  }
}

在这里插入图片描述

效果:点击浮动按钮,盒子的透明度会变化。

AnimatedBuilder自定义显式动画

透明度动画:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomePage(),
    );
  }
}

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

  
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 1),
    )..repeat(reverse: true); //.. 连缀操作
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('透明度动画'),
      ),
      body: Center(
        child: AnimatedBuilder(
          animation: _controller,
          builder: (BuildContext context, Widget? child) {
            return Opacity(
              opacity: _controller.value,	//从0到1变化	
              child: Container(
                width: 200,
                height: 200,
                color: Colors.blue,
                child: const Text('我是一个Text组件'),
              ),
            );
          },
        ),
      ),
    );
  }
}

在这里插入图片描述

效果:盒子的透明度会自动不停变化。

自定义变化范围:

上面代码中 opacity 的值我们也可以使用 Tween 来设置:

opacity: Tween(begin: 0.5, end: 1.0).animate(_controller).value, //从0.5到1变化

位置变化:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomePage(),
    );
  }
}

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

  
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 1),
    )..repeat(reverse: true); //.. 连缀操作
  }

  
  Widget build(BuildContext context) {
    Animation y = Tween(begin: -120.0, end: 120.0)
        .chain(CurveTween(curve: Curves.easeIn))
        // .chain(CurveTween(curve: const Interval(0.2, 0.6)))
        .animate(_controller);

    return Scaffold(
      appBar: AppBar(
        title: const Text('位置变化'),
      ),
      body: Center(
        child: AnimatedBuilder(
          animation: _controller,
          builder: (BuildContext context, Widget? child) {
            return Container(
              width: 200,
              height: 200,
              color: Colors.blue,
              transform: Matrix4.translationValues(0, y.value, 0),
              child: const Text('我是一个Text组件'),
            );
          },
        ),
      ),
    );
  }
}

在这里插入图片描述

效果:一个盒子在不停上下跳动。

child优化:

return Scaffold(
  appBar: AppBar(
    title: const Text('child优化'),
  ),
  body: Center(
    child: AnimatedBuilder(
      animation: _controller,
      builder: (BuildContext context, Widget? child) {
        return Container(
          width: 200,
          height: 200,
          color: Colors.blue,
          transform: Matrix4.translationValues(0, y.value, 0),
          child: child,
        );
      },
      child: const Text('我是一个Text组件'),
    ),
  ),
);

当我们将 Text 组件放在 builder 函数内部时,Text 组件会根据 _animation 的值进行重建。这意味着在每个动画帧上,Text 组件都会被重新构建,即使 Text 内容没有发生变化。这可能会导致不必要的重建和性能损失。

相比之下,将 Text 组件放在 builder 函数外部,则不会在每个动画帧上进行重建。Text 组件只会在初始渲染时创建一次,并且不会随着动画的进度而重建。这样可以减少重建次数,提高性能。

因此,将 Text 组件放在 builder 函数外部是一种更优化的做法,特别是当 Text 内容不会随动画进度而改变时。只有当动画进度对 Text 内容有影响时,才需要将 Text 组件放在 builder 函数内部,以确保 Text 能够根据动画的进度进行更新。

Hero动画

Hero动画的应用一

微信朋友圈点击小图片的时候会有一个动画效果到大图预览,这个动画效果就可以使用Hero 动画实现。

Hero 指的是可以在路由(页面)之间 “飞行” 的 widget,简单来说 Hero 动画就是在路由切换时,有一个共享的 widget 可以在新旧路由间切换。

我们回到之前写的自定义底部导航实现页面切换的代码:

在这里插入图片描述

我们将 home.dart 进行改进,并添加一个 hero.dart 用于演示 Hero 动画,具体代码如下:

main.dart

import 'package:flutter/material.dart';
import './routers/router.dart';

void main() {
  runApp(const MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      initialRoute: "/",
      onGenerateRoute: onGenerateRoute,
    );
  }
}

home.dart

import 'package:flutter/material.dart';
import '../../res/listData.dart';

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

  
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  List<Widget> _getListData() {
    var tempList = listData.map((value) {
      return GestureDetector(
        onTap: () {
          Navigator.pushNamed(context, "/hero", arguments: {
            "imageUrl": value['imageUrl'],
            "author": value['author'],
          });
        },
        child: Container(
          decoration: BoxDecoration(
            border: Border.all(
                color: const Color.fromRGBO(233, 233, 233, 0.9), width: 1),
          ),
          child: Column(
            children: [
              Hero(
                tag: value['imageUrl'],	//唯一值
                child: Image.network(value['imageUrl']),
              ),
              const SizedBox(height: 12),
              Text(
                value['title'],
                textAlign: TextAlign.center,
                style: const TextStyle(fontSize: 17),
              ),
            ],
          ),
        ),
      );
    });

    return tempList.toList();
  }

  
  Widget build(BuildContext context) {
    return GridView.count(
      crossAxisCount: 2, //一行的Widget数量
      crossAxisSpacing: 10.0, //水平方向的子Widget之间的间距
      mainAxisSpacing: 10.0, //垂直方向的子Widget之间的间距
      padding: const EdgeInsets.all(10),
      children: _getListData(),
    );
  }
}

hero.dart

import 'package:flutter/material.dart';

class HeroPage extends StatefulWidget {
  final Map arguments;
  const HeroPage({super.key, required this.arguments});

  
  State<HeroPage> createState() => _HeroPageState();
}

class _HeroPageState extends State<HeroPage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('详情页面'),
      ),
      body: ListView(
        children: [
          Hero(
            tag: widget.arguments['imageUrl'],	//tag值要与home.dart中一致
            child: Image.network(widget.arguments['imageUrl']),
          ),
          const SizedBox(height: 20),
          Padding(
            padding: const EdgeInsets.fromLTRB(30, 5, 30, 0),
            child: Text(
              widget.arguments['author'],
              style: const TextStyle(fontSize: 22),
            ),
          ),
        ],
      ),
    );
  }
}

router.dart

import 'package:flutter/cupertino.dart';
import '../pages/hero.dart';
import '../pages/tabs/category.dart';
import '../pages/tabs/home.dart';
import '../pages/tabs/message.dart';
import '../pages/tabs/setting.dart';
import '../pages/tabs/user.dart';
import '../pages/tabs.dart';

//1. 定义路由
final Map routes = {
  "/": (context) => const Tabs(),
  "/home": (context) => const HomePage(),
  "/category": (context) => const CategoryPage(),
  "/setting": (context) => const SettingPage(),
  "/message": (context) => const MessagePage(),
  "/user": (context) => const UserPage(),
  "/hero": (context, {arguments}) => HeroPage(arguments: arguments)
};

//2. 配置onGenerateRoute,固定写法
var onGenerateRoute = (settings) {
  // 统一处理
  final String? name = settings.name;
  final Function? pageContentBuilder = routes[name];
  if (pageContentBuilder != null) {
    if (settings.arguments != null) {
      final Route route = CupertinoPageRoute(
          builder: (context) =>
              pageContentBuilder(context, arguments: settings.arguments));
      return route;
    } else {
      final Route route =
          CupertinoPageRoute(builder: (context) => pageContentBuilder(context));
      return route;
    }
  }
  return null;
};

在这里插入图片描述

点击图片会进入对应的详情页面:

在这里插入图片描述

在这里插入图片描述

Hero动画的应用二

hero.dart 换成这个:

import 'package:flutter/material.dart';

class HeroPage extends StatefulWidget {
  final Map arguments;
  const HeroPage({super.key, required this.arguments});

  
  State<HeroPage> createState() => _HeroPageState();
}

class _HeroPageState extends State<HeroPage> {
  
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        Navigator.pop(context);
      },
      child: Hero(
        tag: widget.arguments['imageUrl'],
        child: Scaffold(
          //加Scaffold是为了点击屏幕任意位置都可以返回
          backgroundColor: Colors.black,
          body: Center(
            child: AspectRatio(
              aspectRatio: 16 / 9,
              child: Image.network(
                widget.arguments['imageUrl'],
                fit: BoxFit.cover,
              ),
            ),
          ),
        ),
      ),
    );
  }
}

配置Hero动画的执行时间

  1. 引入 scheduler.dart

    import 'package:flutter/scheduler.dart';
    
  2. 设置动画时间

    void initState() {
      super.initState();
      timeDilation = 1.0; //设置动画时间
    }
    

Hero+photo_view实现类似微信朋友圈图片预览

  • photo_view 插件支持预览图片,可放大、缩小、滑动图片
  • photo_view 官方地址:https://pub-web.flutter-io.cn/packages/photo_view

photo_view预览单张图片

  1. 配置依赖

    dependencies:
      photo_view: ^0.15.0
    
  2. 引入

    import 'package:photo_view/photo_view.dart';
    
  3. 单张图片的预览

    改进 hero.dart

    import 'package:flutter/material.dart';
    import 'package:photo_view/photo_view.dart';
    
    class HeroPage extends StatefulWidget {
      final Map arguments;
      const HeroPage({super.key, required this.arguments});
    
      
      State<HeroPage> createState() => _HeroPageState();
    }
    
    class _HeroPageState extends State<HeroPage> {
      
      Widget build(BuildContext context) {
        return GestureDetector(
          onTap: () {
            Navigator.pop(context);
          },
          child: Hero(
            tag: widget.arguments['imageUrl'],
            child: Scaffold(
              //加Scaffold是为了点击屏幕任意位置都可以返回
              backgroundColor: Colors.black,
              body: Center(
                child: AspectRatio(
                    aspectRatio: 16 / 9,
                    child: PhotoView(
                      imageProvider: NetworkImage(widget.arguments['imageUrl']),
                    )),
              ),
            ),
          ),
        );
      }
    }
    

photo_view预览多张图片

  1. 配置依赖

    dependencies:
      photo_view: ^0.15.0
    
  2. 引入

    import 'package:photo_view/photo_view_gallery.dart';
    
  3. 多张图片的预览

    改造 listData,加个属性:

    List listData = [
      {
        "id": 0,
        "title": 'Candy Shop',
        "author": 'Mohamed Chahin',
        "imageUrl": 'https://www.itying.com/images/flutter/1.png',
      },
      {
        "id": 1,
        "title": 'Childhood in a picture',
        "author": 'Google',
        "imageUrl": 'https://www.itying.com/images/flutter/2.png',
      },
      {
        "id": 2,
        "title": 'Alibaba Shop',
        "author": 'Alibaba',
        "imageUrl": 'https://www.itying.com/images/flutter/3.png',
      },
      {
        "id": 3,
        "title": 'Candy Shop',
        "author": 'Mohamed Chahin',
        "imageUrl": 'https://www.itying.com/images/flutter/4.png',
      },
      {
        "id": 4,
        "title": 'Tornado',
        "author": 'Mohamed Chahin',
        "imageUrl": 'https://www.itying.com/images/flutter/5.png',
      },
      {
        "id": 5,
        "title": 'Undo',
        "author": 'Mohamed Chahin',
        "imageUrl": 'https://www.itying.com/images/flutter/6.png',
      },
      {
        "id": 6,
        "title": 'white-dragon',
        "author": 'Mohamed Chahin',
        "imageUrl": 'https://www.itying.com/images/flutter/7.png',
      }
    ];
    

    home.dart 中需要传入 hero.dart 需要的参数:

    在这里插入图片描述
    hero.dart

    import 'package:flutter/material.dart';
    import 'package:photo_view/photo_view_gallery.dart';
    
    class HeroPage extends StatefulWidget {
      final Map arguments;
      const HeroPage({super.key, required this.arguments});
    
      
      State<HeroPage> createState() => _HeroPageState();
    }
    
    class _HeroPageState extends State<HeroPage> {
      late List listData = [];
      late int initialPage;
    
      
      void initState() {
        super.initState();
        listData = widget.arguments['listData'];
        initialPage = widget.arguments['initialPage'];
      }
    
      
      Widget build(BuildContext context) {
        return GestureDetector(
          onTap: () {
            Navigator.pop(context);
          },
          child: Hero(
            tag: widget.arguments['imageUrl'],
            child: Scaffold(
              //加Scaffold是为了点击屏幕任意位置都可以返回
              backgroundColor: Colors.black,
              body: Center(
                child: PhotoViewGallery.builder(
                  itemCount: listData.length,
                  pageController:
                      PageController(initialPage: initialPage), //点击后显示点击的图片
                  builder: ((context, index) {
                    return PhotoViewGalleryPageOptions(
                        imageProvider: NetworkImage(listData[index]["imageUrl"]));
                  }),
                ),
              ),
            ),
          ),
        );
      }
    }
    

    可以实现点击哪张图片就预览哪张图片,同时可以左右滑动切换图片。

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

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

相关文章

北京大学第一医院与智源研究院共同发布基于可信执行环境的AI医学影像挑战赛

肾动脉狭窄是导致继发性高血压及肾功能不全的常见原因&#xff0c;而目前针对肾动脉狭窄功能学的评估尚处于探索阶段。数据保护和可信计算环境是目前人工智能技术应用于临床研究的一大瓶颈。北京大学第一医院与北京智源人工智能研究院心脏AI 联合研究中心特发布基于可信执行环境…

wps表格样式【笔记】

wps表格样式【笔记】 前言版权推荐wps表格样式第一种方法第二种方法 最后 前言 2024-5-15 19:25:47 以下内容源自《【笔记】》 仅供学习交流使用 版权 禁止其他平台发布时删除以下此话 本文首次发布于CSDN平台 作者是CSDN日星月云 博客主页是https://jsss-1.blog.csdn.net …

【第五节】C++的多态性与虚函数

目录 前言 一、子类型 二、静态联编和动态联编 三、虚函数 四、纯虚函数和抽象类 五、虚析构函数 六、重载&#xff0c;重定义与重写的异同 前言 面向对象程序设计语言的三大核心特性是封装性、继承性和多态性。封装性奠定了基础&#xff0c;继承性是实现代码重用和扩展…

JWT身份验证相关安全问题

前言&#xff1a;工作中需要基于框架开发一个贴近实际的应用&#xff0c;找到一款比较合适的cms框架&#xff0c;其中正好用到的就是jwt做身份信息验证&#xff0c;也记录一下学习jwt相关的安全问题过程。 JWT介绍 Json web token (JWT), 是为了在网络应用环境间传递声明而执行…

如何遍历并处理不平衡的Python数据集

目录 一、引言 二、不平衡数据集的概念与影响 三、处理不平衡数据集的策略 重采样策略 集成学习方法 代价敏感学习 一分类方法 四、Python工具与库 五、案例分析与代码实现 案例一&#xff1a;使用imbalanced-learn库进行上采样 案例二&#xff1a;使用scikit-learn…

知识付费小程序源码系统 界面支持万能DIY装修,一站式运营 附带完整的源代码以及搭建教程

系统概述 这是一款功能强大的知识付费小程序源码系统&#xff0c;它为用户提供了一个全面的平台&#xff0c;能够满足各种知识付费场景的需求。其界面支持万能 DIY 装修&#xff0c;让用户可以根据自己的品牌形象和风格进行个性化定制&#xff0c;打造出独具特色的小程序界面。…

台灯护眼是真的吗?台灯怎么选对眼睛好?看这一篇就够了

随着现代生活方式的改变&#xff0c;孩子们面临着越来越多的视力挑战。我们一直使用普通台灯&#xff0c;往往忽略了不合适的台灯也会给孩子眼部健康带来危害。普通台灯&#xff0c;尤其是使用白炽灯或荧光灯作为光源的台灯&#xff0c;会发射出紫外线。这些紫外线辐射对孩子的…

HTML新春烟花盛宴

目录 写在前面 烟花盛宴 完整代码 修改文字

内存卡频频提示格式化?数据恢复全攻略

内存卡提示需要格式化 在数字时代&#xff0c;内存卡作为我们存储数据的常用设备&#xff0c;广泛应用于手机、相机、无人机等多种设备中。然而&#xff0c;不少用户在使用过程中会突然遭遇一个令人头疼的问题——内存卡提示需要格式化。这一提示往往伴随着数据的丢失风险&…

端午节趣味互动小游戏的作用是什么

端午节吃粽子&#xff0c;多数行业商家都可借势进行品牌营销&#xff0c;而一场营销效果的优劣&#xff0c;除了好方案外&#xff0c;还需要好的工具/渠道及运营等&#xff0c;围绕粽子元素的互动小游戏是营销互动的主要形式之一。 运用【雨科】平台拥有多款端午节粽子主题互动…

STM32-10-定时器

STM32-01-认识单片机 STM32-02-基础知识 STM32-03-HAL库 STM32-04-时钟树 STM32-05-SYSTEM文件夹 STM32-06-GPIO STM32-07-外部中断 STM32-08-串口 STM32-09-IWDG和WWDG 文章目录 一、STM32 基础定时器1. 基本定时器简介2. 基本定时器框图3. 基本定时器相关寄存器4. 定时器溢出…

单链表,双向链表,循环链表

文章目录 链表单链表双向链表循环链表链表的底层结构链表的实现代码 链表 链表分为单链表&#xff0c;双向链表&#xff0c;循环链表。 单链表 如上图所示&#xff0c;链表是由多个节点组成&#xff0c;节点由数据域与指针域组成&#xff0c;数据域用于存储数据&#xff0c;指…

服务器主机托管一站式托管服务有哪些?

服务器主机托管一站式托管服务&#xff0c;作为现代企业信息化建设的重要一环&#xff0c;为企业提供了一种高效、安全、可靠的服务器运行环境。下面&#xff0c;我们将从多个方面详细介绍这一服务的内容。 一、硬件与基础设施 服务器主机托管服务首先涵盖了服务器硬件和网络基…

windows环境redis未授权利用手法总结

Redis未授权产生原因 1.redis绑定在0.0.0.0:6379默认端口&#xff0c;直接暴露在公网&#xff0c;无防火墙进行来源信任防护。 2.没有设置密码认证&#xff0c;可以免密远程登录redis服务 漏洞危害 1.信息泄露&#xff0c;攻击者可以恶意执行flushall清空数据 2.可以通过ev…

前端Vue自定义个性化导航栏菜单组件的设计与实现

摘要&#xff1a; 随着前端技术的飞速发展和业务场景的日益复杂&#xff0c;组件化开发已成为提升开发效率和降低维护成本的关键手段。本文将以Vue uni-app平台为例&#xff0c;介绍如何通过自定义导航栏菜单组件&#xff0c;实现业务逻辑与界面展示的解耦&#xff0c;以及如何…

25 使用MapReduce编程了解垃圾分类情况

测试数据中1表示可回收垃圾&#xff0c;2表示有害垃圾&#xff0c;4表示湿垃圾&#xff0c;8表示干垃圾。 统计数据中各类型垃圾的数量&#xff0c;分别存储可回收垃圾、有害垃圾、湿垃圾和干垃圾的统计结果。 &#xff08;存储到4个不同文件中&#xff0c;垃圾信息&#xff0…

高效记录收支明细,预设类别账户,智能统计财务脉络,轻松掌握个人财务!

收支明细管理是每位个人或企业都必须面对的财务任务&#xff0c;财务管理已经成为我们生活中不可或缺的一部分。如何高效记录收支明细&#xff0c;预设类别账户&#xff0c;智能统计财务脉络&#xff0c;轻松掌握个人财务&#xff1f;晨曦记账本为您提供了完美的解决方案&#…

JVM的垃圾回收机制--GC

垃圾回收机制&#xff0c;是java提供的对于内存自动回收的机制。java不需要像C/C那样手动free()释放内存空间&#xff0c;而是在JVM中封装好了。垃圾回收机制&#xff0c;不是java独创的&#xff0c;现在应该是主流编程语言的标配。GC需要消耗额外的系统资源&#xff0c;而且存…

“2024深圳数字能源展”共同探讨数字能源未来发展方向和挑战

在数字化浪潮的推动下&#xff0c;新一轮科技革命与产业革命正以前所未有的速度加速兴起。在这个时代背景下&#xff0c;数字化技术与能源行业的高度融合&#xff0c;使得能源数字化成为未来发展的必然趋势。数字经济浪潮的蓬勃兴起&#xff0c;为能源行业的数字化转型提供了强…

网络安全-钓鱼篇-利用cs进行钓鱼

一、环境 自行搭建&#xff0c;kill&#xff0c;Windows10&#xff0c;cs 二、原理 如图所示 三、钓鱼演示 首先第一步&#xff1a;打开System Profiler-分析器功能 选择克隆www.baidu.com页面做钓鱼 之后我们通过包装域名&#xff0c;各种手段让攻击对象访问&#xff1a;h…