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

Flutter vs 前端 杂谈:SliverAppBar、手动实现Appbar、前端Html+JS怎么实现滚动变化型Appbar - 比较

Flutter vs 前端 杂谈
SliverAppBar的弹性背景的显隐效果使用Html+JS怎么实现

作者李俊才 (jcLee95):https://blog.csdn.net/qq_28550263
邮箱 :291148484@163.com
本文地址:https://blog.csdn.net/qq_28550263/article/details/134149018



1. 一些AppBar效果

Flutter 中,最简单的 appbar 就是 Appbar 组件,它没有任何难点,任何刚刚入门的开发着在 Flutter 脚手架创建的计数器应用中就使用了它。但是现实的开发场景中,Appbar 组件往往难以适应复杂的需求场景。

比如以下是 “王者营地” APP (即王者荣耀官方的社区应用) 的 Appbar,这个据说也是 Flutter 实现的:
在这里插入图片描述
这种向下滚动时,AppBar出现,向上滚到顶AppBar逐渐隐藏的效果还是比较简单,可以直接使用SliverAppBar。

与之相比,下面这个高德地图滚动方向与王者营地是相反的,并且还带有一个相遇于下面内容部分似乎在向下跑的图片:
在这里插入图片描述

这些效果当然不是使用 Appbar 组件做的。

在 Flutter 中,最简单的随着滚动带有显影效果的appbar可以使用 SliverAppBar 组件实现。

但是实际上appbar仅仅是一个应用顶部导航的效果不仅仅局限于 Flutter 原生的 AppbarSliverAppBar 。实际上,为了实现更加灵活的 appbar,还可以考虑基于 Sliver 协议 实现外观类似的组件,将它放在页面的顶部,着很好理解,因为在 写 Web 的时候就可以这样干(事实上我就是这样干过)。因此先从一个类似的 Web 中手写的例子看起。

2. 一个Web移动端上的复杂AppBar例子

先看效果吧(其实就是模仿上面的高德地图的大概效果):
在这里插入图片描述

(附:感谢图片来源地址,我在网络随便拿的,仅仅用于此示例,祝愿贵App、贵店铺生意红火。)

这个Appbar以及相关其它动画效果,本质上都是与滚动相关的。总结起来,我们要实现的效果如下:

  1. 页面上方有一个固定的Appbar,背景颜色为蓝色,内部包含一个输入框;

  2. 页面的上半部分有一个背景图像,通过#bg-item元素实现,并且这个元素在最下层;

  3. 页面的下半部分分为两部分:

    • #scroll-item:一个滚动元素,包含一张图片,它会随着页面的滚动而滚动,但在背景元素之上。
    • #content:一个内容区域,包含一个标题,它也会随着页面的滚动而滚动,但在滚动元素之上。
  4. 使用JavaScript监听页面的滚动事件,根据滚动距离动态改变以下效果:

    • Appbar的背景颜色透明度,使其在页面滚动时逐渐变为透明。
    • Appbar内文字的颜色透明度,同样逐渐变为透明。
    • Appbar内输入框的透明度,使其在页面滚动时逐渐变为透明。
    • 滚动元素的位置,随着页面滚动而向上移动,实现视差效果。
    • 内容区域的位置,随着页面滚动而向上移动,也实现视差效果。
  5. 使用CSS的变量--my-height定义了滚动元素的初始高度,以便在JavaScript中使用。

Web 中,要实现总体思路是通过 JavaScript 监听页面滚动事件,根据滚动距离动态改变页面元素的样式,从而实现Appbar背景颜色和文字颜色的渐变效果,以及滚动元素和内容区域的视差滚动效果。这种交互设计可以提升页面的视觉吸引力和用户体验。

Web代码如下:

<!DOCTYPE html>
<html>
<head><!-- 作者信息 --><!-- Author: 李俊才 --><!-- Email: 291149494@163.com --><!-- 许可证信息 --><!-- LICENSE: MIT --><style>body {margin: 0;padding: 0;--my-height: 460px;  // 定义一个CSS变量,表示滚动元素的初始高度}#appbar {position: fixed;top: 0;width: 100%;height: 50px;background: rgba(0, 123, 255, 1);color:white;font-size: large;transition: background 0.3s;display: flex;align-items: center;justify-content: space-between;padding: 0 10px;padding-right: 20px;z-index: 3;  // 设置appbar在最上层}#appbar-input {padding: 5px;border-radius: 5px;border: 1px solid white;margin-right: 20px;}#appbar-input::placeholder {color: white;}#bg-item {position: fixed;top: 0;width: 100%;height: var(--my-height);z-index: 0;  // 设置背景元素在最下层}#bg-item img {width: 100%;height: auto;object-fit: cover;}#scroll-item {position: absolute;top: var(--my-height);width: 100%;z-index: 1;  // 设置滚动元素在背景元素之上}#scroll-item img {width: 100%;height: auto;object-fit: cover;}#content {position: absolute;top: var(--my-height);height: 610px;width: 100%;background-color: #ececec;z-index: 2;  // 设置内容元素在滚动元素之上}</style>
</head>

从CSS部分就可以看出,实际上归纳起来,我把页面拆分为了 appbar、背景图层、滚动图层、内容层,通过 z-index 属性来控制层级关系(可以结合下面html部分)。代码接上:

    <!-- 作者信息 --><!-- Author: 李俊才 --><!-- Email: 291149494@163.com --><!-- 许可证信息 --><!-- LICENSE: MIT -->
<body><div id="appbar"><div>我是appbar</div><input id="appbar-input" type="text" placeholder="我是输入框"></div><div id="bg-item"><img src="https://gw.alicdn.com/imgextra/i4/2212013333132/O1CN01DetIjE1Z0VMx4155t_!!2212013333132.jpg_Q75.jpg_.webp" alt="Image"></div><div id="scroll-item"><img src="https://gitee.com/jacklee1995/example-pictures/raw/master/piano/jonathanvasquez8950_piano_795a8e31-a910-48aa-9eae-45b1602f7cba.png" alt="Image"/></div><div id="content"><h1>我是内容区域</h1></div><script>// 获取 appbar 以及appbar内的输入框元素节点const appbar = document.getElementById('appbar');const appbarInput = document.getElementById('appbar-input');// 获取滚动项节点,这是一个与内容节点差速滚动的元素const scrollItem = document.getElementById('scroll-item');// 获取内容节点const content = document.getElementById('content');// 定义页面滚动的最大距离,在这个距离内appbar的背景颜色和文字颜色会发生变化const maxScroll = 280;window.addEventListener("scroll", function() {let scrollTop = window.pageYOffset || document.documentElement.scrollTop;let opacity =  (scrollTop / maxScroll);opacity = opacity < 0 ? 0 : opacity;// 根据滚动距离动态改变appbar的背景颜色透明度appbar.style.background = `rgba(0, 123, 255, ${opacity})`;// 根据滚动距离动态改变appbar内文字的颜色透明度appbar.style.color = `rgba(255, 255, 255, ${opacity})`;appbarInput.style.opacity = `${opacity}`;// 根据滚动距离动态改变滚动项的位置scrollItem.style.top = `calc(var(--my-height) - ${scrollTop}px)`;// 根据滚动距离动态改变内容的位置content.style.top = `calc(var(--my-height) - ${scrollTop / 2}px)`;});</script>
</body>
</html>

所有的控制逻辑我在 scroll 监听中完成的,实际上就是对各个层的控制。

3. Flutter小试:我就不用SliverAppBar了

其实我的意思就是想自定义与滚动效果相关的appbar。既然需要滚动控制,而且使用 SliverAppBar 套参数也不是那么方便,即使这样的效果无非是控制一个盒子的透明度变化以及其它的位置移动。说来说去, SliverAppBar 也可以通过其它的组件实现,最后转为 Sliver 协议放入CustomScrollView不就可以了。

整体思路和 Web 中差不多,由于是分层,需要使用 StackPositioned 组件(相比于上一小节在Web中我们使用的是html+CSS的z-index,然后在 JS 代码中动态调整opacity)。

整体思路完全一样。于是,可以将上一个小节的 Web 代码 改用Flutter实现一下:

import 'package:flutter/material.dart';// Author: 李俊才
// Email: 291149494@163.com
// https://blog.csdn.net/qq_28550263/article/details/134149018class WebAppBarScaffold extends StatefulWidget {const WebAppBarScaffold({Key? key}) : super(key: key);State<WebAppBarScaffold> createState() => _WebAppBarScaffoldState();
}class _WebAppBarScaffoldState extends State<WebAppBarScaffold> {double _opacity = 0.0;double _offsetImage = 0.0;double _offsetContent = 0.0;Widget build(BuildContext context) {return Scaffold(body: NotificationListener<ScrollNotification>(onNotification: (ScrollNotification scrollInfo) {if (scrollInfo is ScrollUpdateNotification) {setState(() {_opacity = scrollInfo.metrics.pixels / 280;_opacity = _opacity.clamp(0.0, 1.0);_offsetImage = scrollInfo.metrics.pixels * 1.5; // 修改这里_offsetContent = scrollInfo.metrics.pixels / 2; // 修改这里});}return true;},child: Stack(children: <Widget>[Positioned(top: 0,child: Image.network('https://gw.alicdn.com/imgextra/i4/2212013333132/O1CN01DetIjE1Z0VMx4155t_!!2212013333132.jpg_Q75.jpg_.webp',width: MediaQuery.of(context).size.width,fit: BoxFit.cover,),),Positioned(top: 460 - _offsetImage,child: Image.network('https://gitee.com/jacklee1995/example-pictures/raw/master/piano/jonathanvasquez8950_piano_795a8e31-a910-48aa-9eae-45b1602f7cba.png',width: MediaQuery.of(context).size.width,fit: BoxFit.cover,),),Positioned(top: 460 - _offsetContent,child: Container(color: Colors.grey[200],width: MediaQuery.of(context).size.width,height: 610,child: const Center(child: Text('我是内容区域')),),),Positioned(top: 0,child: Container(width: MediaQuery.of(context).size.width,height: 50,color: Colors.blue.withOpacity(_opacity),child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: <Widget>[Padding(padding: const EdgeInsets.only(left: 10),child: Text('我是appbar',style: TextStyle(color: Colors.white.withOpacity(_opacity)),),),Padding(padding: const EdgeInsets.only(right: 20),child: Opacity(opacity: _opacity,child: const SizedBox(width: 200, // 限定宽度child: TextField(decoration: InputDecoration(hintText: '我是输入框',hintStyle: TextStyle(color: Colors.white),),),),),),],),),),ListView.builder(itemCount: 1,itemBuilder: (context, index) {return Container(height: MediaQuery.of(context).size.height * 2);},),],),),);}
}

在这里插入图片描述
这里其实有一个小缺陷,就是滚动过头我没去做处理了。这里是一点小数学问题,就是计算中间层的图片相对于内容层图片滚动的位移值恰好为图片的高度时,让中间滚动图片层和内容层一起滚动,就可以避免看到中间滚动图层相比于内容层越来越远。读者可以尝试修改一下代码。

4. 结论

其实本文主要目的还是比较。可以看到,使用Web事件监听处理滚动事件,其实和Flutter中使用滚动控制差不多。对于一些复杂的效果,没有必要拘束于现有的组件,可以基于一些更加基础的部件构成复杂的效果。

相关文章:

Flutter vs 前端 杂谈:SliverAppBar、手动实现Appbar、前端Html+JS怎么实现滚动变化型Appbar - 比较

Flutter vs 前端 杂谈 SliverAppBar的弹性背景的显隐效果使用HtmlJS怎么实现 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550…...

Qt 二维码生成与识别

1.简介 QZXing是一个基于Qt框架的二维码解码库&#xff0c;它是对ZXing&#xff08;Zebra Crossing&#xff09;开源项目的一个Qt封装。ZXing是一个功能强大的开源二维码解码库&#xff0c;支持多种类型的码&#xff0c;包括QR码、DataMatrix码、Aztec码等。 QZXing提供了一个…...

jacoco和sonar

目录 jacoco 引入依赖 构建配置修改 单元测试 生成报告 查看报告 报告说明 1. Instructions 2. Branches 3. Cyclomatic Complexity 4. Lines 5. Methods 6. Classes sonar7.7 基础环境 需要下载软件 解压文件并配置 运行启动 jacoco 引入依赖 <dep…...

Django系列之Serializer的source参数使用、自定义序列化方法

数据准备 models.py from django.contrib.auth.models import AbstractUser from django.db import modelsclass Publish(models.Model):name models.CharField(max_length32)city models.CharField(max_length8)email models.CharField(max_length32)def __str__(self):r…...

Java从入门到精通

Java从入门到精通 1. Java概述1.1 Java是什么1.2 为什么用Java1.3 Java能做什么1.4 Java技术体系平台2. Java快速入门2.1 Java开发环境的准备:JDK简介、安装、常用命令如何使用JavaJDK产品的发展史获取JDK如何验证能用javac和java其他常用命令行命令2.2 Java入门程序-HelloWor…...

电路布线问题动态规划详解(做题思路)

对于电路布线问题&#xff0c;想必学过动态规划的大家都很清除。今天就来讲解一下这个动态规划经典题目。 目录 问题描述输入分析最优子结构代码 问题描述 在一块电路板的上、下2端分别有n个接线柱。根据电路设计&#xff0c;要求用导 线(i,π(i))将上端接线柱与下端接线柱相…...

webpack 的 Loader 和 Plugin 的区别,常见的 loader 和 plugin 有哪些?

结论先行&#xff1a; 1、 Loader 和 Plugin 的区别 Loader 也叫做就是“加载器”&#xff0c;因为 webpack 原生只能解析 js 文件&#xff0c;而对于其他类型文件&#xff0c;则需要借助 loader。所以 loader 的作用就是实现对不同格式文件的解析和处理&#xff0c;例如把 E…...

云计算实战项目之---学之思在线考试系统

简介&#xff1a; 学之思开源考试系统是一款 java vue 的前后端分离的考试系统。主要优点是开发、部署简单快捷、界面设计友好、代码结构清晰。支持web端和微信小程序&#xff0c;能覆盖到pc机和手机等设备。 支持多种部署方式&#xff1a;集成部署、前后端分离部署、docker部…...

研究生学术与职业素养讲座MOOC---期末复习(1-15)

目录 单选题多选题填空题判断题 单选题 我国制造科学与技术与工业发达国家相比的阶段性差距不包括&#xff1a;人工成本高不属于面向产业的学科&#xff1a;哲学哪个国际前沿本讲未提&#xff1a;纳米技术早期的科学研究不分学科是以达芬奇为例说的待遇不是管理者与领导者的区…...

kube-prometheus-stack监控k8s1.24+ docker缺少图像

1.24 中 cAdvisor 指标中缺少图像、名称和容器标签 由于 Kubernetes 1.24 已经从 cadvisor 中删除了 docker 插件,因此虽然可以使用 cri-dockerd 来适配容器运行时,但 cadvisor 无法获取有关图像标签等 docker 容器信息。进而导致 grafana 很多图像无数据。解决方法为对 pro…...

【C/PTA——循环结构3】

C/PTA——循环结构3 7-1 二分法求多项式单根1.题目要求2.代码实现 7-2 循环-十进制转化1.题目要求2.代码实现 7-3 梅森数1.题目要求2.代码实现 7-4 单词长度1.题目要求2.代码实现 7-5 21循环-求和31.题目要求2.代码实现 7-6 21循环-金字塔1.题目要求2.代码实现 7-7 循环-杨辉三…...

MAC设备(M1)环境下编译安装openCV for Java

最近发现一个需求&#xff0c;可以用openCV来实现&#xff0c;碰巧又新买了mac笔记本&#xff0c;就打算利用业余时间安装下openCV。这里将主要步骤记录下&#xff0c;希望能帮助有需要的人。 1、准备编译环境 #查询编译opencv相关依赖 brew info opencv查询结果如下图所示&a…...

pytest中的pytest.ini

[pytest] filterwarnings ignore::DeprecationWarning addopts -v -s markers uat:1 smok:2 log_cli1 xfail_strict True filterwarnings ignore::DeprecationWarning 这个的功能就是 test_login.py::Test_login::test_login_correct_password PASSEDwarnings summary …...

C#通过TCP发送List<string>

using System; using System.IO; using System.Net.Sockets; using System.Text; using System.Collections.Generic;public static void SendList<string>(Stream stream, List<string> list) {// 将List<string>对象转换为字节数组byte[] data Encoding.U…...

Mactracker for mac(硬件信息查询工具)免费下载

想知道你电脑的信息吗&#xff1f;Mactracker Mac版是Macos上一款硬件信息查询工具&#xff0c;可以查询电脑中的硬件信息&#xff0c;还可以查看您使用软件的具体情况&#xff0c;苹果电脑产品和周边产品的信息&#xff0c;售价等等&#xff0c;让您对电脑有更多深刻的了解。 …...

MES管理系统中常规的生产建模有哪些

随着制造业的快速发展&#xff0c;MES生产管理系统已经成为了现代制造业不可或缺的核心系统。MES通过对生产过程进行建模&#xff0c;实现了生产过程的可视化、可控制和可优化&#xff0c;为企业提供了全方位的生产管理解决方案。本文将深化对MES管理系统及其主要生产模型的理解…...

电商API:淘宝京东拼多多1688多电商平台的商品销量库存信息获取

item_get 获得淘宝商品详情 获取APIkeyitem_get_pro 获得淘宝商品详情高级版item_review 获得淘宝商品评论item_fee 获得淘宝商品快递费用item_password 获得淘口令真实urlitem_list_updown 批量获得淘宝商品上下架时间seller_info 获得淘宝店铺详情item_search 按关键字搜索淘…...

EPLAN软件中的术语-主数据‘’技术分享

在EPLAN中&#xff0c;主数据(Master Data)这个词被经常、反复地提及&#xff0c;我曾经困惑了很长时间&#xff0c;不得要领。在EPLAN的帮助系统中&#xff0c;它列举了一部分内容&#xff0c;说这些这些就是主数据&#xff0c;但没有解释什么是主数据&#xff0c;除了上面这些…...

web应用程序、Django框架的学习

web应用程序 什么是web? Web应用程序是一种可以通过Web访问的应用程序,用户只需要有浏览器即可&#xff0c;不需要再安装其他软件 案例&#xff1a; 淘宝网、京东网、博客园、等都是基于web应用的程序 应用程序有两种模式C/S、B/S。C/S是客户端/服务器端程序&#xff0c…...

【c++之设计模式】组合使用:抽象工厂模式与单例模式

简介 学以致用&#xff0c;使用抽象工厂及单例模式创建不同轿车及轿车装饰品。 代码 定义一个抽象工厂类来创建不同类型的轿车和轿车装饰品。抽象工厂类中具有创建不同类型轿车和轿车装饰品的纯虚方法。 abstractFactory.h #pragma once#include "Car.h" #inclu…...

Adobe Photoshop Elements 2024 v24.0 简体中文版 | 中文直装版

下载&#xff1a; http://dt1.8tupian.net/2/29913a53b500.pg3介绍&#xff1a;Photoshop Elements 2024(简称PSE即PS简化版)是一款定位在数码摄影领域的全新的图像处理软件&#xff0c;该软件包括了专业版的大多数特性&#xff0c;只有少量的简化选项&#xff0c;提供了调整颜…...

seata事务回滚引起的skywalking数据库存储空间剧增的问题排查

基本信息 产品名称&#xff1a;ATS3.0 问题分类&#xff1a;编码问题 环境类型&#xff1a;环境无关 问题现象 11月1日上午华润DBA收到数据库磁盘空间告警&#xff0c;检查后发现skywalking连接的mysql数据库占用空间从之前一直是比较稳定的&#xff0c;但是10月31日…...

数据库SQL

数据库&SQL 数据库基本概念数据库DataBase定义 数据库管理系统(DBMS)定义在JAVA项目中与数据库的结合数据库管理系统中常见的概念库与表的关系 SQL数据类型数字类型浮点类型字符类型TEXT类型日期类型 SQL语言的分类DDL:数据定义语言修改表结构的注意事项 DML:数据操作语言D…...

C语言实现给一个不多于5位的正整数,要求:一、求它是几位数,二、逆序打印出各位数字。

完整代码&#xff1a; // 给一个不多于5位的正整数&#xff0c;要求&#xff1a;一、求它是几位数&#xff0c;二、逆序打印出各位数字。 #include<stdio.h>int main(){int num;int len0;printf("请输入一个不多于5位的正整数:");scanf("%d",&n…...

101 对称二叉树

原题链接&#xff1a;101 对称二叉树 全代码&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : va…...

安全测试,接口返回内容遍历~

最近公司被人大量爬取数据&#xff0c;查了一下发现&#xff0c;用户主页接口&#xff0c;没有加用户登录校验&#xff0c;返回了用户的敏感信息有手机号和邮箱&#xff0c;其实这个接口是用不到这些信息的。再加上用户id是自增长的&#xff0c;所以很容易被别人爬取。 既然这…...

【GIS】地理坐标系与投影坐标系的区别

在地理信息系统中&#xff0c;坐标系的选择和使用是至关重要的。我们通常使用的坐标系有两种&#xff1a;地理坐标系和投影坐标系。本文将详细介绍这两种坐标系的概念、区别、转换方式以及常见投影。 一、定义 地理坐标系&#xff08;Geographic Coordinate System&#xff09…...

太细了:美团一面连环夺命20问,搞定就60W起

说在前面 在40岁老架构师尼恩的&#xff08;50&#xff09;读者社群中&#xff0c;经常有小伙伴&#xff0c;需要面试美团、京东、阿里、 百度、头条等大厂。 下面是一个小伙伴成功拿到通过了美团一面面试&#xff0c;现在把面试真题和参考答案收入咱们的宝典。 通过美团一面…...

休眠和睡眠有哪些区别?如何让电脑一键休眠?

电脑中有休眠和睡眠&#xff0c;那么它们有什么区别呢&#xff1f;下面我们就通过本文来了解一下。 休眠和睡眠的区别 电脑在睡眠状态时&#xff0c;会切断内存之外的设备电源&#xff0c;电脑会进入睡眠状态&#xff0c;当再次唤醒电脑后&#xff0c;不会影响睡眠前保存好的工…...

Kibana使用Timelion根据时间序列展示数据

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…...