[{"content":"使用webp格式的图片 使用方式:将webp的图片作为背景图或者放在img中。 出现的问题:在ios中会出现帧图片重影的情况。\n使用拼接的序列帧长图 前提:设计提供每一帧拼接好的序列帧长图,以及动效的播放时长。假设提供的长图宽高为25500px * 850px, 播放时长为4s,屏幕宽度为750px,那么长图可以分为34帧图片。\n使用方式:\nhtml部分\n\u0026lt;div class=\u0026#34;animation-wrapper\u0026#34;\u0026gt; \u0026lt;div class=\u0026#34;animation-img\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; css部分:使用steps(n)动画函数,将100%的动画终点分为n帧来执行,每一帧的时间为动画的总时长除以帧数。\n播放一次,停留在最后一帧图片的样式:\n.animation-wrapper { width: 100vw; height: 850px; position: relative; } .animation-img { width: 25500px; height: 850px; background-size: 25500px 588px; /* 使用steps(33)将动画分为33帧, 比原始的34帧少一帧是为了停留在最后一帧的开始位置, forwards用于控制停留在动画的100%时的样式 */ animation: back-bg-steps 4s steps(33) forwards; /* todo: 修改图片路径 */ background-image: url(\u0026#39;img.png\u0026#39;); background-position: 0 0; } @keyframes back-bg-steps { 100% { /* 这里100%的位置偏移要和33帧的宽度对应上 */ transform: translatex(-24750px); } } 循环播放的样式:\n.animation-wrapper { width: 100vw; height: 850px; position: relative; } .animation-img { width: 25500px; height: 850px; background-size: 25500px 588px; /* todo: 修改图片路径 */ background-image: url(\u0026#39;img.png\u0026#39;); background-position: 0 0; /* 控制序列帧动画 */ animation: back-bg-steps 4s steps(34) alternate infinite; } @keyframes back-bg-steps { 100% { transform: translatex(-25500px); } } 遇到的问题:\n播放一次停止在最后一帧的方式:一开始控制动画的100%位置是使用background-position: -24750px,这种方式在ios中会出现图片前面的帧闪烁的问题。\n资源加载和动画不同步的问题:由于拼接的序列帧长图有点大,图片在加载的时候,动画就已经在执行了,网络太差的情况,会出现动画已经播放完了,资源才加载完成。 ===\u0026gt; 这个可以通过使用动画前,进行图片的预加载,这样子浏览器就会使用已经加载过的图片,而不会再去加载。\n","date":"2024-05-13","permalink":"https://zeroailian.github.io/posts/css%E6%92%AD%E6%94%BE%E5%8A%A8%E6%95%88/","summary":"使用webp格式的图片 使用方式:将webp的图片作为背景图或者放在img中。 出现的问题:在ios中会出现帧图片重影的情况。 使用拼接的序列帧长图 前提:设计提供每一","title":"css动效使用总结"},]
[{"content":"使用场景 需要将一张图片自适应到一个长度、宽度固定的容器中、且充满整个容器,但不希望压缩图片。在实际中,我们可以通过设置 div 标签的 background-size: cover; 来实现,也可以通过设置 img 标签的 object-fit: cover; 来实现。有一种场景,想要将图片裁剪成cover的样子导出为base64作为其他用处,以上两种方式就很难实现。\n解决方案 一种简单的实现方式,可以通过 html2cavans 包将 div 或者 img 标签调整好的图片大小做一个快照保存成 cavans 来导出。本质上可以直接使用 canvas 来实现该功能,基本的原理是将图片等比例放大,然后定位图片在 cavans 中的绘制起点位置。实现逻辑:\n创建一个目标大小的 cavans 标签。 计算图片和 cavans 的最大缩放比例,等于宽和高的缩放比例的最大值。 计算图片缩放后的宽和高。 计算 cavans (0, 0)坐标对应图片的坐标点,也就是起点的偏移位置。 调用cavans 的绘制方法,将图片、起点偏移信息、缩放后的宽高传进去绘制,最后导出base64即可。 代码实现 /** * 以cover的方式改变图片的大小 * @param {string} src 图片 * @param {number} targetwidth 目标图片的宽度 * @param {number} targetheight 目标图片的高度 */ changeimage(src: string, targetwidth: number, targetheight: number) { return new promise((resolve) =\u0026gt; { // 创建一个canvas const canvas = document.createelement(\u0026#39;canvas\u0026#39;); const ctx = canvas.getcontext(\u0026#39;2d\u0026#39;); // 加载图片资源 const img = new image(); img.src = src; img.onload = function () { const canvaswidth = targetwidth; // 设置 canvas 的固定宽度 const canvasheight = targetheight; // 设置 canvas 的固定高度 canvas.width = canvaswidth; canvas.height = canvasheight; const scalex = canvaswidth / img.width; // 计算横向缩放比例 const scaley = canvasheight / img.height; // 计算纵向缩放比例 const scale = math.max(scalex, scaley); // 取最大的缩放比例 const scaledwidth = img.width * scale; // 计算缩放后的宽度 const scaledheight = img.height * scale; // 计算缩放后的高度 const offsetx = (canvaswidth - scaledwidth) / 2; // 计算图片在 canvas 中的横向偏移量 const offsety = (canvasheight - scaledheight) / 2; // 计算图片在 canvas 中的纵向偏移量 //绘制图片并导出 ctx.drawimage(img, offsetx, offsety, scaledwidth, scaledheight); resolve(canvas.todataurl()); }; }); } ","date":"2024-05-10","permalink":"https://zeroailian.github.io/posts/canvas-cover/","summary":"使用场景 需要将一张图片自适应到一个长度、宽度固定的容器中、且充满整个容器,但不希望压缩图片。在实际中,我们可以通过设置 div 标签的 background-size: cover; 来实现,也可以通过设置 img 标签的","title":"canvas实现图片的cover裁剪"},]
[{"content":"npm npm 1.x / 2.x 时期 npm 1.x版本和2.x版本,在下载包时,采用的是嵌套依赖树的模式。比如项目(project)依赖于package1和package2,同时package1和package2都依赖于package3,那么最终下载的依赖树结构如下:\n最终下载的 node_modules 结构如下:\nproject - node_modules --- package1 ----- node_modules ------- package3 --- package2 ----- node_modules ------- package3 其中,package3会被下载两次。这种嵌套依赖树的管理方式比较简单方便,但也会带来重复包太多的问题。同时,由于嵌套的层次未知,可能会带来访问路径太深的情况。\nnpm 3.x时期 npm从3.x版本开始,npm采用了扁平化依赖树的方式来管理包之间依赖。基于这种方式,下载包时,npm会将每个树节点的依赖提升根目录的 node_modules 下,出现相同包时,则按以下规则处理:\n版本相同,则去重,保留一个。 版本不同,则保留先下载的包在根目录的 node_modules 下,将新版本的包下载在树节点下的 node_mudules 下。以此来区分不同版本包的依赖。 例如下图的依赖树: 假设先解析下载的包为package1,则最终下载的 node_modules 结构如下:\nproject - node_modules --- package1 --- package3 --- package4@1.0.0 --- package2 ----- node_modules ------- package4@2.0.0 基于此,npm很大程度上解决了包重复下载和包访问路径过深的问题。但扁平化依赖树算法的出现,也带来了一定的计算开销。同时,npm依赖node-semver的包版本解析存在版本的不确定性,这会带来 npm install 时,不同的机器环境下安装的包版本会不一致。\nnpm v5时期 主要新增了 package-lock.json。该文件记录了 npm install 时,实际安装的包和依赖包的版本等信息。借助该文件,npm安装时的大概流程如下: 通过git版本控制改文件的一致性,可以达到不同机器环境,安装的包版本一致的效果。\nyarn yarn的出现,主要是针对npm各个时期发展中出现的不足,不断提出改进的方案,同时也促进了npm的不断优化。\n特点 并行安装:npm安装包的时候,是以串行的方式进行安装;而yarn在装包的时候,采用的是并行的方式进行,相对之下,效率要提高很多。 离线模式:对于已经安装过的包,yarn会缓存起来,再次安装时,会直接从缓存中获取,借此特性可以不需要通过网络去离线装包。 版本锁定:为了防止拉取到不同的版本,yarn在安装包的时候会生成 yarn.lock 文件 ,该文件记录了被安装的包的版本号。每次只要新增了一个模块,yarn 就会更新这个文件。 版本 yarn classic:yarn的初始版本,其目录结构与npm类似,保留了 node_modules 目录,同时带来了并行安装、离线下载、版本锁定等功能。\nyarn berry:yarn的新版本,摒弃了 node_modules 目录,会生成以下几个文件,其中 cache 目录存放了依赖包的压缩文件,减少了包大小,.pnp 文件用于项目定位依赖的包在 cache 中的哪个压缩文件中。unplugged 目录用于存放解压后的包,可以通过 yarn unplug xx 进行解压对应的包。同时,新版本的yarn也支持自定义插件和 .yml 的配置文件。\n.yarn/cache\r.yarn/unplugged\r.pnp pnpm pnpm动机 pnpm的出现是为了节省磁盘空间和提升项目的安装速度。npm和yarn的包管理形式是,每个项目都有自己的包目录,多个项目间会存在很多相同的包,大大浪费了磁盘的空间。pnpm实现该目的的方式主要是以下几点:\n将包放到磁盘可寻址的空间中,每当包有新版本更新时,则另外储存版本的不同文件,相同文件不重复 当项目依赖相应的包时,pnpm通过硬链接的方式来链接到相应的依赖包,借此,不同的项目就可以共享相同的包,而不必每个项目都拷贝一份。 由于不必下载包到项目下,只是通过生成链接文件的方式来依赖包,随着磁盘中已有的共享包越来越多,pnpm构建项目的速度也会越来越快。 项目结构 pnpm构建后,依赖的包结构如下: package.json中直接依赖的包生成到node_modules 下,并软链接(符号链接)到 .pnpm 中对应的依赖包。 生成 .pnpm 目录,目录下存放每个依赖包的硬链接和符号链接的关系。硬链接主要是依赖包跟磁盘的联系,符号链接用来指定依赖包直接的联系。 总结 npm、yarn、pnpm在各自的版本迭代中,不断完善缺陷,加入新的特性。随着版本的迭代优化,每个包管理器之间会有相互借鉴和改进的情况,下表是依据个人目前的了解对各个特性的对比总结。\nnpm yarn pnpm 嵌套依赖 v1.0 / v2.0 × × 扁平化依赖 v3.0 yarn classic × 依赖包压缩 × yarn berry × 版本锁定 v5.0 √ √ 并行下载 × √ × 离线下载 × √ × 共享磁盘包 × × √ ","date":"2024-05-10","permalink":"https://zeroailian.github.io/posts/npmyarnpnpm%E7%9A%84%E5%8C%BA%E5%88%AB/","summary":"npm npm 1.x / 2.x 时期 npm 1.x版本和2.x版本,在下载包时,采用的是嵌套依赖树的模式。比如项目(project)依赖于package1和package2,同时packa","title":"npm、yarn、pnpm的区别"},]
[{"content":"简介 每个项目的根目录下面,一般都会有package.json文件,定义了这个项目中所需各种模板及项目中的配置信息。npm install命令根据这个配置文件,自动下载所需的模块,也就是配置项目中所需的运行和开发环境,其中下载的模块版本和node-semver语义化的版本控制系统有关,本文就package.json的版本号组成和版本号解析两部分进行简单介绍。\n版本号 版本号格式有以下四种情况,其中连接符是固定的 - | +\n标准版本号 标准版本号-先行版本号 标准版本号+编译信息 标准版本号-先行版本号+编译信息 总结:版本号 = 标准版本号[-先行版本号][+编译信息]\n标准版本号 标准版本代表着代码包的核心版本标识。组成格式为 x.y.z,x、y、z 均分非负的整数,且均是以递增的方式来增加。x代表主版本号,x的修改,一般意味着代码包有不兼容的修改;y代表次版本号,y的修改,一般意味着有向下兼容的新功能出现;z代表修订号,z的修改意味着只做了向下兼容的修正。\n先行版本号 先行版本代表当前版本并非稳定而且可能无法满足预期的兼容性需求。组成格式为 以句点分隔的标识符,其中标识符由 ascii 字母数字和连接号 [0-9a-za-z-] 组成,例如1.0.0-alpha、1.0.0-alpha.1。\n编译信息 编译信息被标注在标准版本号或先行版本号之后,用于作为编译信息记录,不参与版本号的区别比较。组成格式与先行版本号一致。\n版本号的优先级比较\n判断优先层级时,把版本依序拆分为主版本号、次版本号、修订号及先行版本号后进行比较(编译信息不在这份比较的列表中)。 由左到右依序比较每个标识符,第一个差异值用来决定优先层级:主版本号、次版本号及修订号以数值比较。 例如:1.0.0 \u0026lt; 2.0.0 \u0026lt; 2.1.0 \u0026lt; 2.1.1。 当主版本号、次版本号及修订号都相同时,改以优先层级比较低的先行版本号决定。 例如:1.0.0-alpha \u0026lt; 1.0.0。 有相同主版本号、次版本号及修订号的两个先行版本号,其优先层级由从左到右的每个被句点分隔的标识符来比较,直到找到一个差异值后决定: 只有数字的标识符以数值高低比较。 有字母或连接号时则逐字以 ascii 的排序来比较。 数字的标识符比非数字的标识符优先层级低。 若开头的标识符都相同时,句点分隔的栏位比较多的先行版本号优先层级比较高。 版本号解析 package.json中常见的依赖代码包版本格式:\nversion:下载的版本必须与 version 完全匹配。 \u0026gt;version:下载版本必须大于 version。 \u0026gt;=version:下载版本必须大于或等于 version。 \u0026lt;version:下载版本必须小于 version。 \u0026lt;=version:下载版本必须小于或等于 version。 ~version:如果只指定主版本号(eg: ~1),则下载的代码包限定在1.x.x;如果指定到次版本号(eg: ~1.2),则下载的代码包限定在1.2.x;如果指定到修订号(eg: ~1.2.3),则下载的代码包限定为 \u0026gt;=1.2.3 且 \u0026lt; 1.3.0。 ^version:如果主版本号为0,则效果和~version一致;主版本号不为0(eg: 1.x.x),则下载的代码包为当前主版本号下的最新版本。 1.2.x :下载的代码包大于等于1.2.0且小于1.3.0。 *:下载任何非先行版的代码包。 \u0026quot;\u0026quot;:空字符与* 效果一样。 version1-version2:下载版本必须 \u0026gt;=version1且 \u0026lt;=version2。 range1||range2:下载版本符合range1 或 range2的限定,range1 和 range2是一个版本表达式。 http://...:下载指定 url 的代码包。 git…:下载指定 git url 的代码包。 user/repo:下载指定代码仓库中的包。 tag:下载标记并发布为tag的特定版本。 path/path/path:下载的本地路径的代码包。 ","date":"2022-10-29","permalink":"https://zeroailian.github.io/posts/node-semver/","summary":"简介 每个项目的根目录下面,一般都会有package.json文件,定义了这个项目中所需各种模板及项目中的配置信息。npm install命令根据这个配置文件,自动","title":"node-semever总结"},]
[{"content":"我的一切吗\r我的一切吗?\n想知道的话,可以全部告诉你\n去找出来吧\n我的一切都在那里!\n","date":"0001-01-01","permalink":"https://zeroailian.github.io/about/","summary":"我的一切吗 我的一切吗? 想知道的话,可以全部告诉你 去找出来吧 我的一切都在那里!","title":"about"},]
[{"content":"","date":"0001-01-01","permalink":"https://zeroailian.github.io/archive/","summary":"","title":"archive"},]
[{"content":" 🌞 工具库 帮小忙 开发小工具 时间戳 配乐资源网 🔨 常用网站 github gitee apifox processon 设计网 时评网 写作网 🔖 好文博客 你不知道javascript https://www.javascriptc.com/books/you-dont-know-js/ 前端开发核心知识进阶 https://codeteenager.github.io/fe-core-book/guide/ 数据结构算法博客 https://ziyi2.github.io/algorithms/guide/introduction.html 算法 https://programmercarl.com/ ","date":"0001-01-01","permalink":"https://zeroailian.github.io/nav/","summary":"🌞 工具库 帮小忙 开发小工具 时间戳 配乐资源网 🔨 常用网站 github gitee apifox processon 设计网 时评网 写作网 🔖 好文博客 你不知道javascript https://www.javascriptc.com/books/you-dont-know-js/ 前端开发核心知识进阶 https://codeteenager.github.io/fe-core-book/guide/ 数据结构算法博客 https://ziyi2.github.io/algorithms/guide/introduction.html 算法","title":"nav"},]
[{"content":"","date":"0001-01-01","permalink":"https://zeroailian.github.io/search/","summary":"","title":"search"},]
[{"content":"第一篇草稿 测试草稿\n","date":"0001-01-01","permalink":"https://zeroailian.github.io/notes/note-1/","summary":"第一篇草稿 测试草稿","title":"测试"},]