前端三件套配合MarsCode实现钉钉官网动画 # 豆包MarsCode

本文主要是介绍前端三件套配合MarsCode实现钉钉官网动画 # 豆包MarsCode,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 如何固定动画区域
  • 创建项目
  • MarsCode 设置样式
    • MarsCode 优点1
    • MarsCode 缺点
    • MarsCode 优点2
  • js实现动画
    • 实现获取动画曲线的函数
    • 为什么实现这个函数?
    • 根据当前滚动位置,计算每一个元素不同的数值
      • 更新 dom 的 style
      • 更新 animationMap
      • getDomAnimation

@豆包MarsCode

要写出钉钉官网动画,首先第一步就是分析钉钉官网动画是怎么实现的!

在这里插入图片描述
滑动滚轮发现到了动画这里,界面是不会继续滚动的,而是等待动画执行完成后,才继续滚动!我们要实现的第一点就是:如何固定动画区域!只有搞定这个问题,下一个问题才是如何实现动画!

如何固定动画区域

在这里插入图片描述

这是一个解析图:灰色部分是网页内容比较长,蓝色部分是动画的执行区域,相对来说比较高(不然滚动条一滚动就被带走了),但是只有这两个是不行的,还需要红色这个粘性定位的内容,等内容滚动到红色区域时,会一直固定,等父元素(蓝色部分)滚动到最上面的时候,底部会将红色部分一起带走(保证了红色区域不管怎么滚动,有一段时间一直在可视区域内)!

不懂粘性定位可以异步:css Position(定位) [第八天]

创建项目

现在我们一步一步来,配合我们的 MarsCode 完成代码 !首先在vscode里准备好我们的前端三件套文件!

在这里插入图片描述

在这里插入图片描述

其中:body 是灰色部分,playground 是蓝色部分,红色部分是 animation_container,这里只是模仿钉钉这个动画,所以里面用的是小方格 list-item!

MarsCode 设置样式

使用 MarsCode 设置样式!

MarsCode 优点1

简单注释,MarsCode 生成的代码还是挺好用的

在这里插入图片描述

在这里插入图片描述

MarsCode 缺点

但是这种有多个需求的,MarsCode 就不能特别好的提示了

在这里插入图片描述

MarsCode 优点2

可以通过尝试换书写注释来生成正确的代码,但是比较难试!

通过菜鸟不断的尝试,MarsCode 居然真的自己写出来了:

在这里插入图片描述

效果如下:

在这里插入图片描述

然后我们自己优化一下:

/* 通配符取消margin、padding */
* {margin: 0;padding: 0;
}
body {height: 4000px;
}
/* 设置header占满屏幕,背景白色,文字黑色100px */
.header {height: 100vh;width: 100%;background-color: #fff;color: #000;font-size: 100px;text-align: center;line-height: 100vh;
}.playground {height: 2000px;width: 100%;background-color: #000;
}
/* 设置animation_container为粘性定位,并占满屏幕 */
.animation_container {position: sticky;top: 0;height: 100vh;width: 100%;
}/* 设置list在animation_container的中间,list-item排列成2行7列,均匀分布 */
.list {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);display: grid;grid-template-columns: repeat(7, 1fr);grid-template-rows: repeat(2, 1fr);grid-gap: 50px;
}/* 请设置list-item的宽高为100px,高宽比为1:1 */
.list-item {width: 100px;height: 100px;aspect-ratio: 1/1;border-radius: 5%;
}/* list-item有14个,请均匀分布在list中,且2行7列,颜色各不相同 */
.list-item:nth-child(1) {background-color: #f00;
}
.list-item:nth-child(2) {background-color: #0f0;
}
.list-item:nth-child(3) {background-color: #00f;
}
.list-item:nth-child(4) {background-color: #ff0;
}
.list-item:nth-child(5) {background-color: #0ff;
}
.list-item:nth-child(6) {background-color: #f0f;
}
.list-item:nth-child(7) {background-color: #fff;
}
.list-item:nth-child(8) {background-color: #f00;
}
.list-item:nth-child(9) {background-color: #0f0;
}
.list-item:nth-child(10) {background-color: #00f;
}
.list-item:nth-child(11) {background-color: #ff0;
}
.list-item:nth-child(12) {background-color: #0ff;
}
.list-item:nth-child(13) {background-color: #f0f;
}
.list-item:nth-child(14) {background-color: #fff;
}

结果

在这里插入图片描述

到此元素结构和样式搞定了!

js实现动画

现在到了实现动画的阶段了,首先要知道css动画是什么?css就是数值随时间的变化,但是这里没有时间,细心的同学就会发现虽然和时间无关,但是和滚动条相关了,所以要抽象成这个图

在这里插入图片描述

值随滚动条变化的图,而不是时间了!

实现获取动画曲线的函数

现在就是要写一个动画曲线函数,给我一个x,算出一个y,为了知道曲线函数需要传入scrollStart、scrollEnd、valueStart、valueEnd,然后剩下的就交给 MarsCode了!

写函数,然后输入几个参数后,MarsCode 自己就帮助我们生成好了!
在这里插入图片描述
自己想要完善一下(写的时候,MarsCode 也可以直接帮你,实在是牛)

在这里插入图片描述

function createAnimation(scrollStart, scrollEnd, valueStart, valueEnd) {return function (x) {if (x < scrollStart) return valueStart;if (x > scrollEnd) return valueEnd;return (valueStart +((valueEnd - valueStart) * (x - scrollStart)) / (scrollEnd - scrollStart));};
}

为什么实现这个函数?

就是用于备用,直接传值进函数,获得一个根据滚动条和属性直接的关系函数(MarsCode也直接帮你完成,但是暂时不需要)
在这里插入图片描述
这里解释一下

opacity 这个函数就是:滚动条从0 到 100,那么透明度就从 0 到 1的函数曲线!

当然这里的滚动值不是很对,这个就是后面我们按需求修改!

根据当前滚动位置,计算每一个元素不同的数值

既然是动态变化的值,那肯定是这样的数据结构

在这里插入图片描述

所以要建立映射关系,将对象给每一个 dom

// 为每一个元素映射一个动画
const animationMap = new Map();
const items = document.querySelectorAll(".list-item");
const playground = document.querySelector(".playground");
const list = document.querySelector(".list");

然后就是两件事:

  1. 更新 animationMap
  2. 更新 dom 的 style

所以写出这两个函数

// 更新动画隐射
function updateAnimationMap() {}// 将map结构用于元素
function updateStyle() {}

更新 dom 的 style

其中比较好写的就是 更新 dom 的 style

思路:获取整个界面的滚动距离,循环 Map 去获取上面的对象,再循环对象获取值并调用函数!

有了思路,MarsCode 会直接帮你写好(写两个for,自己就出来了)

// 将map结构用于元素
function updateStyle() {const scrollY = window.scrollY;for (const [element, animation] of animationMap) {for (const key in animation) {// 自己添加的注释// 调用每个dom对应的动画函数// 动画函数的参数是当前的scrollYelement.style.setProperty(key, animation[key](scrollY));}}
}

写完之后就调用,MarsCode 也会帮你完成

在这里插入图片描述

更新 animationMap

思路:循环dom节点,并设置Map

写一个for,MarsCode 直接就帮你写好了

在这里插入图片描述

只是这里没这么简单,设置的是那个数据结构的对象,所以我们只保留设置部分!

function getDomAnimation(dom) {}// 更新动画隐射
function updateAnimationMap() {for (const item of items) {animationMap.set(item, getDomAnimation(dom));}
}

getDomAnimation

返回的是一个对象

return {opacity,transform,
};

这里的 opacity,transform 又可以通过 createAnimation 来获取!然后发现 scrollStart,scrollEnd 所有的dom是一样的,所以直接当参数传入!

function getDomAnimation(scrollStart, scrollEnd, dom) {const opacity = createAnimation(scrollStart, scrollEnd, 0, 1);const transform = createAnimation(scrollStart, scrollEnd, 0, 100);return {opacity,transform,};
}// 更新动画隐射
function updateAnimationMap() {for (const item of items) {animationMap.set(item, getDomAnimation(scrollStart, scrollEnd, item));}
}

确定好什么时候滚动、以及什么时候滚动结束!

// 更新动画隐射
function updateAnimationMap() {const playgroundRect = playground.getBoundingClientRect();const scrollY = window.scrollY;const scrollStart = playgroundRect.top + scrollY;const scrollEnd = playgroundRect.bottom + scrollY - window.innerHeight;for (const item of items) {animationMap.set(item, getDomAnimation(scrollStart, scrollEnd, item));}
}

这个时候透明度的变化已经完成!

剩下的就是transform的一些属性,也可以按照 opacity 一样,不同的是这个 transformx\transformy ,需要计算

function getDomAnimation(scrollStart, scrollEnd, dom) {const opacity = createAnimation(scrollStart, scrollEnd, 0, 1);const scale = createAnimation(scrollStart, scrollEnd, 0.5, 1);const Xtransform = createAnimation(scrollStart, scrollEnd, ?, 0);const Ytransform = createAnimation(scrollStart, scrollEnd, ?, 0);const transform = (x) => {return `scale(${scale(x)}) translate(${Xtransform(x)}px, ${Ytransform(x)}px)`;};return {opacity,transform,};
}

都是从中间出来的,所以

function getDomAnimation(scrollStart, scrollEnd, dom) {const opacity = createAnimation(scrollStart, scrollEnd, 0, 1);const scale = createAnimation(scrollStart, scrollEnd, 0.5, 1);const { clientWidth, clientHeight, offsetTop, offsetLeft } = dom;console.log(clientWidth, clientHeight, offsetTop, offsetLeft);const listRect = list.getBoundingClientRect();const Xtransform = createAnimation(scrollStart,scrollEnd,listRect.width / 2 - clientWidth / 2 - offsetLeft,0);const Ytransform = createAnimation(scrollStart,scrollEnd,listRect.height / 2 - clientHeight / 2 - offsetTop,0);const transform = (x) => {return `translate(${Xtransform(x)}px, ${Ytransform(x)}px) scale(${scale(x)}) `;};return {opacity,transform,};
}

至此,效果基本实现,再就是动画需要延时,通过data-设置delay来实现

<div data-delay="0" class="list-item"></div>
<div data-delay="1" class="list-item"></div>
<div data-delay="2" class="list-item"></div>
<div data-delay="3" class="list-item"></div>
<div data-delay="2" class="list-item"></div>
<div data-delay="1" class="list-item"></div>
<div data-delay="0" class="list-item"></div>
<div data-delay="0" class="list-item"></div>
<div data-delay="1" class="list-item"></div>
<div data-delay="2" class="list-item"></div>
<div data-delay="3" class="list-item"></div>
<div data-delay="2" class="list-item"></div>
<div data-delay="1" class="list-item"></div>
<div data-delay="0" class="list-item"></div>
function getDomAnimation(scrollStart, scrollEnd, dom) {// 注意这个不要超过滚动距离,不然就会导致超过的动画瞬间完成scrollStart += dom.dataset.delay * 200;const opacity = createAnimation(scrollStart, scrollEnd, 0, 1);const scale = createAnimation(scrollStart, scrollEnd, 0.5, 1);const { clientWidth, clientHeight, offsetTop, offsetLeft } = dom;const listRect = list.getBoundingClientRect();const Xtransform = createAnimation(scrollStart,scrollEnd,listRect.width / 2 - clientWidth / 2 - offsetLeft,0);const Ytransform = createAnimation(scrollStart,scrollEnd,listRect.height / 2 - clientHeight / 2 - offsetTop,0);const transform = (x) => {return `translate(${Xtransform(x)}px, ${Ytransform(x)}px) scale(${scale(x)}) `;};return {opacity,transform,};
}

到此,钉钉官网动画基本上主要内容完成了,剩下的都是些图标什么的,还是比较简单的!

体验完 MarsCode ,感觉智能提示等都很不错,但是也有不足的地方,就是有些没有确定思路的地方,如果你不会,那么提示的大概率也是错误的!所以 AI 只是辅助,重要的还是自己的能力过关!

这篇关于前端三件套配合MarsCode实现钉钉官网动画 # 豆包MarsCode的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

Vue和React受控组件的区别小结

《Vue和React受控组件的区别小结》本文主要介绍了Vue和React受控组件的区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录背景React 的实现vue3 的实现写法一:直接修改事件参数写法二:通过ref引用 DOMVu

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

C#实现一键批量合并PDF文档

《C#实现一键批量合并PDF文档》这篇文章主要为大家详细介绍了如何使用C#实现一键批量合并PDF文档功能,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言效果展示功能实现1、添加文件2、文件分组(书签)3、定义页码范围4、自定义显示5、定义页面尺寸6、PDF批量合并7、其他方法

SpringBoot实现不同接口指定上传文件大小的具体步骤

《SpringBoot实现不同接口指定上传文件大小的具体步骤》:本文主要介绍在SpringBoot中通过自定义注解、AOP拦截和配置文件实现不同接口上传文件大小限制的方法,强调需设置全局阈值远大于... 目录一  springboot实现不同接口指定文件大小1.1 思路说明1.2 工程启动说明二 具体实施2

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T

Python实现精确小数计算的完全指南

《Python实现精确小数计算的完全指南》在金融计算、科学实验和工程领域,浮点数精度问题一直是开发者面临的重大挑战,本文将深入解析Python精确小数计算技术体系,感兴趣的小伙伴可以了解一下... 目录引言:小数精度问题的核心挑战一、浮点数精度问题分析1.1 浮点数精度陷阱1.2 浮点数误差来源二、基础解决