前言:在现实生活中,看书的时候,在文本的下面画个波浪线,画个横线,是很常见的行为。本篇文章使用D3动画来实现一个给文本绘制下划线的效果,可以暂停绘制,继续绘制,重新绘制,还可以支持自定义的曲线,不过自定义曲线就需要你自己书写曲线函数,接下来就来看一下如何实现吧!
可惜文章里没办法上传视频,只能截图给大家看了。
我上传了视频资源效果演示

在这里插入图片描述
GitHub - d3/d3: Bring data to life with SVG, Canvas and HTML. 📊📈🎉

D3(或D3.js)是一个用于可视化数据的免费开源JavaScript库。D3不是传统意义上的图表库。它没有“图表”的概念。当您使用D3可视化数据时,您可以组合各种基元。

官网还推荐了一个高级姐妹库:

D3中的直方图可能需要50行代码,而Plot可以在一行中完成!Plot的简洁而富有表现力的API让您更专注于分析和可视化数据,而不是Web开发。

Observable Plot

D3名字含义为data-driven documents,数据驱动的文档,其中的选择和过渡模块会操作DOM,但是大部分模块是对数据进行操作。D3还可以与React、Vue和Svelte等Web框架搭配使用。

D3用于定制可视化。D3适合对于可视化效果要求比较高的场景,如果只是渲染普通的图表,建议使用Plot。

D3用于动态可视化。D3可以实现数据绑定,实现动态、交互式可视化。

下面的网站是D3示例网站:

Recent notebooks by D3

D3可以用来绘制图表和动画,功能非常的丰富,可玩性很强,今天先来分享一个动画的效果

D3是结合SVG一起使用的

d3-ease | D3 by Observable

D3 中的API都采用链式调用的方式,非常的方便进行连续的操作。

一、动画实现

(一)路径的绘制

d3.path() 用来绘制路径

d3.path

构建一个路径对象 path,通过路径对象上面的API来绘制路径

  • path.moveTo(x, y) 移动画笔到特定点,不会进行绘制,用于波的起始位置的设定。
  • path.lineTo(x, y) 从当前点到特定点绘制直线,用于执行绘制过程。

path.lineTo() 是绘制直线的,如果函数是一条直线,那么调用一次即可。如果要绘制波函数,则需要在无数个微小时间间隔中调用path.lineTo() 以组成具有弧度的曲线。以正弦波为例,

const yCenter = 0; // 波的y轴的坐标,相对于svg元素,控制下划线和文字的垂直距离
// 正弦波浪线
const waveAmplitude = 1.5; // 振幅
const waveLength = 8; // 波长,表示一个周期中波的传播距离
const pointsPerCycle = 10; // 每个周期点数 点数越多,曲线越平滑,但计算量也越大
const totalCycles = width / waveLength; // 总周期数
const steps = Math.floor(totalCycles * pointsPerCycle) // 总步数path.moveTo(0, yCenter);
for (let i = 0; i <= steps; i++) {const x = (i / steps) * width;const waveY = yCenter + Math.sin((x / waveLength) * Math.PI * 2) * waveAmplitude;path.lineTo(x, waveY);
}

(二)创建SVG元素

考虑到一段文字可能出现换行,所以需要动态创建SVG元素数组。通过遍历文字,计算当前文字和上一个文字的位置差异,如果两个文字离得比较远,则代表出现了换行。换行的时候就需要往下划线数组中增加一行。

然后需要给SVG元素添加波浪线

const svg = d3.select(svgEl); // 获取SVG元素
const wavePath = g.append("path").attr("class", `wavy-path-${index}`).attr("d", wavePathString)  // 调用 wavePathString 生成 path.attr("stroke", props.wavyLineColor).attr("stroke-width", waveStyle.strokeWidth).attr("fill", waveStyle.fill).attr("stroke-linecap", waveStyle.strokeLinecap).attr("stroke-linejoin", waveStyle.strokeLinejoin);

(三)动画控制

由于SVG元素可能有多个,所以动画也需要维护一个数组。

const animationProgress = ref([]);
animationProgress.value.push({element: wavePath.node(), // 波浪线元素originalPathLength: pathLength, // 原始路径长度originalDuration: lineDuration, // 原始持续时间pausedOffset: pathLength, // 暂停偏移量lineIndex: index // 行索引
});

数组中存放所有的SVG元素的相关信息,通过下面的API,对SVG元素遍历进行操作

1、d3.select(selector)

选中元素目标元素,返回目标元素对象 element,链式进行动画。参数为选择器的字符串。

2、element.interrupt()

暂停动画。

3、element.transition()

这是D3动画系统的基础,用于创建一个过渡效果。它会返回一个过渡对象 transition,可以在该对象上链式调用其他过渡方法。

d3.selectAll("rect").transition() // 开始过渡
4、transition.duration()

设置动画持续时间(毫秒)。持续时间越长,动画越慢。

.duration(1000) // 1秒动画

延时时间是一个需要计算的点,因为在多行绘制的情况下,除了第一行,下面的行都需要等待上面的行的波浪线绘制完成之后再进行动画。

5、transition.delay()
.delay(function(d, i) {return i * 100; // 每个元素延迟100ms
})
6、transition.ease()

设置缓动函数,(如 <font style="color:rgb(199, 37, 78);background-color:rgb(249, 242, 244);">d3.easeLinear</font><font style="color:rgb(199, 37, 78);background-color:rgb(249, 242, 244);">d3.easeBounce</font>等),官网给出了不同速度下波的函数图像,斜率表示速度。

element.transition().duration(duration).ease(d3.easeLinear) // 匀速
7、transition.on()

监听函数

  • <font style="color:rgb(224, 70, 0);background-color:rgba(142, 150, 170, 0.14);">start</font> - 动画开始
  • <font style="color:rgb(224, 70, 0);background-color:rgba(142, 150, 170, 0.14);">end</font> - 动画结束
  • <font style="color:rgb(224, 70, 0);background-color:rgba(142, 150, 170, 0.14);">interrupt</font> - 动画暂停
  • <font style="color:rgb(224, 70, 0);background-color:rgba(142, 150, 170, 0.14);">cancel</font> - 动画取消

二、组件介绍

写了一个Vue3组件,实现在文档中动态绘制波浪线的效果,可以动态控制波浪线绘制的动画效果的暂停和播放。接收参数:

  • 文本 text 字符串
  • 文本样式 style 对象
  • 波浪线颜色 wavyLineColor 字符串
  • 波浪线类型 waveType sin | solid | zigzag | custom
  • customFunction自定义曲线的函数 返回值是一个函数,比如 Math.sin(),会根据这个函数按照步长输入 x 得到 y,然后绘制曲线

方法:

  • action 执行动画
  • pause 暂停动画
  • resume 继续播放暂停的动画

使用示例

 <WavyText ref="wavyText1"text="D3.js 的反反复复凤飞飞反反复复方法方法反反复复反反复复凤飞飞发发发发发发发发发发发反反复复凤飞飞反反复复方法方法方法反反复复凤飞飞反反复复发发发发发发发发发发发发发发发都Vue 3 作为渐进式 JavaScript 框架的代表,凭借其出色的响应式系统和组合式 API":style="{ fontSize: '18px', color: '#2c3e50' }" wavyLineColor="#42b883" waveType="sin" />

三、开源代码

wavy-text-d3

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单表查询-分页提前获取数据

1、 问题 以下的例子如何优化呢&#xff1f; SELECT * FROM(SELECT INNER_TABLE.*, ROWNUM OUTER_TABLE_ROWNUM FROM (SELECT t1.* FROM ( SELECT * FROM T1 ) t1 WHERE 1 1 ORDER BY T1.TTIME DESC)INNER_TABLE ) OUTER_TABLE WHERE OUTER_TABLE_ROWNUM<25AND OUTER_TA…

Oracle触发器:数据世界的“隐形守护者“

今天&#xff0c;我想和大家聊一个在Oracle数据库领域既强大又神秘的话题——触发器&#xff08;Trigger&#xff09;​。在座的各位可能都写过SQL语句&#xff0c;做过表结构设计&#xff0c;甚至用过存储过程&#xff0c;但有很多人对触发器的态度可能是"既爱又怕"…

Python桌面版数独游戏(三版)-增加难易度模式

数独游戏难度模式解析 在数独游戏中&#xff0c;难度通常由已知数字&#xff08;提示数&#xff09;的数量决定。难度越高&#xff0c;已知数字越少&#xff0c;玩家需要推理的步骤越多。以下是不同模式下的算法区别和核心代码解析。 文章目录数独游戏难度模式解析1. **难度模…

k8s查看某个pod的svc

在 Kubernetes 中&#xff0c;要查看与特定 Pod 相关的 Service&#xff0c;可以通过以下方法&#xff1a;#### 方法一&#xff1a;通过标签匹配1. **获取 Pod 的标签**bashkubectl get pod <pod-name> --show-labels输出示例&#xff1a;NAME READY STATUS RESTARTS AGE…

通俗易懂卷积神经网络(CNN)指南

本文用直观类比和可视化方法&#xff0c;帮你彻底理解CNN的工作原理&#xff0c;无需深厚数学基础也能掌握计算机视觉的核心技术。卷积神经网络&#xff08;CNN&#xff09;是深度学习中革命性的架构&#xff0c;它彻底改变了计算机"看世界"的方式。本文将用最直观的…

AV1平滑缓冲区

对于解码的每一帧视频数据&#xff0c;解码器都必须从缓冲池中找到一个尚未被使用的帧缓冲区插槽来存储解码后的数据。分配的帧缓冲区插槽用于临时保存解码过程中生成的帧数据&#xff0c;直到它们被用于显示或进一步的处理。函数get_free_buffer的作用是在缓冲池中搜索尚未被分…

Python并发编程:突破GIL枷锁,高效利用多核CPU

解密concurrent.futures的双引擎&#xff1a;线程池与进程池的明智选择在Python并发编程领域&#xff0c;concurrent.futures模块堪称利器&#xff0c;但如何正确使用其两大核心组件——ThreadPoolExecutor和ProcessPoolExecutor&#xff0c;却让许多开发者困惑。本文将深入剖析…

在Windows Server 2012 R2中安装与配置IIS服务并部署mssql靶机教程

在Windows Server 2012 R2中安装与配置IIS服务全指南 IIS&#xff08;Internet Information Services&#xff09;作为Windows系统自带的Web服务组件&#xff0c;在企业级Web部署、内网服务搭建等场景中应用广泛。本文将详细介绍在Windows Server 2012 R2中安装IIS服务的完整流…

C#/.NET/.NET Core技术前沿周刊 | 第 47 期(2025年7.14-7.20)

前言 C#/.NET/.NET Core技术前沿周刊&#xff0c;你的每周技术指南针&#xff01;记录、追踪C#/.NET/.NET Core领域、生态的每周最新、最实用、最有价值的技术文章、社区动态、优质项目和学习资源等。让你时刻站在技术前沿&#xff0c;助力技术成长与视野拓宽。 欢迎投稿、推荐…

一.AD域与DFS集群-AD域安装

目录 1.网络规划 2.主域控安装 3.辅助域控安装 1.网络规划 服务器名称IP地址DNS名称主域控192.168.188.2pdc.test.cn辅助域控192.168.188.3bdc.test.cnDFS1192.168.188.4dfs1.test.cnDFS2192.168.188.5dfs2.test.cn 服务器系统版本为windows server 2022 2.主域控安装 第一…

BUUCTF在线评测-练习场-WebCTF习题[BSidesCF 2020]Had a bad day1-flag获取、解析

解题思路打开靶场&#xff0c;作者对我们进行了亲切的关怀老规矩查看源码、抓包并没有发现什么猫腻点下面两个按钮会出现猫猫狗狗的图片&#xff0c;此时我们发现url多了个 参数category那么比较明显就是提示我们是任意文件包含、任意文件读取漏洞了找不到任何信息&#xff0c;…

stm32mp157f-dk2安装镜像并且部署qt全流程

在网上看的关于stm32mp157的开发教程太少了&#xff0c;于是乎写一篇踩坑笔记&#xff0c;仅供学习参考 大概流程&#xff1a;在虚拟机通过stm32cubeprogrammer烧录镜像&#xff0c;然后烧录成功之后&#xff0c;给stm32mp157连接网线&#xff0c;使得开发板有ip地址&#xff…

遗像照片尺寸要求及手机制作打印方法

遗像作为寄托哀思的重要载体&#xff0c;其规格和质量都有严格要求。本文将详细介绍遗像照片的标准尺寸规范&#xff0c;并提供使用手机快速制作合规遗像的完整方案。一、遗像照片的标准尺寸要求遗像照片的尺寸主要分为传统黑白遗像和现代彩色遗像两种规格。传统黑白遗像一般采…

适配器模式 (Adapter Pattern)

适配器模式 (Adapter Pattern) 适配器模式是一种结构型设计模式&#xff0c;用于解决两个不兼容接口之间的兼容性问题&#xff0c;充当两个不同接口之间的桥梁。 &#x1f31f; 核心思想转换接口&#xff1a;将一个类的接口转换成客户端期望的另一个接口&#xff0c;使原本不兼…

03-虚幻引擎蓝图类的各父类作用讲解

虚幻引擎&#xff08;Unreal Engine&#xff09;的蓝图系统提供了多种父类&#xff0c;每种父类都有其特定的用途和生命周期。理解这些父类的作用&#xff0c;是高效使用蓝图开发游戏的基础。以下是虚幻引擎中常见蓝图父类的详细讲解&#xff1a;1. Actor 作用&#xff1a;所有…

141 个 LangChain4j Maven 组件分类解析、多场景实战攻略

141 个 LangChain4j Maven 组件分类解析、多场景实战攻略 文章目录 141 个 LangChain4j Maven 组件分类解析、多场景实战攻略 1. 引言 2. LangChain4j 组件分类 2.1. 核心模块 (Core Modules) 2.2. LLM 集成 (LLM Integrations) 2.3. 向量存储集成 (Embedding Store Integratio…

Python可迭代归约函数深度解析:从all到sorted的进阶指南

在Python中&#xff0c;归约函数&#xff08;Reduction Functions&#xff09;是处理可迭代对象的利器。它们通过遍历元素并逐步收敛为单个结果&#xff0c;广泛应用于数据分析、逻辑判断和数值计算等场景。本文将系统梳理这些函数的核心特性、使用技巧及底层逻辑&#xff0c;助…

大带宽服务器都有哪些应用场景?

大带宽服务器凭借着高速的数据传输能力和强大的网络承载能力&#xff0c;通常被企业应用在需要高流量和高并发处理能力的业务场景当中&#xff0c;下面&#xff0c;就让我们共同了解一下大带宽服务器的应用场景吧&#xff01;首先&#xff0c;随着科学技术的快速发展&#xff0…

爬虫实战指南:从定位数据到解析请求的全流程解析

爬虫的本质是什么&#xff1f; 爬虫的本质就是用代码模拟人类在浏览器里的操作&#xff0c;像点击网页、填写表单、提交数据等行为&#xff0c;自动化地进行网页数据的获取和处理。比如&#xff1a; 发送 GET 请求 来请求网页内容&#xff0c;相当于你在浏览器地址栏输入网址…

Sentinel dashboard 添加context-path后无法信息无法上传问题

Sentinel dashboard 添加context-path后无法加载问题 添加server.servlet.context-path/sentinel后可以正常访问&#xff0c;但是客户端启动后信息上报失败。 transport: dashboard: localhost:8858/sentinel 经查阅文档需要加入api-path&#xff0c;但是我配置提示无api-path所…