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

本文主要是介绍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 - 比较的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/343797

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

AI绘图怎么变现?想做点副业的小白必看!

在科技飞速发展的今天,AI绘图作为一种新兴技术,不仅改变了艺术创作的方式,也为创作者提供了多种变现途径。本文将详细探讨几种常见的AI绘图变现方式,帮助创作者更好地利用这一技术实现经济收益。 更多实操教程和AI绘画工具,可以扫描下方,免费获取 定制服务:个性化的创意商机 个性化定制 AI绘图技术能够根据用户需求生成个性化的头像、壁纸、插画等作品。例如,姓氏头像在电商平台上非常受欢迎,

百度/小米/滴滴/京东,中台架构比较

小米中台建设实践 01 小米的三大中台建设:业务+数据+技术 业务中台--从业务说起 在中台建设中,需要规范化的服务接口、一致整合化的数据、容器化的技术组件以及弹性的基础设施。并结合业务情况,判定是否真的需要中台。 小米参考了业界优秀的案例包括移动中台、数据中台、业务中台、技术中台等,再结合其业务发展历程及业务现状,整理了中台架构的核心方法论,一是企业如何共享服务,二是如何为业务提供便利。

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C