当前位置: 首页 > article >正文

js 动画库、2048核心逻辑、面试题add[1][2][3]+4

1、js 动画库 web animation api

(1)初始化代码

  • hmtl、css 部分
    • 初始化全局背景黑色
    • 初始化黄色小球
  • js 部分
    • 监听全局点击事件
    • 创建并添加元素 class="pointer" 的 div 标签
      • 设置 left、top 位置
      • 监听动画结束事件,移除该元素
    • 定位小球到画面中心
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="./css/js动画库.css">
</head>
<body><div class="ball"></div><script src="./js/js动画库.js"></script>
</body>
</html>
const ball = document.querySelector('.ball');function init() {const x = window.innerWidth / 2;const y = window.innerHeight / 2;ball.style.transform = `translate(${x}px, ${y}px)`
}
init()
body {padding: 0;margin: 0;width: 100%;height: 100vh;background-color: #000;
}
.ball {width: 100px;height: 100px;background-color: yellow;border-radius: 50%;
}

 (2)实现步骤

①点击小球移动

animate():不改变 dom 树,因此不需要浏览器主线程管理,就不会阻塞主线程

window.addEventListener("click", (e) => {const x = e.clientX;const y = e.clientY;move(x, y);
});function move(x, y) {ball.animate([{transform: `translate(0px, 0px)`,},{transform: `translate(${x}px, ${y}px)`,}],2000)
}

②小球不回到中心位置
ball.animate([{transform: `translate(0px, 0px)`,},{transform: `translate(${x}px, ${y}px)`,}],{duration: 1000,fill: 'forwards',}
)

③获取小球当前位置
function move(x, y) {// 获取小球位置const rect = ball.getBoundingClientRect();const ballX = rect.left;const ballY = rect.top;ball.animate([{transform: `translate(${ballX}px, ${ballY}px)`,},{transform: `translate(${x}px, ${y}px)`,}],{duration: 1000,fill: 'forwards',})
}

④清除上一个动画
// 注意:只能在获取小球位置后清除
ball.getAnimations().forEach(animation=>{animation.cancel();
})
⑤小球先原地拉伸,后移动
ball.animate([{transform: `translate(${ballX}px, ${ballY}px)`,},{transform: `translate(${ballX}px, ${ballY}px) scaleX(1.5)`,offset: 0.6, // 该部分动画所占时长},{transform: `translate(${x}px, ${y}px) scaleX(1.5)`,offset: 0.8,},{transform: `translate(${x}px, ${y}px)`,}],{duration: 1000,fill: 'forwards',}
)

⑤拉伸角度跟随鼠标位置
const rad = Math.atan2(y - ballY, x - ballX);
const deg = (rad * 180) / Math.PI;
ball.animate([{transform: `translate(${ballX}px, ${ballY}px) rotate(${deg}deg)`,},{transform: `translate(${ballX}px, ${ballY}px) rotate(${deg}deg) scaleX(1.5)`,offset: 0.6, // 该部分动画所占时长},{transform: `translate(${x}px, ${y}px) rotate(${deg}deg) scaleX(1.5)`,offset: 0.8,},{transform: `translate(${x}px, ${y}px) rotate(${deg}deg)`,}],{duration: 1000,fill: 'forwards',}
)

(3)完整代码

const ball = document.querySelector(".ball");function init() {const x = window.innerWidth / 2;const y = window.innerHeight / 2;ball.style.transform = `translate(${x}px, ${y}px)`;
}
init();window.addEventListener("click", (e) => {const x = e.clientX;const y = e.clientY;move(x, y);
});function move(x, y) {// 获取小球位置const rect = ball.getBoundingClientRect();const ballX = rect.left;const ballY = rect.top;// 注意:只能在获取小球位置后清除ball.getAnimations().forEach((animation)=>{animation.cancel();})const rad = Math.atan2(y - ballY, x - ballX);const deg = (rad * 180) / Math.PI;ball.animate([{transform: `translate(${ballX}px, ${ballY}px) rotate(${deg}deg)`,},{transform: `translate(${ballX}px, ${ballY}px) rotate(${deg}deg) scaleX(1.5)`,offset: 0.6, // 该部分动画所占时长},{transform: `translate(${x}px, ${y}px) rotate(${deg}deg) scaleX(1.5)`,offset: 0.8,},{transform: `translate(${x}px, ${y}px) rotate(${deg}deg)`,}],{duration: 1000,fill: 'forwards',})
}

2、实现 2048 的核心逻辑——合并

Array.prototype.print = function () {console.log(this.join("\n"));
};// 棋盘
const matrix = [[0, 2, 2, 0],[0, 0, 2, 2],[2, 4, 4, 2],[2, 4, 4, 4],
];/*** 移动* @param {*} matrix 棋盘* @param {*} direction 方向*/
function move(matrix, direction) {const rows = matrix.length;const cols = matrix[0].length;/*** 是否越界* @param {*} i* @param {*} j* @returns*/function _inRange(i, j) {return i >= 0 && i < rows && j >= 0 && j < cols;}// 配置方向const nexts = {up: (i, j) => [i + 1, j],down: (i, j) => [i - 1, j],left: (i, j) => [i, j + 1],right: (i, j) => [i, j - 1],};/*** 下一个位置* @param {*} i* @param {*} j* @returns*/function _nextPos(i, j) {const [ni, nj] = nexts[direction](i, j);if (!_inRange(ni, nj)) {return null;}return [ni, nj];}/*** 得到下一个非0的位置* @param {*} i* @param {*} j* @returns*/function _nextNonZeroPos(i, j) {const pos = _nextPos(i, j);if (!pos) {return null;}const [ni, nj] = pos;if (matrix[ni][nj] !== 0) {return pos;}return _nextNonZeroPos(ni, nj); // 递归}/*** 计算某个位置最新的值,同时计算该行或该列所有的最新值* @param {*} i* @param {*} j*/function _calc(i, j) {const pos = _nextNonZeroPos(i, j);if (!pos) {return;}const [ni, nj] = pos;const v = matrix[i][j]; // 当前位置值const nv = matrix[ni][nj]; // 下一个位置值if (v === 0) {matrix[i][j] = nv;matrix[ni][nj] = 0;_calc(i, j); // 递归} else if (v === nv) {matrix[i][j] *= 2;matrix[ni][nj] = 0;}const nextPos = _nextPos(i, j);_calc(...nextPos);}if(direction === 'up') {for (let i = 0; i < cols; i++) {_calc(0, i);}}if(direction === 'down') {for (let i = 0; i < cols; i++) {_calc(rows - 1, i);}}if(direction === 'left') {for (let i = 0; i < cols; i++) {_calc(i, 0);}}if(direction === 'right') {for (let i = 0; i < cols; i++) {_calc(i, cols - 1);}}
}matrix.print();
move(matrix, "down");
console.log("======================");
matrix.print();

3、实现 add

让下面代码成立

const r1 = add[1][2][3] + 4; // 期望结果 10
const r2 = add[10][20] + 30; // 期望结果 60
const r3 = add[100][200][300] + 400; // 期望结果 1000

(1)实现思路

  • 从 add 的调用得出,add 是对象且属性是未知的
  • 如何读取未知属性对象呢?——完成一个代理辅助函数

(2)实现步骤

①读值
function createProxy() {return new Proxy({},{get(target, prop) {console.log(prop);},});
}const add = createProxy();
add[100]; // 100
②返回值

步骤思路1:由 add[1][2][3] 可以看出返回值也必须是一个代理,这样在执行完 add[1] 后能继续执行后面的

const a1 = add[1];
const a2 = a1[2];
const a3 = a2[3];

步骤思路2:累计计算

以下代码报错的原因是 add[1] 是对象,而 2 是原始类型,二者无法相加

function createProxy(value = 0) {return new Proxy({},{get(target, prop) {console.log(prop);return createProxy(value + Number(prop));},});
}const add = createProxy();
const a = add[1] + 2;
console.log(a); // 报错 TypeError: Cannot convert a Symbol value to a number

步骤思路3:对象转为原始类型

function createProxy(value = 0) {const handler = () => value;return new Proxy({},{get(target, prop) {if(prop === Symbol.toPrimitive) {return handler;}return createProxy(value + Number(prop));},});
}const add = createProxy();
const a = add[1] + 2;
console.log(a); // 3
③完整代码-结果验证
function createProxy(value = 0) {const handler = () => value;return new Proxy({},{get(target, prop) {if(prop === Symbol.toPrimitive) {return handler;}return createProxy(value + Number(prop));},});
}// 实现add
const add = createProxy();
// 让下面代码成立
const r1 = add[1][2][3] + 4; // 期望结果 10
const r2 = add[10][20] + 30; // 期望结果 60
const r3 = add[100][200][300] + 400; // 期望结果 1000
console.log(r1); // 10
console.log(r2); // 60
console.log(r3); // 1000

4、Sass 星空

(1)初始化代码

注意:html 引入的是 css 文件

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="./css/Sass星空.css">
</head>
<body><div class="layer1"></div><div class="layer2"></div><div class="layer3"></div><div class="layer4"></div><div class="layer5"></div><div class="title">Sass 星空</div>
</body>
</html>

编写的 css 是在 scss 文件中,后续再通过编译生成对应的 css 文件即可

body {padding: 0;margin: 0;background-color: #10141A;
}.title {font-size: 40px;background: linear-gradient(to top, #000 0%, #fff 100%);-webkit-background-clip: text;background-clip: text;-webkit-text-fill-color: transparent;color: transparent;position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);
}

(2)实现步骤

①用 函数+阴影 实现 n 个随机星星
@function star($n) {$result: '#{random(100)}vw #{random(100)}vh 0 #fff';@for $i from 2 through $n {$result: '#{$result},#{random(100)}vw #{random(100)}vh 0 #fff'}@return unquote($result);
}.layer1 {position: fixed;width: 20px;height: 20px;border-radius: 50%;box-shadow: star(100);
}

 

②scss 编译成 css
  • 在 scss 文件目录中下载 sass
  • npm install sass
  • 执行编译命令
  • sass Sass星空.scss Sass星空.css
③让星星动起来
.layer1 {position: fixed;width: 20px;height: 20px;border-radius: 50%;box-shadow: star(100);animation: moveUp 10s linear infinite;
}
@keyframes moveUp {to {transform: translateY((-100vh));}
}

④断层无感处理
.layer1 {position: fixed;width: 20px;height: 20px;left: 0;top: 0;border-radius: 50%;box-shadow: star(100);animation: moveUp 10s linear infinite;
}
.layer1::after {content: '';position: inherit;width: inherit;height: inherit;border-radius: inherit;box-shadow: inherit;left: 0;top: 100vh;
}

⑤循环多层
$n: 5;
$duration: 400s;
$count: 1000;
@for $i from 1 through $n {$duration: floor($duration / 2);$count: floor($count / 2);.layer#{$i} {position: fixed;width: #{$i}px;height: #{$i}px;left: 0;top: 0;border-radius: 50%;box-shadow: star($count);animation: moveUp $duration linear infinite;}.layer#{$i}::after {content: '';position: inherit;width: inherit;height: inherit;border-radius: inherit;box-shadow: inherit;left: 0;top: 100vh;}
}

(3)完整代码

body {padding: 0;margin: 0;width: 100%;height: 100vh;background-color: #10141A;
}.title {font-size: 40px;background: linear-gradient(to top, #000 0%, #fff 100%);-webkit-background-clip: text;background-clip: text;-webkit-text-fill-color: transparent;color: transparent;position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);
}@function star($n) {$result: '#{random(100)}vw #{random(100)}vh 0 #fff';@for $i from 2 through $n {$result: '#{$result},#{random(100)}vw #{random(100)}vh 0 #fff'}@return unquote($result);
}$n: 5;
$duration: 400s;
$count: 1000;
@for $i from 1 through $n {$duration: floor($duration / 2);$count: floor($count / 2);.layer#{$i} {position: fixed;width: #{$i}px;height: #{$i}px;left: 0;top: 0;border-radius: 50%;box-shadow: star($count);animation: moveUp $duration linear infinite;}.layer#{$i}::after {content: '';position: inherit;width: inherit;height: inherit;border-radius: inherit;box-shadow: inherit;left: 0;top: 100vh;}
}@keyframes moveUp {to {transform: translateY((-100vh));}
}

相关文章:

js 动画库、2048核心逻辑、面试题add[1][2][3]+4

1、js 动画库 web animation api &#xff08;1&#xff09;初始化代码 hmtl、css 部分 初始化全局背景黑色初始化黄色小球 js 部分 监听全局点击事件创建并添加元素 class"pointer" 的 div 标签 设置 left、top 位置监听动画结束事件&#xff0c;移除该元素 定位小…...

华为OD机试真题——书籍叠放(2025B卷:200分)Java/python/JavaScript/C/C++/GO最佳实现

2025 B卷 200分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…...

PyTorch-Transforms的使用(二)

对图像进行处理 安装open cv ctrlP 看用法 ToTensor的使用 常见的Transforms 归一化的图片 两个长度为三的数组&#xff0c;分别表示三个通道的平均值和标准差 Resize&#xff08;&#xff09; Compose&#xff08;&#xff09; 合并执行功能&#xff0c;输入进去一个列表&a…...

Pytorch知识点2

Pytorch知识点 1、官方教程2、张量&#x1f9f1; 0、数组概念&#x1f9f1; 1. 创建张量&#x1f4d0; 2. 张量形状与维度&#x1f522; 3. 张量数据类型➗ 4. 张量的数学与逻辑操作&#x1f504; 5. 张量的就地操作&#x1f4e6; 6. 复制张量&#x1f680; 7. 将张量移动到加速…...

Java详解LeetCode 热题 100(23):LeetCode 206. 反转链表(Reverse Linked List)详解

文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 反转前后对比2.2 核心思路 3. 解法一&#xff1a;迭代法&#xff08;三指针法&#xff09;3.1 算法思路3.2 详细图解3.3 Java代码实现3.4 代码执行过程演示3.5 执行结果示例3.6 优化版本&#xff08;简化代码&#xff09;…...

StarRocks部署方案详解:从单机到分布式集群

#### 一、引言 StarRocks&#xff08;原名DorisDB&#xff09;是一款高性能的MPP&#xff08;大规模并行处理&#xff09;分析型数据库&#xff0c;支持实时查询、高并发和复杂分析场景。其基于列式存储和向量化执行引擎的设计&#xff0c;使其在大数据OLAP领域表现优异。本文…...

AWS API Gateway 配置WAF(中国区)

问题 需要给AWS API Gateway配置WAF。 AWS WAF设置 打开AWS WAF首页&#xff0c;开始创建和配置WAF&#xff0c;如下图&#xff1a; 设置web acl名称&#xff0c;然后开始添加aws相关资源&#xff0c;如下图&#xff1a; 选择资源类型&#xff0c;但是&#xff0c;我这里出…...

【前端面经】百度一面

写在前面&#xff1a;面经只是记录博主遇到的题目。每题的答案在编写文档的时候已经有问过deepseek&#xff0c;它只是一种比较普世的答案&#xff0c;要学得深入还是靠自己 Q&#xff1a; <html><style>.a {background-color: red;width: 200px;height: 100px;}…...

嵌入式学习笔记 - freeRTOS 动态创建任务跟静态创建任务的区别,以及内存回收问题

‌FreeRTOS动态创建任务和静态创建任务各有优缺点&#xff0c;选择哪种方式取决于具体的应用场景和需求。‌ 一 动态创建任务 ‌优点‌&#xff1a; ‌灵活性高‌&#xff1a;动态任务在运行时通过pvPortMalloc()动态分配内存&#xff0c;系统自动管理栈和任务控制块&#xf…...

[免费]微信小程序网上花店系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序网上花店系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序网上花店系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

如何给老旧 iOS App 添加安全保护?用 Ipa Guard 对 IPA 文件混淆加固实录

在大多数安全讨论中&#xff0c;我们习惯关注新项目的安全性&#xff0c;从代码结构、API 设计、用户认证机制出发&#xff0c;构建完善的防护体系。但现实是&#xff0c;很多开发者都在维护一些年久失修的老项目——技术架构老旧、团队成员流失、源码混乱甚至缺失。 我最近接…...

C#语音录制:使用NAudio库实现语音录制功能详解

C#语音录制&#xff1a;使用NAudio库实现语音录制功能详解 在音频处理领域&#xff0c;C# 凭借其强大的生态系统和丰富的类库&#xff0c;为开发者提供了便捷的开发工具。NAudio 库就是其中一款用于音频处理的优秀开源库&#xff0c;它支持多种音频格式和音频设备操作。今天&a…...

[蓝桥杯]缩位求和

缩位求和 题目描述 在电子计算机普及以前&#xff0c;人们经常用一个粗略的方法来验算四则运算是否正确。 比如&#xff1a;248153720248153720 把乘数和被乘数分别逐位求和&#xff0c;如果是多位数再逐位求和&#xff0c;直到是 1 位数&#xff0c;得 24814>14524814…...

MySQ-8.42 MGR 组复制部署及详解

目录 1 MGR要求 2 操作系统信息和软件版本 3 集群架构图 4 MySQL MGR 主库部署步骤 1 MGR要求 InnoDB 存储引擎 表上必须存在主键或唯一非空索引 MGR可允许的最大节点9个 2 操作系统信息和软件版本 rootu24-mysql-mgr-42:~# cat /etc/issue Ubuntu 24.04.2 LTS \n \l mysql…...

css使用scoped之后样式失效问题

项目中的vue代码原本用的style标签来写css&#xff0c;现在想改成<style langscss scoped>&#xff0c;但是改完之后发现样式不对&#xff1a; 原来是&#xff1a; 将style改成scoped之后变成了&#xff1a;检查发现是之前定义的一些变量无法被识别&#xff0c;导致这些样…...

【NLP】将 LangChain 与模型上下文协议 (MCP) 结合使用

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…...

使用NMEA Tools生成GPS轨迹图

前言 在现代科技快速发展的时代&#xff0c;GPS定位技术已经广泛应用于各种领域&#xff0c;如导航、物流、运动追踪等。为了获取和分析GPS数据&#xff0c;我们常常需要使用一些专业的工具。本文将详细介绍如何使用一款名为“NMEA Tools”的APK应用&#xff0c;结合GPSVisual…...

1. pytorch手写数字预测

1. pytorch手写数字预测 1.背景2.准备数据集2.定义模型3.dataloader和训练4.训练模型5.测试模型6.保存模型 1.背景 因为自身的研究方向是多模态目标跟踪&#xff0c;突然对其他的视觉方向产生了兴趣&#xff0c;所以心血来潮的回到最经典的视觉任务手写数字预测上来&#xff0…...

vs中添加三方库的流程

在Visual Studio&#xff08;VS&#xff09;中添加第三方库&#xff08;如OpenCV、PCL等&#xff09;的流程可以分为以下几个步骤&#xff1a;安装库、配置项目、编写代码。以下是详细的步骤说明&#xff1a; 1. 安装第三方库 首先&#xff0c;需要下载并安装所需的第三方库。…...

JAVASE面相对象进阶之static

JavaSE 面向对象进阶之 static 一、static 的核心作用 static 是 Java 中用于修饰成员&#xff08;属性/方法&#xff09;的关键字&#xff0c;作用是让成员与类直接关联&#xff0c;而非依赖对象存在。 二、static 修饰属性&#xff08;静态变量&#xff09; 特点&#xf…...

深入解析 Redis Cluster 架构与实现(一)

#作者&#xff1a;stackofumbrella 文章目录 Redis Cluster特点Redis Cluster与其它集群模式的区别集群目标性能hash tagsMutli-key操作Cluster Bus安全写入&#xff08;write safety&#xff09;集群节点的属性集群拓扑节点间handshake重定向与reshardingMOVED重定向ASK重定向…...

(12)java+ selenium->元素定位大法之By_link_text

1.简介 本章节介绍元素定位中的link_text,顾名思义是通过链接定位的(官方说法:超链接文本定位)。什么是link_text呢,就是我们在任何一个网页上都可以看到有一个或者多个链接,上面有一个文字描述,点击这个文字,就可以跳转到其他页面。这个就是link_Text。 注意:link_t…...

数据库MySQL集群MGR

一、MGR原理 一、基本定义 MGR&#xff08;MySQL Group Replication&#xff09; 是 MySQL 官方推出的一种高可用、高可靠的数据库集群解决方案&#xff0c;基于分布式系统理论&#xff08;如 Paxos 协议变种&#xff09;实现&#xff0c;主要用于构建强一致性的主从复制集群…...

Ubuntu22.04 安装 ROS2 Humble

ROS2 Documentation: Humble Ubuntu 22.04 对应的 ROS 2 版本是 ROS 2 Humble Hawksbill (LTS)。 1.设置系统区域 确保区域设置支持UTF-8 sudo apt update && sudo apt install locales sudo locale-gen en_US en_US.UTF-8 sudo update-locale LC_ALLen_US.UTF-8 L…...

Spring Boot,注解,@RestController

RestController 是 Spring MVC 中用于创建 RESTful Web 服务的核心注解。 RestController 核心知识点 REST 作用: RestController 是一个方便的组合注解&#xff0c;它结合了 Controller 和 ResponseBody 两个注解。 Controller: 将类标记为一个控制器&#xff0c;使其能够处理…...

C++中新式类型转换static_cast、const_cast、dynamic_cast、reinterpret_cast

C中新式类型转换static_cast、const_cast、dynamic_cast、reinterpret_cast 在C中&#xff0c;新式类型转换&#xff08;也称为强制类型转换&#xff09;是C标准引入的一种更安全、更明确的类型转换方式&#xff0c;用以替代C语言风格的类型转换。C提供了四种新式类型转换操作…...

AXI 协议补充(二)

axi协议存在slave 和master 之间的数据交互,在ahb ,axi-stream 高速接口 ,叠加大位宽代码逻辑中,往往有时序问题,valid 和ready 的组合电路中的问题引发的时序问题较多。 本文根据axi 协议和现有解决反压造成的时序问题的方法做一个详细的科普。 1. 解决时序问题的方法:…...

Linux 基础指令入门指南:解锁命令行的实用密码

文章目录 引言&#xff1a;Linux 下基本指令常用选项ls 指令pwd 命令cd 指令touch 指令mkdir 指令rmdir 指令 && rm 指令man 指令cp 指令mv 指令cat 指令more 指令less 指令head 指令tail 指令date 指令cal 指令find 指令按文件名搜索按文件大小搜索按修改时间搜索按文…...

标准精读:2025 《可信数据空间 技术架构》【附全文阅读】

《可信数据空间 技术架构》规范了可信数据空间的技术架构,明确其作为国家数据基础设施的定位,以数字合约和使用控制技术为核心,涵盖功能架构(含服务平台与接入连接器的身份管理、目录管理、数字合约管理等功能)、业务流程(登记、发现、创建空间及数据流通利用)及安全要求…...

山东大学软件学院项目实训-基于大模型的模拟面试系统-面试官和面试记录的分享功能(2)

本文记录在发布文章时&#xff0c;可以添加自己创建的面试官和面试记录到文章中这一功能的实现。 前端 首先是在原本的界面的底部添加了两个多选框&#xff08;后期需要美化调整&#xff09; 实现的代码&#xff1a; <el-col style"margin-top: 1rem;"><e…...