为自己的项目媒体资源添加固定高度
为自己的项目媒体资源添加固定高度
未媒体资源添加固定高度,不仅有利于确定懒加载后的切确位置,还可以做骨架屏、loading动画等等,但是因为历史数据中很多没有加高度的媒体资源,所以一直嫌麻烦没有做。
直到这个季度有一个自上而下(不可抗力)的push。一个需求需要在懒加载的情况下跳转到底部的一个坐标。
一开始我们拟定的方案是中途查询,边查询边修改目标高度,但是这样做无法避免有些很大的图片加载慢的情况,跳转到正确位置后整整1~2秒才加载出来,这时候我们已经跳转到目标地在那里正常浏览了,页面突然被顶下去的效果是我们无法接受的。(尤其是在移动端真机测试上表现得更加明显)。
于是不得已之下必须还是得选择固定高度的方案,翻找了一下网上的建议,最后找到了一个比较快捷的方式如下,只需要设定好每个媒体资源的宽高比例,以及宽度,即可自动设定好高度。
根据padding-bottom
配置比例。
图片和视频资源都需要配置固定高度,以前一直以为视频是有高度的,但是在精确测试后发现视频未加载时候的高度和它加载后的高度不匹配。
把懒加载组件和中途查询函数的代码列如下方
图片固定高度组件
需注意:因为固定高度的span包裹在lazyload里面,所以它仍然会用户下滑到某个距离才显示出内部内容 以及 高度,但是span \ padding-bottom的加载速度极快,比媒体资源快很多,所以可以达到下滑时看到固定高度的效果。
但是要达到我上面的需求:锚点定位跳转,可能还是会有定位不准的情况,因此我采用两种方式相结合,也就是中途查询+固定高度。
import React, { useEffect } from 'react';
import LazyLoad from 'react-lazyload';
import ossImgCompress from '@/utils/ossImgCompress';
import styles from './index.module.less';/*** @param {string} className* @param {Array} ratio [长,宽]图片比例,设置比例后必须设定懒加载组件className或者outerStyle中的宽度。* @param {Object} outerStyle* @returns*/
const LazyLoadImg = ({ children, ...props }) => {let {src,offset = 400,ratio,className,coverClassName,outerStyle = {},style = { width: '100%' },onClick,webp,type = 'img',key,...restProps} = props;src = webp ? ossImgCompress(src, { webp }) : src;const hasRatio = Array.isArray(ratio) && type !== 'cover';return (<LazyLoad offset={offset} className={[styles.lazyimg, className].join(' ')} style={outerStyle}>{hasRatio && <span className={styles.ratioSpan} style={{ paddingBottom: `${(ratio[1] / ratio[0]) * 100}%` }} />}{type === 'img' && <img {...restProps} src={src} style={style} onClick={onClick} alt='' />}{type === 'cover' && (<div{...restProps}className={coverClassName ?? styles.cover}style={{ backgroundImage: `url(${src})`, ...style }}onClick={onClick}>{children}</div>)}</LazyLoad>);
};
export default LazyLoadImg;
// css.cover {width: 100%;height: 100%;background-size: cover;background-position: center;background-repeat: no-repeat;
}.lazyimg {position: relative;font-size: 0;line-height: 0;overflow: hidden;.ratioSpan {position: unset !important;display: inline-block;box-sizing: border-box;width: initial;height: initial;background: none;opacity: 0;border: 0px !important;margin: 0px !important;& + img {border-radius: inherit;position: absolute;inset: 0px;box-sizing: border-box;padding: 0px;border: none;margin: auto;display: block;width: 0px;height: 0px;min-width: 100%;max-width: 100%;min-height: 100%;max-height: 100%;}}
}
视频固定高度组件
视频的懒加载函数既是将data-src的内容放到src里,这个函数在其他文章《如何优化一个很多视频的网页》中给出了。
video的固定高度放在了lazyload组件上,所以高度会一直存在,基本不存在图片固定高度组件中 滑动一定距离才加载出内部元素 & 高度的情况。
import React from 'react';
import LazyLoad from 'react-lazyload';
import styles from './index.module.less';/*** 存在两种懒加载方案、可以自动设置高度的video组件* @param {Object} style video元素的style* @param {Object} outerStyle video元素父级组件的style* @param src 采用LazyLoad 懒加载组件加载* @param poster 采用LazyLoad 懒加载组件加载* @param data_src 不采用懒加载组件(否则获取不到video元素),配合VideoLazyLoad使用* @param data_poster 不采用懒加载组件,配合VideoLazyLoad使用* @param offset* @param {Array} ratio 视频宽高比例,设置后需要设定父级className的宽度* @param className* @param autoPlay* @param onClick* @param {object} videoProps* @returns*/
const LazyLoadVideo = ({ children, ...props }) => {let {src,poster,data_src,data_poster,offset = 400,ratio,className,autoPlay = true,onClick,videoProps,outerStyle = {},style = { width: '100%' },key,} = props;return data_src ? (<div key={key} className={[styles.lazyVideo1, className].join(' ')} style={outerStyle}><spanclassName={styles.ratioSpan}style={{ paddingBottom: Array.isArray(ratio) && `${(ratio[1] / ratio[0]) * 100}%` }}/><videodata-src={data_src}data-poster={data_poster || poster}poster={poster}src={src}style={style}disablePictureInPictureautoPlay={autoPlay}loopmutedplaysInlinecontrols={false}onClick={onClick}{...videoProps}/></div>) : (<LazyLoadkey={key}offset={offset}className={[styles.lazyVideo, className].join(' ')}style={{ ...outerStyle, paddingBottom: Array.isArray(ratio) ? `${(ratio[1] / ratio[0]) * 100}%` : 'auto' }}><videosrc={src}style={style}poster={poster}disablePictureInPictureautoPlay={autoPlay}loopmutedplaysInlinecontrols={false}onClick={onClick}{...videoProps}/></LazyLoad>);
};
export default LazyLoadVideo;
// css
.lazyVideo {position: relative;width: 100%;height: 0;overflow: hidden;display: inline-block;box-sizing: border-box;background: none;border: 0px;margin: 0px;font-size: 0;line-height: 0;video {object-fit: fill;position: absolute;inset: 0px;box-sizing: border-box;padding: 0px;border: none;margin: 0 auto;display: block;width: 100%;height: 100%;font-size: 0;line-height: 0;border-radius: inherit;}
}.lazyVideo1 {position: relative;font-size: 0;line-height: 0;.ratioSpan {width: 100%;inset: 0px;height: 0;overflow: hidden;display: inline-block;box-sizing: border-box;background: none;border: 0px;margin: 0px;font-size: 0;line-height: 0;}video {object-fit: fill;position: absolute;inset: 0px;box-sizing: border-box;padding: 0px;border: none;margin: 0 auto;display: block;width: 100%;height: 100%;border-radius: inherit;}
}
中途查询修改目标高度的函数
其实JQUERY似乎是有一个$().animation()函数已经直接实现了这个功能,但是因为我的项目没有用到,所以就只能自己实现一下了。
const targetRef = useRef(null);
const menuHeader = useRef(null);
const timer = useRef(null);
const max_call = 10;
let max_call_count = 0;
const [res, setRes] = useState([]);<button onClick={handleScrollToTarget}>跳转</button>const scrollToElement = async (lastScrollTop, lastWindowScrollY, lastElementTop) => {// 安卓手机端兼容性const windowScrollY = document.documentElement.scrollTop || document.body.scrollTop;const nowElementTop = targetRef.current.offsetTop;clearTimeout(timer.current);timer.current = null;const margin = isMobile ? (menuHeader.current ? menuHeader.current.clientHeight : 80) : 50;const target = nowElementTop - margin;const step1 = nowElementTop / 3;const step2 = nowElementTop * 0.75;let scrollTop = 0; // 记录本次指定的高度,避免反复赋值造成卡顿// 分阶段赋予高度,避免过快跳转导致中间有高度变化查询不到if (windowScrollY < step1 - 300) {scrollTop = step1;}if (windowScrollY >= step1 - 300 && windowScrollY < step2 - 300) {scrollTop = step2;}if (windowScrollY >= step2 - 300) {scrollTop = target;}if (isReachBottom(10)) {max_call_count = 0;return window.scrollTo(0, targetRef.current.offsetTop);}if (targetRef.current.getBoundingClientRect().top.toFixed(0) > margin) {// 判断当前高度 避免反复赋值造成卡顿if (windowScrollY >= lastScrollTop - 300 || nowElementTop.toFixed(0) !== lastElementTop.toFixed(0)) {window.scrollTo({top: scrollTop,left: 0,behavior: 'instant',});}// 每100ms更新一次if (max_call_count < max_call) {if (lastWindowScrollY === windowScrollY) max_call_count += 1;timer.current = setTimeout(() => {scrollToElement(scrollTop, windowScrollY, nowElementTop);}, 90);}}};// 避免懒加载一直加载导致屏幕滚动失败,将路程分为4段,每隔一段查询一次目标高度,直到滚动到目标位置const handleScrollToTarget = async () => {try {// 查询目标let firstScrollTop = 0;if (!targetRef.current) {const t = await querySelector('#target').then((ele) => {targetRef.current = ele;return ele;});if (!t) return;firstScrollTop = t.offsetTop;} else {firstScrollTop = targetRef.current.offsetTop;}// 查询documentElement & 错误捕获const documentElement =document.documentElement ||(await new Promise((resolve, reject) => {const interval = setInterval(() => {if (max_call_count < max_call) {if (!!document.documentElement) {max_call_count = 0;clearInterval(interval);resolve(document.documentElement);} else {max_call_count++;}} else {clearInterval(interval);max_call_count = 0;resolve(null);}}, 100);}));if (documentElement || document.documentElement) {window.scrollTo(0, firstScrollTop);scrollToElement(firstScrollTop / 2, 0, firstScrollTop);} else {throw Error('无法获取document.documentElement');}} catch (e) {console.error('滚动函数失败——', e);// 兜底函数,直接滚动}};/*** 页面触底判断* @param margin 触底函数判断范围*/
function isReachBottom(margin = 36) {// 窗口高度var windowHeight = document.documentElement.clientHeight || document.body.clientHeight;// 滚动高度var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;// 页面高度var documentHeight = document.documentElement.scrollHeight || document.body.scrollHeight;if (windowHeight + scrollTop + margin > documentHeight) {return true;} else {return false;}
}
相关文章:
为自己的项目媒体资源添加固定高度
为自己的项目媒体资源添加固定高度 未媒体资源添加固定高度,不仅有利于确定懒加载后的切确位置,还可以做骨架屏、loading动画等等,但是因为历史数据中很多没有加高度的媒体资源,所以一直嫌麻烦没有做。 直到这个季度有一个自上而…...
家政小程序系统源码开发:引领智能生活新篇章
随着科技的飞速发展,小程序作为一种便捷的应用形态,已经深入到我们生活的方方面面。尤其在家庭服务领域,家政小程序的出现为人们带来了前所未有的便利。它不仅简化了家政服务的流程,提升了服务质量,还为家政服务行业注…...
多表查询
目录 统计出一张数据表中的数据量 查询 dept 表中的数据量 查询 emp 表中的数据量 实现 emp 与 dept 的多表查询 笛卡尔积 消除笛卡尔积 把数据表 emp 的别名定为 e,数据表 dept 的别名定为 d,然后在查询中分别使用 e 和 d 代替这两个表 Oracle从…...
PHP开发日志 ━━ 深入理解三元操作与一般条件语句的不同
概况 三元运算符的功能与“if…else”流程语句一致。 在一般情况下,三元操作替换if条件语句可以精简代码,并且更为直观,但是在下面的情况中使用三元操作将会返回警告。 借图: 案例 比如原代码: class classA{publ…...
多维时序 | Matlab实现RF-Adaboost随机森林结合Adaboost多变量时间序列预测
多维时序 | Matlab实现RF-Adaboost随机森林结合Adaboost多变量时间序列预测 目录 多维时序 | Matlab实现RF-Adaboost随机森林结合Adaboost多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现RF-Adaboost随机森林结合Adaboost多变量时间序列预…...
vue3-内置组件-Suspense
Suspense (实验性功能) <Suspense> 是一项实验性功能。它不一定会最终成为稳定功能,并且在稳定之前相关 API 也可能会发生变化。 <Suspense> 是一个内置组件,用来在组件树中协调对异步依赖的处理。它让我们可以在组件树上层等待下层的多个嵌…...
Rust入门:如何在windows + vscode中关闭程序codelldb.exe
在windows中用vscode单步调试rust程序的时候,发现无论是按下stop键,还是运行完程序,调试器codelldb.exe一直霸占着主程序不退出,如果此时对代码进行修改,后续就没法再编译调试了。 目前我也不知道要怎么处理这个事&am…...
git错误整理
remote: Support for password authentication was removed on August 13, 2021. 参考:这篇即可 GnuTLS recv error (-110): The TLS connection was non-properly terminated. 执行下面的指令: git config --global http.sslVerify false...
跟着cherno手搓游戏引擎【22】CameraController、Resize
前置: YOTO.h: #pragma once//用于YOTO APP#include "YOTO/Application.h" #include"YOTO/Layer.h" #include "YOTO/Log.h"#include"YOTO/Core/Timestep.h"#include"YOTO/Input.h" #include"YOTO/KeyCod…...
微信小程序(四十二)wechat-http拦截器
注释很详细,直接上代码 上一篇 新增内容: 1.wechat-http请求的封装 2.wechat-http请求的拦截器的用法演示 源码: utils/http.js import http from "wechat-http"//设置全局默认请求地址 http.baseURL "https://live-api.ith…...
tomcat部署zrlog
1.下载zrlog包,并添加到虚拟机中 1)进入/opt/apache-tomcat-8.5.90/webapps目录 cd /opt/apache-tomcat-8.5.90/webapps2)下载zrlog包 wget http://dl.zrlog.com/release/zrlog-1.7.1-baaecb9-release.war 3)重命名包 mv zrlog-1.7.1-baaecb9-release zrblog 2…...
Ubuntu Desktop 开机数字小键盘
Ubuntu Desktop 开机数字小键盘 1. 开机数字小键盘References 1. 开机数字小键盘 一般情况下,Ubuntu 开机后小键盘区是控制方向键而非数字键,每次开机后若用到数字键都需要按下 NumLock 键。 References [1] Yongqiang Cheng, https://yongqiang.blog…...
树莓派编程基础与硬件控制
1.编程语言 Python 是一种泛用型的编程语言,可以用于大量场景的程序开发中。根据基于谷歌搜 索指数的 PYPL(程序语言流行指数)统计,Python 是 2019 年 2 月全球范围内最为流行 的编程语言 相比传统的 C、Java 等编程语言&#x…...
autojs通过正则表达式获取带有数字的text内容
视频连接 视频连接 参考 参考 var ctextMatches(/\d/).findOne()console.log("当前金币"c.text()) // 获取当前金币UiSelector.textMatches(reg) reg {string} | {Regex} 要满足的正则表达式。 为当前选择器附加控件"text需要满足正则表达式reg"的条件。 …...
Android java基础_类的继承
一.Android Java基础_类的继承 先封装一个persion类,在persion的基础上定义Student类,并基础persion类。 子类能访问父类的成员函数。 class Person {private int age;public void setAge(int age) {if (age < 0 || age > 200)age 0;else {thi…...
nginx stream proxy 模块的ssl连接源码分析
目录 1. 源起2. 分析验证环境的配置3. 源码分析3.1 代理模块的请求入口点分析3.2 发起与上游服务器的连接3.3 连接回调3.4 TCP连接建立成功后为上下游数据透传做准备3.5 TCP连接的ssl上下文初始化3.6 ssl握手成功后的处理3.7 连接数据的收与发1. 源起 我一直来对ssl建立连接的过…...
C#面:Static Nested Class 和 Inner Class 有什么不同
这是两种不同的类嵌套方式。 Static Nested Class : 是一个静态嵌套类,它是在外部类中定义的一个静态类。它可以访问外部类的静态成员和方法,但不能直接访问外部类的非静态成员和方法。静态嵌套类可以独立于外部类实例化,即可以…...
LeetCode、208. 实现 Trie (前缀树)【中等,自定义数据结构】
文章目录 前言LeetCode、208. 实现 Trie (前缀树)【中等,自定义数据结构】题目链接与分类思路 资料获取 前言 博主介绍:✌目前全网粉丝2W,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技术领…...
java数据结构与算法刷题-----LeetCode151. 反转字符串中的单词
java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 解题思路 这道题,可以理解为,将字符串颠倒…...
《Java 简易速速上手小册》第8章:Java 性能优化(2024 最新版)
文章目录 8.1 性能评估工具 - 你的性能探测仪8.1.1 基础知识8.1.2 重点案例:使用 VisualVM 监控应用性能8.1.3 拓展案例 1:使用 JProfiler 分析内存泄漏8.1.4 拓展案例 2:使用 Gatling 进行 Web 应用压力测试 8.2 JVM 调优 - 魔法引擎的调校8…...
mysql全国省市县三级联动创表sql(一)
1. 建表sql CREATE TABLE province (id VARCHAR ( 32 ) PRIMARY KEY COMMENT 主键,code CHAR ( 6 ) NOT NULL COMMENT 省份编码,name VARCHAR ( 40 ) NOT NULL COMMENT 省份名称 ) COMMENT 省份信息表;CREATE TABLE city (id VARCHAR ( 32 ) PRIMARY KEY COMMENT 主键,code …...
go面试题--使用两个goroutine交替打印数字与字母
使用两个goroutine交替打印数字与字母 题目如下: 使用两个goroutine交替打印序列,一个goroutine打印数字,另外一个goroutine打印字母,最终效果如下: 12AB34CD56EF78GH910IZ1112KL1314MN1516OP1718QR1920ST2122UV2324W…...
DolphinScheduler-3.2.0 集群搭建
目录 一、基础环境准备 1.1 组件下载地址 1.2 前置准备工作 二、 DolphinScheduler集群部署 2.1 解压安装包 2.2 配置数据库 2.3 准备 DolphinScheduler 启动环境 2.3.1 配置用户免密及权限 2.3.2 配置机器 SSH 免密登陆 2.3.3 启动 zookeeper集群 2.3.4 修改instal…...
07:Kubectl 命令详解|K8S资源对象管理|K8S集群管理(重难点)
Kubectl 命令详解|K8S资源对象管理|K8S集群管理 kubectl管理命令kubectl get 查询资源常用的排错命令kubectl run 创建容器 POD原理pod的生命周期 k8s资源对象管理资源文件使用资源文件管理对象Pod资源文件deploy资源文件 集群调度的规则扩容与缩减集群更…...
【设计模式】springboot3项目整合模板方法深入理解设计模式之模板方法(Template Method)
🎉🎉欢迎光临🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟特别推荐给大家我的最新专栏《Spring 狂野之旅:底层原理高级进阶》 🚀…...
Windows搭建docker+k8s
安装Docker Desktop 从官网下载,然后直接安装即可,过程很简单,一直Next就行。 有一点需要注意就是要看好对应的版本,因为后边涉及到版本的问题。 https://www.docker.com/products/docker-desktop 安装完成,双击图…...
年假作业10
一、选择题 BBDBACCCAD 二、填空题 1,4,13,40 3715 358 5 2 6 1 5 4 8 2 0 2 三、编程题 1、 #include <iostream> #include<array> #include <limits> using namespace std; int main() {array<int,10> score;array<int,10>::iterat…...
[ai笔记4] 将AI工具场景化,应用于生活和工作
欢迎来到文思源想的AI空间,这是技术老兵重学ai以及成长思考的第4篇分享内容! 转眼已经到了大年初三,但是拜年的任务还只完成了一半,准备的大部头的书,现在也就看了两本,还好AI笔记通过每天早起坚持了下来。…...
【生产实测可用】Redis修改集群弱口令
起因 漏扫redis连接发现弱口令需要修改 先连上去看看是空口令还是弱口令 redis-cli -p 6379 -h a.b.c.d info sentinel找到启动服务器的配置文件 cp -av /app/redis-7001/redis.conf /app/redis-7001/redis.conf.bak20240207 echo "requirepass 口令" >>/a…...
备战蓝桥杯---图论基础理论
图的存储: 1.邻接矩阵: 我们用map[i][j]表示i--->j的边权 2.用vector数组(在搜索专题的游戏一题中应用过) 3.用邻接表: 下面是用链表实现的基本功能的代码: #include<bits/stdc.h> using nam…...
新手如何自己做网站/发布软文的平台
点击Window-->Preferences 然后新建一个jsp文件就会发现默认编码已经修改成utf-8了 !!!...
许昌市建设信息网站/郑州网站推广培训
任务:应帅气的领导要求,需要监控生产环境mysql和mongo数据库服务。不仅要connect successful还要进行数据交互进一步确认数据库服务正常。思路:mysql和mongo 数据库ip、端口、用户名、密码、认证库(mongo)分别写在mysqldb_message.txt和mongo…...
怎么在手机上制作网站/seo入门到精通
列表 列表是python中最基本的数据结构之一,并且列表的数据项不需要具有相同的数据类型,创建一个列表,只需把逗号分隔的不同数据项使用方括号括起来即可。具体的定义式如下: list[变量1,变量2,变量3......] #变量可以是字符串也可以…...
阳谷做网站/app拉新一手渠道
题目源于百度深度学习平台算法工程师面试 NMS 概念 非极大值抑制(Non-Maximum Suppression, NMS),顾名思义就是抑制那些不是极大值的元素,可以理解为局部最大值搜索。对于目标检测来说,非极大值抑制的含义就是对于重叠度较高的一部分同类候选…...
设计网站都有什么/平台优化
扩展 Android Tab Layout,实现动画指示器效果,很漂亮。所有样式:IndicatorExampleCustom behaviorDachshundIndicatorPointMoveIndicatorsetInterpolator(TimeInterpolator interpolator)LineMoveIndicatorsetEdgeRadius(int edgeRadius)Poin…...
淘宝网网页版登录入口在哪里/东莞网站推广及优化
for、while、do while和switch暂时没发现与c的不同,这里只整理foreach。 foreach foreach的作用是遍历集合中的所有元素。foreach语句中的表达式由关键字in隔开的两个项组成,in左边的项是变量名,in右边的项是集合名。语法结构如下:…...