03 d3动画

03 动画

3.pdf
2-数据可视化编程2023-基础-第二节.mp4
3-数据可视化编程2023-动画-第三节.mp4
!8-数据可视化编程2023-层次-第八节.mp4

动画概览

  • 动画 D3.js的Transition模块:
    • d3.transition与时长控制
    • 动画的过度(Ease)
    • 动画的同步
    • 动画的继承
    • 动画的插值
    • 动画的循环
  • 基于动画绘制动态散点图
    • 数据的清洗与预处理
  • 基于动画绘制追逐柱状图
  • Tip:数字的格式化
  • Tip:图元的起始状态

D3-transition

  • 引用D3.js文档:‘Selection-like’ interface。
  • D3的selections后调用transition,将后续的.attr(…)加以动画效果。
  • selections.transition().duration(ms).attr(type, value)
    • ms是毫秒,故1000表示动画持续1秒钟。
    • e.g., d3.select(“#my_rect”).transition().duration(2000).attr(“width”, “400”);
    • 即用两秒钟(2000毫秒)的时间把选择图元的宽变成400。
  • 同d3.selections,支持链式调用
1
d3.select(‘#my_rect’).transition().duration(1000).attr(…).attr(…).attr(…) 

只有transition()后面的.attr(…)会有动画效果。

1
d3.select(‘#my_rect’).attr(…).transition().duration(1000).attr(…)

第一个attr没有动画效果,第二个有动画效果
动画Demo d3动画特效针对svg标签

1
2
3
4
5
6
7
8
<svg width="960" height="400" id="mainsvg" class="svgs" style='display: block; margin: 0 auto;'>
<rect id="my_rect" x="10" y="200" width="200" height="30" stroke="black" fill="#69b3a2" stroke-width="1" />
</svg>
<script>
d3.select("#my_rect")
.transition().duration(2000)
.attr("width", "400");
</script>

动画的过渡

ease,动画过渡的方式。
通过链式调用的方式作用在transition对象后:

1
d3.select("#my_rect").transition().duration(2000).ease(d3.easeLinear).attr(…) 
  • D3提供多种Ease函数供选择:
    • d3.easeCubic 默认,从加速到减速
    • d3.easeLinear 线性
    • d3.easeElastic 弹射
    • d3.easeBounce 弹跳
    • d3.easeExp 突变

动画的同步

通常,可视化作品都需要多个图元执行多个动画…
‘显式’定义Transition对象:
let transition = d3.transition().duration(ms)
并让其与多个图元共享,即所有绑定的图元会同步播放动画:

1
2
rects.transition(transition).attr(…).attr(…) 
circles.transition(transition).attr(…).attr(…)

等待一个transition全部相关的图元执行完毕:
await transition.end();
异步函数会不等待调用执行完直接进入下一条语句
await会强制等待异步函数执行完毕
JavaScript异步:
async:将函数转换成异步函数,即把返回值包装成一个Promise对象
await:等待异步函数执行结束

动画的继承

动画的插值

动画的循环

基本原则

基本原则

实例

d3

d3

d3

D3.js(Data-Driven Documents)是一个基于数据操作文档的JavaScript库,广泛应用于数据可视化领域。它结合了HTML、SVG和CSS等Web标准技术,能够通过数据驱动的方式操作DOM元素,创建动态和交互式的可视化效果。
以下是D3.js中一些常用的方法及其功能介绍:

1. 选择元素

D3.js通过选择器来操作DOM元素,常用的选择器包括:

  • d3.select():选择单个元素。
    1
    var svg = d3.select("svg");
  • d3.selectAll():选择多个元素。
    1
    var circles = d3.selectAll("circle");

2. 数据绑定

D3.js的核心功能之一是数据绑定,通过data()方法将数据与DOM元素关联起来。

  • 绑定数据
    1
    2
    3
    4
    5
    6
    7
    8
    var data = [10, 20, 30, 40, 50];
    var circles = svg.selectAll("circle")
    .data(data)
    .enter()
    .append("circle")
    .attr("cx", (d, i) => i * 50 + 25)
    .attr("cy", 25)
    .attr("r", d => d);
  • 动态数据处理:使用enter()update()exit()来处理动态数据。

3. 设置属性和样式

D3.js提供了丰富的接口来设置DOM元素的属性和样式。

  • 设置属性
    1
    2
    3
    circles.attr("cx", (d, i) => i * 50 + 25)
    .attr("cy", 25)
    .attr("r", d => d);
  • 设置样式
    1
    2
    circles.style("fill", "blue")
    .style("stroke", "black");

4. 事件监听

D3.js支持强大的事件处理功能,通过on()方法可以监听各种事件。

  • 基本事件监听
    1
    2
    3
    4
    5
    6
    circles.on("mouseover", function(event, d) {
    d3.select(this).style("fill", "red");
    })
    .on("mouseout", function(event, d) {
    d3.select(this).style("fill", "blue");
    });

5. 动画和过渡

D3.js提供了丰富的动画和过渡效果,通过transition()方法可以实现元素的动态变化。

  • 基本过渡
    1
    2
    3
    4
    circles.transition()
    .duration(1000)
    .attr("r", d => d * 2)
    .style("fill", "green");

6. 加载外部数据

D3.js可以方便地加载和处理外部数据源,如CSV、JSON等格式。

  • 加载CSV数据
    1
    2
    3
    d3.csv("data.csv").then(function(data) {
    // 处理数据
    });
  • 加载JSON数据
    1
    2
    3
    d3.json("data.json").then(function(data) {
    // 处理数据
    });

7. 力导向图

D3.js的d3-force模块提供了一种基于物理模拟的布局方式,广泛应用于社交网络分析、知识图谱等场景。

  • 核心物理力
    • 向心力(d3.forceCenter:使节点聚集到画布中心。
      1
      2
      const simulation = d3.forceSimulation(nodes)
      .force("center", d3.forceCenter(width / 2, height / 2));
    • 碰撞检测(d3.forceCollide:防止节点重叠。
      1
      2
      const simulation = d3.forceSimulation(nodes)
      .force("collide", d3.forceCollide().radius(d => d.size + 5));
    • 弹簧力(d3.forceLink:模拟节点间的连接关系。
      1
      2
      const simulation = d3.forceSimulation(nodes)
      .force("link", d3.forceLink(links).distance(100).strength(0.5));

8. 常见应用场景

D3.js广泛应用于以下领域:

  • 数据报表:创建柱状图、折线图、饼图等。
  • 交互式可视化:支持用户交互和数据筛选。
  • 地理信息可视化:绘制地图和地理数据。
    D3.js的强大之处在于其灵活的数据绑定机制和对DOM元素的高效操作能力,能够轻松处理动态变化的数据,并实时更新界面。

svg

在JavaScript中操作SVG(可缩放矢量图形)是一种常见的数据可视化和图形绘制方法。SVG是一种基于XML的标记语言,用于描述二维矢量图形。通过JavaScript,可以动态地创建、修改和操作SVG元素,实现复杂的图形效果和交互功能。以下将详细介绍如何使用JavaScript操作SVG,包括基础概念、常用方法和一些实用示例。

1. SVG基础

SVG是一种基于XML的矢量图形格式,具有以下特点:

  • 矢量图形:SVG图形由几何形状(如圆形、矩形、路径等)组成,可以无限放大而不失真。
  • 可交互性:SVG元素可以绑定JavaScript事件,实现交互功能。
  • 可嵌入性:SVG可以直接嵌入HTML文档中,也可以作为独立文件引用。
    SVG的基本结构如下:
1
2
3
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<!-- 在这里定义图形元素 -->
</svg>

2. 使用JavaScript操作SVG

2.1 创建SVG元素

可以通过JavaScript动态创建SVG元素,并将其添加到HTML文档中。

1
2
3
4
5
6
7
// 创建SVG元素
const svgNS = "http://www.w3.org/2000/svg"; // SVG命名空间
const svg = document.createElementNS(svgNS, "svg");
svg.setAttribute("width", "200");
svg.setAttribute("height", "200");
// 将SVG添加到页面
document.body.appendChild(svg);

2.2 添加图形元素

SVG支持多种图形元素,如矩形(<rect>)、圆形(<circle>)、椭圆(<ellipse>)、路径(<path>)等。
示例:添加一个矩形

1
2
3
4
5
6
7
const rect = document.createElementNS(svgNS, "rect");
rect.setAttribute("x", "10");
rect.setAttribute("y", "10");
rect.setAttribute("width", "100");
rect.setAttribute("height", "50");
rect.setAttribute("fill", "blue");
svg.appendChild(rect);

示例:添加一个圆形

1
2
3
4
5
6
const circle = document.createElementNS(svgNS, "circle");
circle.setAttribute("cx", "100");
circle.setAttribute("cy", "100");
circle.setAttribute("r", "50");
circle.setAttribute("fill", "red");
svg.appendChild(circle);

示例:添加一个路径

1
2
3
4
5
const path = document.createElementNS(svgNS, "path");
path.setAttribute("d", "M10,10 L150,10 L100,100 Z");
path.setAttribute("stroke", "black");
path.setAttribute("fill", "none");
svg.appendChild(path);

2.3 修改SVG元素

可以通过JavaScript动态修改SVG元素的属性。
示例:修改矩形的颜色

1
rect.setAttribute("fill", "green");

示例:动态调整圆形的半径

1
circle.setAttribute("r", "70");

2.4 添加交互功能

SVG元素可以绑定JavaScript事件,实现交互功能。
示例:鼠标悬停时改变颜色

1
2
3
4
5
6
circle.addEventListener("mouseover", () => {
circle.setAttribute("fill", "yellow");
});
circle.addEventListener("mouseout", () => {
circle.setAttribute("fill", "red");
});

示例:点击时移动矩形

1
2
3
4
rect.addEventListener("click", () => {
const x = parseInt(rect.getAttribute("x")) + 10;
rect.setAttribute("x", x);
});

3. 使用D3.js操作SVG

D3.js是一个基于SVG的可视化库,它提供了更简洁的API来操作SVG元素。以下是D3.js操作SVG的常用方法。

3.1 创建SVG容器

1
2
3
4
const svg = d3.select("body")
.append("svg")
.attr("width", 200)
.attr("height", 200);

3.2 添加图形元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 添加矩形
svg.append("rect")
.attr("x", 10)
.attr("y", 10)
.attr("width", 100)
.attr("height", 50)
.attr("fill", "blue");
// 添加圆形
svg.append("circle")
.attr("cx", 100)
.attr("cy", 100)
.attr("r", 50)
.attr("fill", "red");
// 添加路径
svg.append("path")
.attr("d", "M10,10 L150,10 L100,100 Z")
.attr("stroke", "black")
.attr("fill", "none");

3.3 动态绑定数据

D3.js的核心功能之一是数据绑定。通过data()方法可以将数据绑定到SVG元素上。

1
2
3
4
5
6
7
8
9
const data = [10, 20, 30, 40, 50];
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", (d, i) => i * 30 + 20)
.attr("cy", 50)
.attr("r", d => d)
.attr("fill", "purple");

3.4 添加交互功能

D3.js也支持事件监听,可以为SVG元素添加交互功能。

1
2
3
4
5
6
7
svg.selectAll("circle")
.on("mouseover", function(event, d) {
d3.select(this).attr("fill", "yellow");
})
.on("mouseout", function(event, d) {
d3.select(this).attr("fill", "purple");
});

4. SVG与Canvas的对比

SVG和Canvas是两种常见的图形绘制技术,各有优缺点:

  • SVG
    • 优点:矢量图形,可无限放大不失真;支持CSS和JavaScript交互;可嵌入HTML。
    • 缺点:复杂图形时性能可能下降;不适合像素级操作。
  • Canvas
    • 优点:像素级操作,适合复杂图形和游戏;性能较好。
    • 缺点:位图,放大后会失真;不支持DOM操作。

5. 实用示例:动态柱状图

以下是一个使用D3.js和SVG绘制动态柱状图的示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG Bar Chart</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<script>
const data = [10, 20, 30, 40, 50];
const width = 400;
const height = 300;
const svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
const bars = svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", (d, i) => i * 50 + 20)
.attr("y", d => height - d * 5)
.attr("width", 40)
.attr("height", d => d * 5)
.attr("fill", "steelblue");
bars.on("mouseover", function(event, d) {
d3.select(this).attr("fill", "orange");
})
.on("mouseout", function(event, d) {
d3.select(this).attr("fill", "steelblue");
});
</script>
</body>
</html>

6. 总结

SVG是一种强大的矢量图形格式,可以通过JavaScript和D3.js进行动态操作。它适用于数据可视化、图表绘制和交互式图形设计。通过掌握SVG的基本元素和操作方法,你可以创建出复杂而美观的图形效果。

canvas2d

canvas2d

常用 API

Canvas 2D 是 HTML5 提供的一种绘图 API,用于在网页中创建和操作 2D 图形。它通过 <canvas> 元素提供一个绘图区域,开发者可以使用 JavaScript 来绘制图形、文本、图像等内容。以下是 Canvas 2D 的一些常用 API 和功能,以及示例代码。

1. 初始化 Canvas

首先需要在 HTML 中创建一个 <canvas> 元素,并通过 JavaScript 获取其上下文。

1
<canvas id="myCanvas" width="500" height="500"></canvas>
1
2
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d'); // 获取 2D 绘图上下文

2. 绘制基本图形

绘制矩形

  • 填充矩形
    1
    2
    ctx.fillStyle = 'red'; // 设置填充颜色
    ctx.fillRect(10, 10, 100, 100); // (x, y, width, height)
  • 绘制矩形边框
    1
    2
    ctx.strokeStyle = 'blue'; // 设置边框颜色
    ctx.strokeRect(130, 10, 100, 100); // (x, y, width, height)

绘制圆形

  • 填充圆形
    1
    2
    3
    4
    ctx.beginPath(); // 开始路径
    ctx.fillStyle = 'green';
    ctx.arc(250, 60, 50, 0, Math.PI * 2); // (x, y, radius, startAngle, endAngle)
    ctx.fill(); // 填充路径
  • 绘制圆形边框
    1
    2
    3
    4
    ctx.beginPath();
    ctx.strokeStyle = 'purple';
    ctx.arc(350, 60, 50, 0, Math.PI * 2);
    ctx.stroke(); // 描边路径

绘制线条

1
2
3
4
5
ctx.beginPath();
ctx.moveTo(10, 200); // 移动到起点
ctx.lineTo(150, 200); // 绘制到终点
ctx.strokeStyle = 'orange';
ctx.stroke();

绘制贝塞尔曲线

  • 二次贝塞尔曲线
    1
    2
    3
    4
    5
    ctx.beginPath();
    ctx.moveTo(10, 300);
    ctx.quadraticCurveTo(100, 150, 200, 300); // (cpX, cpY, endX, endY)
    ctx.strokeStyle = 'black';
    ctx.stroke();
  • 三次贝塞尔曲线
    1
    2
    3
    4
    5
    ctx.beginPath();
    ctx.moveTo(250, 300);
    ctx.bezierCurveTo(300, 100, 400, 100, 450, 300); // (cp1X, cp1Y, cp2X, cp2Y, endX, endY)
    ctx.strokeStyle = 'brown';
    ctx.stroke();

3. 绘制文本

绘制文本

1
2
3
ctx.font = '20px Arial'; // 设置字体样式
ctx.fillStyle = 'red';
ctx.fillText('Hello Canvas!', 10, 400); // (text, x, y)

绘制文本边框

1
2
3
ctx.font = '20px Arial';
ctx.strokeStyle = 'blue';
ctx.strokeText('Hello Canvas!', 10, 450);

4. 图像绘制

将图片绘制到 Canvas 上。

1
2
3
4
5
const img = new Image(); // 创建图片对象
img.src = 'path/to/image.jpg'; // 设置图片路径
img.onload = function() {
ctx.drawImage(img, 10, 500, 100, 100); // (image, x, y, width, height)
};

5. 设置样式和颜色

填充样式

1
ctx.fillStyle = 'rgba(255, 0, 0, 0.5)'; // RGBA 颜色

边框样式

1
ctx.strokeStyle = '#00ff00'; // 十六进制颜色

线宽

1
ctx.lineWidth = 5; // 设置线条宽度

线帽和线连接

1
2
ctx.lineCap = 'round'; // 线帽类型:butt、round、square
ctx.lineJoin = 'bevel'; // 线连接类型:bevel、round、miter

6. 路径操作

保存和恢复路径状态

1
2
3
4
ctx.save(); // 保存当前状态
ctx.fillStyle = 'blue';
ctx.fillRect(10, 10, 100, 100);
ctx.restore(); // 恢复之前的状态

裁剪路径

1
2
3
4
5
ctx.beginPath();
ctx.rect(10, 10, 100, 100); // 定义裁剪区域
ctx.clip(); // 裁剪
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 200, 200); // 只在裁剪区域内绘制

7. 变换操作

平移

1
2
ctx.translate(100, 100); // (x, y)
ctx.fillRect(0, 0, 100, 100); // 相对于平移后的坐标

旋转

1
2
3
ctx.translate(200, 200); // 移动到旋转中心
ctx.rotate(Math.PI / 4); // 旋转角度(弧度)
ctx.fillRect(-50, -50, 100, 100); // 绘制矩形

缩放

1
2
ctx.scale(2, 2); // (xScale, yScale)
ctx.fillRect(10, 10, 50, 50); // 缩放后的绘制

8. 图像数据操作

获取图像数据

1
2
const imageData = ctx.getImageData(10, 10, 100, 100); // (x, y, width, height)
console.log(imageData.data); // 获取像素数据

修改图像数据

1
2
3
4
5
const imageData = ctx.getImageData(10, 10, 100, 100);
for (let i = 0; i < imageData.data.length; i += 4) {
imageData.data[i] = 255; // 修改红色通道
}
ctx.putImageData(imageData, 10, 10); // 将修改后的数据绘制回 Canvas

9. 清除画布

1
ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除指定区域

10. 绘制复杂图形

绘制多边形

1
2
3
4
5
6
7
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.lineTo(200, 100);
ctx.lineTo(150, 200);
ctx.closePath(); // 闭合路径
ctx.fillStyle = 'yellow';
ctx.fill();

绘制星形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function drawStar(ctx, x, y, spikes, outerRadius, innerRadius) {
let rot = Math.PI / 2 * 3;
let x0 = x;
let y0 = y;
let angle = Math.PI / spikes;
ctx.beginPath();
ctx.moveTo(x0, y0 - outerRadius);
for (let i = 0; i < spikes; i++) {
x0 = x + Math.cos(rot) * outerRadius;
y0 = y + Math.sin(rot) * outerRadius;
ctx.lineTo(x0, y0);
rot += angle;
x0 = x + Math.cos(rot) * innerRadius;
y0 = y + Math.sin(rot) * innerRadius;
ctx.lineTo(x0, y0);
rot += angle;
}
ctx.lineTo(x, y - outerRadius);
ctx.closePath();
ctx.fill();
}
drawStar(ctx, 300, 300, 5, 50, 20);

11. 事件交互

鼠标事件

1
2
3
4
5
6
7
8
canvas.addEventListener('click', function(event) {
const rect = canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
ctx.beginPath();
ctx.arc(x, y, 10, 0, Math.PI * 2);
ctx.fill();
});

12. 动画

简单的动画

function animate() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

SVG

SVG

api

SVG(Scalable Vector Graphics)是一种基于 XML 的标记语言,用于描述二维矢量图形。SVG 图形可以通过 HTML 直接嵌入网页中,也可以通过 JavaScript 动态生成和操作。SVG 提供了丰富的图形绘制功能,包括形状、路径、文本、图像等,并且支持动画和交互。
以下是 SVG 的一些常用 API 和功能,以及示例代码。

1. 基本形状

SVG 提供了多种基本形状的元素,如矩形、圆形、椭圆、线条、多边形等。

矩形(<rect>

1
<rect x="10" y="10" width="100" height="100" fill="red" />

圆形(<circle>

1
<circle cx="150" cy="150" r="50" fill="blue" />

椭圆(<ellipse>

1
<ellipse cx="250" cy="150" rx="50" ry="30" fill="green" />

线条(<line>

1
<line x1="10" y1="10" x2="200" y2="200" stroke="black" stroke-width="2" />

多边形(<polygon>

1
<polygon points="100,10 40,180 190,60 10,60 160,180" fill="orange" />

多段线(<polyline>

1
<polyline points="50,10 100,50 150,10" stroke="purple" stroke-width="3" fill="none" />

2. 路径(<path>

路径是 SVG 中最强大的图形元素,可以通过一系列指令绘制复杂的形状。

1
<path d="M10 10 L100 10 L100 100 L10 100 Z" fill="yellow" />
  • M:移动到指定点(Move to)
  • L:绘制直线(Line to)
  • Z:闭合路径(Close path)

3. 文本(<text>

用于在 SVG 中添加文本内容。

1
<text x="50" y="50" font-family="Arial" font-size="20" fill="black">Hello SVG!</text>

4. 图像(<image>

可以将外部图像嵌入 SVG 中。

1
<image href="path/to/image.jpg" x="10" y="10" width="200" height="200" />

5. 样式和属性

SVG 元素可以通过内联样式或 CSS 类来设置样式。

内联样式

1
<rect x="10" y="10" width="100" height="100" style="fill: red; stroke: black; stroke-width: 2;" />

CSS 类

1
2
3
4
5
6
7
8
<style>
.my-rect {
fill: blue;
stroke: green;
stroke-width: 3;
}
</style>
<rect x="10" y="10" width="100" height="100" class="my-rect" />

6. 变换(<g>transform

可以使用 <g> 元素对多个图形进行分组,并应用变换。

1
2
3
4
<g transform="translate(50, 50)">
<rect x="10" y="10" width="100" height="100" fill="red" />
<circle cx="150" cy="150" r="50" fill="blue" />
</g>

常见的变换类型:

  • translate(x, y):平移
  • rotate(angle, cx, cy):旋转
  • scale(sx, sy):缩放
  • skewX(angle):水平倾斜
  • skewY(angle):垂直倾斜

7. 动画(<animate><animateTransform>

SVG 提供了内置的动画支持。

简单动画

1
2
3
<rect x="10" y="10" width="100" height="100" fill="red">
<animate attributeName="x" from="10" to="200" dur="2s" repeatCount="indefinite" />
</rect>

路径动画

1
2
3
4
5
6
<circle cx="50" cy="50" r="20" fill="blue">
<animateMotion dur="5s" repeatCount="indefinite">
<mpath href="#myPath" />
</animateMotion>
</circle>
<path id="myPath" d="M10,10 C100,100 200,100 200,10" stroke="black" fill="none" />

8. 事件处理

SVG 元素支持常见的 DOM 事件,如 clickmouseover 等。

1
<rect x="10" y="10" width="100" height="100" fill="red" onclick="alert('Clicked!')" />

9. 创建 SVG 画布

SVG 可以通过 HTML 嵌入,也可以通过 JavaScript 动态创建。

HTML 嵌入

1
2
3
<svg width="500" height="500" xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="100" height="100" fill="red" />
</svg>

JavaScript 动态创建

1
2
3
4
5
6
7
8
9
10
11
12
const svgNS = "http://www.w3.org/2000/svg";
const svg = document.createElementNS(svgNS, "svg");
svg.setAttribute("width", "500");
svg.setAttribute("height", "500");
const rect = document.createElementNS(svgNS, "rect");
rect.setAttribute("x", "10");
rect.setAttribute("y", "10");
rect.setAttribute("width", "100");
rect.setAttribute("height", "100");
rect.setAttribute("fill", "red");
svg.appendChild(rect);
document.body.appendChild(svg);

10. 嵌入 SVG 文件

SVG 文件可以通过 <img><object> 标签嵌入网页中。

1
<img src="path/to/image.svg" alt="SVG Image" />

或者:

1
<object type="image/svg+xml" data="path/to/image.svg"></object>

11. SVG 与 JavaScript 交互

可以通过 JavaScript 操作 SVG 元素。

修改属性

1
2
const rect = document.querySelector("rect");
rect.setAttribute("fill", "blue");

添加事件监听器

1
2
3
4
const rect = document.querySelector("rect");
rect.addEventListener("click", function() {
alert("Rectangle clicked!");
});

12. 响应式 SVG

SVG 可以通过设置 viewBox 属性实现响应式设计。

1
2
3
<svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="100" height="100" fill="red" />
</svg>

viewBox 定义了 SVG 的内部坐标系统,SVG 会根据容器的大小自动缩放内容。

13. 复杂图形

SVG 可以通过组合多个图形元素来创建复杂的图形。

示例:绘制国旗

1
2
3
4
5
6
<svg width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="300" height="200" fill="white" />
<rect x="0" y="0" width="300" height="66.67" fill="red" />
<rect x="0" y="66.67" width="300" height="66.67" fill="white" />
<rect x="0" y="133.34" width="300" height="66.67" fill="red" />
</svg>

14. SVG 的优势

  • 矢量图形:无损缩放,适合高分辨率显示。
  • 可交互:支持事件监听和动态操作。
  • **可嵌

canvas和svg

canvas和svg

在数据可视化中,Canvas 和 SVG 是两种常用的图形渲染技术,它们各有特点和适用场景:

Canvas

  1. 像素基础
    • Canvas 是以像素为单位的位图(bitmap)技术,这意味着它在图像的每个像素上进行渲染。
    • 它适合于需要大量像素操作的场景,如游戏开发、图片编辑等。
  2. 性能
    • Canvas 在处理大量像素数据时性能较好,尤其是在绘制复杂图形和动画时。
    • 它通常比 SVG 快,因为它直接在浏览器的渲染引擎中绘制。
  3. 跨浏览器兼容性
    • Canvas 有很好的跨浏览器兼容性,几乎所有现代浏览器都原生支持 <canvas> 元素。
  4. 交互性
    • Canvas 提供了丰富的事件处理接口,可以很容易地实现用户交互。
  5. 可缩放性
    • Canvas 绘制的内容在缩放时可能会出现像素化,因为它是基于像素的。
  6. 内容操作
    • Canvas 允许开发者通过 JavaScript 直接操作像素数据,这为图像处理提供了强大的灵活性。

SVG

  1. 矢量基础
    • SVG(Scalable Vector Graphics)是基于 XML 的矢量图形格式,这意味着它使用路径和形状来描述图像。
    • 它适合于需要清晰、可缩放图形的场景,如图标、字体和插图。
  2. 性能
    • SVG 在渲染简单图形和文本时性能较好,尤其是在需要频繁重绘或动画的场景中。
  3. 跨浏览器兼容性
    • SVG 同样具有良好的跨浏览器兼容性,但在一些老旧浏览器中可能需要额外的库来支持。
  4. 交互性
    • SVG 元素可以很容易地绑定事件,实现丰富的交互效果。
  5. 可缩放性
    • SVG 图形在缩放时保持清晰,因为它们是基于路径和形状的。
  6. 内容操作
    • SVG 内容可以通过 CSS 和 JavaScript 进行操作,这使得动态修改图形属性变得简单。
  7. 文本支持
    • SVG 原生支持文本,可以很容易地在图形中添加和样式化文本。
  8. 文件大小
    • 对于复杂的图形,SVG 文件可能比 Canvas 绘制的位图大,因为 SVG 需要存储路径数据。

总结

  • Canvas 更适合于需要大量像素操作、游戏开发、实时图形处理和动画的场景。
  • SVG 更适合于需要清晰、可缩放图形、文本支持和简单图形的场景。
    在数据可视化中,选择 Canvas 还是 SVG 取决于具体的应用需求,包括图形的复杂性、交互性、性能要求和可缩放性。有时,两者也可以结合使用,以发挥各自的优势。

Canvas 和 SVG 的详细对比

在选择可视化图表的渲染方式时,通常会面临使用 Canvas 还是 SVG 的选择。两者各有优缺点,适用于不同的场景。以下是对 Canvas 和 SVG 的详细对比,帮助你做出合适的选择。

1. SVG(Scalable Vector Graphics)

优点

  • 矢量图形:SVG 是矢量图形,可以无限放大而不失真,适合需要高分辨率和高质量显示的场景。
  • DOM 兼容:SVG 元素是 DOM 元素的一部分,可以使用 JavaScript 和 CSS 进行操作,支持事件监听和样式控制。
  • 可访问性:SVG 元素可以添加 titledesc 等标签,提高图表的可访问性。
  • 文本处理:SVG 对文本的支持非常好,可以方便地添加和格式化文本内容。
  • 动画:SVG 支持 CSS 动画和 SMIL(Synchronized Multimedia Integration Language)动画,可以实现复杂的动画效果。

缺点

  • 性能问题:SVG 的性能随着元素数量的增加而下降,特别是当图表包含大量元素时,渲染和交互性能会受到影响。
  • 浏览器兼容性:虽然现代浏览器对 SVG 的支持很好,但在一些旧版本的浏览器中可能会遇到兼容性问题。

2. Canvas(HTML5 Canvas)

优点

  • 高性能:Canvas 是一个位图(bitmap)画布,适合处理大量图形和复杂的动画,性能优越,特别是在需要频繁重绘的场景中。
  • 像素级控制:Canvas 提供了像素级的控制,可以实现复杂的图形效果,如图像处理、游戏开发等。
  • 兼容性:Canvas 在现代浏览器中的兼容性很好,支持较广泛的浏览器版本。

缺点

  • 固定分辨率:Canvas 是位图,放大后会失真,不适合需要高分辨率和高质量显示的场景。
  • DOM 交互:Canvas 不是 DOM 元素,不支持事件监听和样式控制,需要手动处理事件和样式。
  • 可访问性:Canvas 的可访问性较差,需要额外的工作来实现类似 SVG 的可访问性功能。

3. 选择建议

使用 SVG 的场景

  • 需要高分辨率和高质量显示:如打印、高清屏幕显示等。
  • 图表元素数量较少:如简单的柱状图、折线图等。
  • 需要良好的可访问性和文本处理:如需要添加描述性文本和提高图表的可访问性。
  • 需要复杂的动画效果:如渐变、路径动画等。

使用 Canvas 的场景

  • 需要处理大量图形和复杂动画:如实时数据可视化、游戏开发等。
  • 需要高性能和频繁重绘:如动态图表、实时数据更新等。
  • 需要像素级控制:如图像处理、自定义图形效果等。

4. 实例

SVG 示例

1
2
3
4
<svg width="400" height="400">
<rect x="50" y="50" width="100" height="100" fill="blue" />
<text x="60" y="100" fill="white">Hello, SVG!</text>
</svg>

Canvas 示例

1
2
3
4
5
6
7
8
9
10
<canvas id="myCanvas" width="400" height="400"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'blue';
ctx.fillRect(50, 50, 100, 100);
ctx.fillStyle = 'white';
ctx.font = '16px Arial';
ctx.fillText('Hello, Canvas!', 60, 100);
</script>

5. 结论

选择 Canvas 还是 SVG 取决于你的具体需求。如果需要高分辨率、良好的可访问性和复杂的动画效果,SVG 是更好的选择。如果需要处理大量图形、频繁重绘和像素级控制,Canvas 更为合适。在实际项目中,也可以根据不同的需求混合使用 Canvas 和 SVG,以达到最佳效果。

echarts常见问题

Echarts常见问题

  • 滚动轴
  • 时间轴
  • 饼图和柱状图切换
  • 交互

d3 和 echarts

在选择数据可视化工具时,D3.js 和 ECharts 各有适用场景。以下是根据不同需求推荐使用 D3.js 而非 ECharts 的关键场景:

1. 需要高度定制化或非标准图表

  • D3:直接操作 SVG/Canvas,可自由设计任意图形(如复杂网络图、地理热力图的特殊投影、动态粒子效果)。
  • ECharts:依赖预设图表类型,对非常规图表(如树状图之外的层级结构)支持有限。

2. 需要底层控制与极致的性能优化

  • D3:手动控制渲染细节(如渐变动画、元素级交互)、优化大数据量(百万级)渲染性能。
  • ECharts:封装了通用优化策略,但深度定制性能时可能受限。

3. 动态数据与复杂交互需求

  • D3:适合实时流数据(如高频金融仪表盘)、自定义过渡动画(如路径插值)、复杂交互逻辑(如多视图联动)。
  • ECharts:动态更新需依赖 API,复杂交互需通过配置实现,灵活性较低。

4. 学术或研究场景

  • D3:常用于论文中的创新可视化(如特定算法的交互展示),直接控制图形元素更易实现学术需求。
  • ECharts:更适用于商业报表或标准化展示。

5. 与其他库深度集成

  • D3:可无缝结合 React/Vue/Angular(如通过 d3-selection 操作虚拟 DOM)、集成物理引擎(如力导向图的动态模拟)。
  • ECharts:需依赖官方提供的框架绑定(如 echarts-for-react),扩展性较弱。

何时用 ECharts?

  • 快速开发:预置图表类型(如地图、3D 图表)开箱即用。
  • 团队技术栈较浅:配置式 API 学习成本低,中文文档友好。
  • 标准化需求:如后台数据看板、常见业务报表。

总结:选择工具的核心因素

因素 D3.js ECharts
开发速度 慢(需手动构建) 快(配置化)
灵活性 极高 中等
学习曲线 陡峭(需 SVG/JS) 平缓
大数据性能 需手动优化 内置优化策略
适用场景 创新研究、定制产品 标准化业务需求
建议:如果项目需要突破常规图表限制或对交互有极致要求,选择 D3;若追求效率且需求标准化,ECharts 是更优解。

字体

字体

Web字体是一种允许网页设计师在网页中使用自定义字体的技术,而无需依赖用户设备上已安装的字体。通过Web字体,网页可以实现更加丰富的视觉效果,同时确保在不同设备和浏览器上的一致性。以下是关于Web字体的详细介绍:

1. Web字体的基本概念

Web字体通过CSS的@font-face规则将字体文件嵌入到网页中。这意味着无论用户的设备是否安装了该字体,网页都能正确显示设计者指定的字体样式。

2. 使用Web字体的方法

2.1 使用@font-face规则

@font-face是CSS中用于定义自定义字体的关键规则。它需要指定字体的名称和字体文件的路径。例如:

1
2
3
4
5
6
7
8
@font-face {
font-family: 'CustomFont';
src: url('path/to/font.woff2') format('woff2'),
url('path/to/font.woff') format('woff');
}
body {
font-family: 'CustomFont', sans-serif;
}

在上述代码中,font-family定义了字体的名称,src属性指定了字体文件的路径和格式。

2.2 字体文件格式

常见的Web字体文件格式包括:

  • WOFF2:现代浏览器广泛支持的高效压缩格式。
  • WOFF:较早的Web字体格式,兼容性较好。
  • TTF/OTF:TrueType和OpenType字体格式,适用于某些旧浏览器。
  • EOT:嵌入式开放类型字体,主要用于旧版本的IE浏览器。
  • SVG:用于早期iOS设备的字体格式。
    为了确保最佳兼容性,通常需要提供多种格式的字体文件。

2.3 使用第三方字体服务

除了自定义字体,还可以使用第三方字体服务,如Google Fonts、Adobe Fonts和国内的Windfonts。这些服务提供了丰富的字体库,并且会自动处理字体格式和加载优化。

3. Web字体的优势与劣势

3.1 优势

  • 视觉一致性:确保网页在所有设备上都能以设计者期望的字体显示。
  • 设计灵活性:提供丰富的字体选择,支持多种设计风格。
  • 生僻字支持:可以用于显示生僻字或特殊字符。

3.2 劣势

  • 性能影响:字体文件可能会增加网页的加载时间,尤其是字体文件较大时。
  • 版权问题:使用Web字体时需要确保字体的授权许可。

4. 字体加载优化

为了减少字体加载对性能的影响,可以采用以下策略:

  • 异步加载:通过JavaScript动态加载字体,避免阻塞页面渲染。
  • 字体子集化:仅加载网页中实际使用的字符子集。
  • 预加载:使用<link rel="preload">提前加载字体文件。

5. 国内Web字体服务

国内首个类Google Fonts的中文字体服务平台是Windfonts,它提供了开源免费的中文字体服务,支持自托管和多种应用场景。

6. 注意事项

  • 字体授权:使用Web字体时,必须确保字体的授权许可,避免侵权。
  • 性能优化:尽量选择轻量级的字体文件,并减少字体文件的加载范围。
    通过合理使用Web字体技术,可以显著提升网页的视觉效果和用户体验,但需要注意性能和版权问题。

必背

必背

  • js
    • 对象
    • 闭包
    • 原型链
    • 运算
  • CSS
  • Vue
    • 响应式数据
    • 组件间通信
    • 生命周期函数
    • vuex
  • 网络
    • http
  • 工程
    • 兼容性
  • 综合
    • 安全
    • 性能
    • 跨域
    • 登录鉴权
  • 详细比较antdesign 和 element puls,并且用表格展示出来
    - vue2 与 vue3
    - vite 与 webpack
    - vue 与其他前端框架
    - pinie 与 vuex
    - defineProperty 和 proxy
    - antdesign 和 element puls

技术栈

技术栈

更新时间:2025-01-02 7:42

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
const {createButton} = app.plugins.plugins["buttons"]

const currentFolder = dv.current().file.folder
const groups = dv.pages(`"${currentFolder}"`).sort(p => p.file.name, 'esc').groupBy(p => p.file.folder)
//不想展示的文件夹
const folderArr = ["MOD","后端","python"]
let result = [];
for (let group of groups) {
if (group.key!="Codes" && folderArr.filter(f => group.key.includes(f)).length == 0) {
const pages = dv.pages(`"${group.key}"`).sort(p => p.file.name, 'esc')
for (let page of pages) {
const content =await dv.io.load(page.file.link)
const headings = content.match(/^##+ .*$/gm);
let item2 = "--"
if(headings){
item2 = headings.map(function(heading){
const regex = /(^#+)(\s?)/g;
const replacedText = heading.replace(regex, function(match, p1, p2) {
return `${p2}`;
//if (p1.length == 2) {
// return `${p2}`;
// } else{
// return `${' '.repeat(p1.length-2)}🔸${p2}`;
// }
});
return replacedText
})
}
result.push([group.key.replace("Codes/",""),`${page.file.name}`,item2]);
}
}
}
dv.table(["文件","一级目录","二级目录"], result);
const table = dv.markdownList(["文件","一级目录","二级目录"], result)
async function copyPageUrl(text) {
try {
await navigator.clipboard.writeText(text);
console.log('Page URL copied to clipboard');
} catch (err) {
console.error('Failed to copy: ', err);
}
}
function replaceMarkdownHeadings(text) {
const regex = /(^|\n)(#{1,6})/g;
const replacer = (match, p1, p2) => {
const hashCount = p2.length;
return p1 + ' '.repeat(hashCount) + '-'.repeat(hashCount);
};
return text.replace(regex, replacer);
}
dv.paragraph(createButton({
app,
el: this.container,
args: {
name: '复制 MD table ',
class:'tiny'
},
clickOverride: {
click: copyPageUrl,
params: [table]
}
}))