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

news2024/11/14 20:54:55

文章目录

  • 如何固定动画区域
  • 创建项目
  • 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对应的动画函数
      // 动画函数的参数是当前的scrollY
      element.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 只是辅助,重要的还是自己的能力过关!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2099742.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

| AutoDL租服务器 |AutoDL租服务器保姆级教程

&#x1f411; | AutoDL租服务器 |AutoDL租服务器保姆级教程 &#x1f411; 文章目录 &#x1f411; | AutoDL租服务器 |AutoDL租服务器保姆级教程 &#x1f411;&#x1f411; 前言&#x1f411;&#x1f411; 实例创建&#x1f411;&#x1f411; 环境配置&#x1f411;&am…

C# DLL已定义类或方法,但是编译报错未定义

现有应用程序1个&#xff0c;动态链接库3个分别称为A、B、C。 应用程序输出在目录P1&#xff0c;动态链接库输出在目录P2。 应用程序引用A、B、C动态链接库&#xff0c;动态链接库A引用B&#xff0c;B引用C。 此时修改动态链接库C&#xff0c;在VS中开发应用程序时可以识别到…

MQ专题:消息积压相关问题和解决思路

一、如何发现消息出现了堆积 二、常见的原因及解决方案 三、消息出现了大量堆积&#xff0c;如何解决 四、建议

2024年软考-信息安全工程师考试介绍及考纲

2024年软考-信息安全工程师考试介绍及考纲 2024年软考-信息安全工程师 考试介绍及考纲 一、考试信息 考试时间&#xff1a;预计2024年11月9日-12日。 考试科目&#xff1a; 科目一&#xff1a;基础知识 客观题&#xff1a;75空 满分&#xff1a;75分 科目二&#xff1a;应用…

C++ | Leetcode C++题解之第391题完美矩形

题目&#xff1a; 题解&#xff1a; class Solution { public:bool isSubsequence(string s, string t) {int n s.size(), m t.size();vector<vector<int> > f(m 1, vector<int>(26, 0));for (int i 0; i < 26; i) {f[m][i] m;}for (int i m - 1; …

linux中最简单方式使用crontab打印当前时间

因特殊需求&#xff0c;需要在linux的某个文件中每分钟打印出当前时间。 先手动试一下命令&#xff1a; echo $(date) 打印出&#xff1a; Mon Sep 1 09:28:06 AM CST 2024 而我需要达到的效果是&#xff1a; 2024-09-01 09:28:06 于是命令改成了&#xff1a; echo $(date &quo…

Unified-IoU:用于高质量对象检测

摘要 https://arxiv.org/pdf/2408.06636 目标检测是计算机视觉领域的重要部分&#xff0c;而目标检测的效果直接由预测框的回归精度决定。作为模型训练的关键&#xff0c;交并比&#xff08;IoU&#xff0c;Intersection over Union&#xff09;极大地展示了当前预测框与真实框…

GCViT实战:使用GCViT实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整策略设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试完整的代码 在上…

Android kotlin使用Netty网络框架实践(客户端、服务端)

开发工具&#xff1a;Android studio 语言:kotlin 设计原理&#xff1a;通讯协议&#xff1a;头类型长度数据尾&#xff0c;自定义编解码器&#xff0c;解析和包装发送数据流&#xff0c;以下贴出部分关键代码 说明&#xff1a;代码中封装了client和server端&#xff0c;可…

记录一下idea的一些使用技巧和遇到的异常(持续更新)

技巧 自己的模板——live template 有些代码在项目中通常会被用到或会被重复使用&#xff0c;可以自己写一个模板存起来&#xff0c;要用的时候用快捷键生成就可以了。 在这里选择生效范围 现在&#xff0c;就有我们自己的模板了&#xff0c;一回车就自动生成 idea的全局配置…

AD7606工作原理以及FPGA控制验证(串行和并行模式)

文章目录 一、AD7606介绍二、AD7606采集原理2.1 AD7606功能框图2.2 AD7606管脚说明 三、AD7606并行模式时序分析以及实现3.1 并行模式时序图3.2 并行模式时序要求3.3 代码编写3.4 仿真观察 四、AD7606串行模式时序分析以及实现4.1 串行模式时序图4.2 串行模式时序要求4.3 代码编…

WWDG—窗口看门狗

WWDG—窗口看门狗 窗口看门狗跟独立看门狗一样&#xff0c;也是一个递减计数器不断的往下递减计数&#xff0c;当减到一个固定值 0X40时还不喂狗的话&#xff0c;产生复位&#xff0c;这个值叫窗口的下限&#xff0c;是固定的值&#xff0c;不能改变。这个是跟独立看门狗类似的…

C练手题--Two Oldest Ages 【7 kyu】

一、原题 链接&#xff1a;Training on Two Oldest Ages | Codewars The two oldest ages function/method needs to be completed. It should take an array of numbers as its argument and return the two highest numbers within the array. The returned value should b…

bash反弹shell分析

目录 介绍步骤 介绍 与目标主机建立连接的原理是利用漏洞执行ShellCode。 GetShell的实质是&#xff1a;执行ShellCode&#xff0c;将目标主机的Shell重定向到攻击机。拿到Shell利于后续的渗透。 所谓的反弹Shell是指GetShell的过程由目标主机主动发起&#xff08;反向连接&a…

mysql(查询)

1.单表查询 &#xff08;1&#xff09;查询多个字段 指定列查询基础语法&#xff1a;select 字段1&#xff0c;字段2&#xff0c;字段3&#xff0c;... from 表名&#xff1b; 全列查询基础语法&#xff1a;select * from 表名&#xff1b; 注意&#xff1a; 1&#xff09;在实…

AI-Talk开发板CSK6固件烧录

一、说明 在windows系统上使用cskburn desktop工具对主控CSK6011A进行固件烧录&#xff0c;烧录接口为UART2&#xff08;TXD:PA18&#xff0c;RXD:PA15&#xff09;&#xff0c;需要CSK6011A处于boot模式才能升级。 官方参考文档&#xff1a;cskburn桌面烧录工具 | 聆思文档中…

DETR3D: 3D Object Detectionfrom Multi-view Images via 3D-to-2D Queries

本文的主要贡献如下&#xff1a; 我们提出了一种基于RGB图像的简化3D物体检测模型。与现有工作在最终阶段结合来自不同相机视角的物体预测不同&#xff0c;我们的方法在每一层计算中融合所有相机视角的信息。据我们所知&#xff0c;这是首次尝试将多摄像头检测视为3D集合到集合…

软考攻略/超详细/系统集成项目管理工程师/基础知识分享06

2.2 新一代信息技术及应用 2.2.1 物联网&#xff08;掌握&#xff09; 物联网&#xff1a;是指通过信息传感设备&#xff0c;按约定的协议将任何物品与互联网相连接&#xff0c;进行信息交换和通信&#xff0c;以实现只能识别、定位、跟踪、监控和管理的网络 1、技术基础 物联…

Flask框架 完整实战案例 附代码解读 【3】

Flask 是一个轻量级的可定制框架&#xff0c;使用Python语言编写&#xff0c;较其他同类型框架更为灵活、轻便、安全且容易上手。 前面已经写过项目从新建运行安装到测试部署的全流程&#xff0c;其中有写Flask框架从新建到部署全流程&#xff0c;但是只有部分代码。本篇主要是…

国产光耦合器在提高各行业能源效率方面的作用

随着各行业对节能解决方案的需求不断增长&#xff0c;国产光耦合器已成为降低能耗和提高整体系统效率的关键部件。这些由本地制造商开发的组件现在不仅因其成本效益而受到认可&#xff0c;而且还因其能够满足需要可靠隔离和高效电源管理的工业应用的特定需求而受到认可。 通过隔…