前端三件套配合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

相关文章

在React中引入Tailwind CSS的完整指南

《在React中引入TailwindCSS的完整指南》在现代前端开发中,使用UI库可以显著提高开发效率,TailwindCSS是一个功能类优先的CSS框架,本文将详细介绍如何在Reac... 目录前言一、Tailwind css 简介二、创建 React 项目使用 Create React App 创建项目

vue使用docxtemplater导出word

《vue使用docxtemplater导出word》docxtemplater是一种邮件合并工具,以编程方式使用并处理条件、循环,并且可以扩展以插入任何内容,下面我们来看看如何使用docxtempl... 目录docxtemplatervue使用docxtemplater导出word安装常用语法 封装导出方

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定