Web图形学与Web可视化
# Web图形学与Web可视化
# Canvas与webGL
Web图形学
- 2D图形
- html + css
- Canvas: 使用js来绘制2D图像
- svg:可缩放矢量图形使用直线,曲线,等几何图形来生成图像
- 3D图形
- WebGL:Web 3D/2D 图像API
Web图形学应用
- 2D应用
- Echarts图表 (opens new window)
- heighCharts
- 3D应用
# SVG
可缩放矢量图形(Scalable Vector Graphics,SVG), SVG 格式提供的是矢量图,这意味着它的图像能够被无限放大而不失真或降低质量。
<svg>:SVG的根元素,用于定义SVG文档的开始和结束。
<rect>:绘制矩形的元素,可以通过指定位置、宽度和高度来定义矩形的形状。
<circle>:绘制圆形的元素,可以通过指定圆心坐标和半径来定义圆的形状。
<ellipse>:绘制椭圆的元素,可以通过指定中心点坐标、水平和垂直半径来定义椭圆的形状。
<line>:绘制直线的元素,可以通过指定起始点和结束点的坐标来定义直线的形状。
<polyline>:绘制折线的元素,可以通过指定一系列连接的点坐标来定义折线的形状。
<polygon>:绘制多边形的元素,可以通过指定一系列连接的点坐标来定义多边形的形状。
<path>:绘制路径的元素,可以通过指定一系列路径指令和参数来定义复杂的形状,如直线段、曲线、弧
<text>:用于在SVG中呈现文本的元素,可以指定文本内容、位置、字体样式等属性。
<g>:用于创建分组的元素,可以将多个元素组合在一起,并对整个组应用变换、样式等属性。
路径命令:
M:移动到指定点(绝对坐标)
m:移动到指定点(相对坐标)
L:绘制直线到指定点(绝对坐标)
l:绘制直线到指定点(相对坐标)
H:绘制水平线(绝对坐标)
h:绘制水平线(相对坐标)
V:绘制垂直线(绝对坐标)
v:绘制垂直线(相对坐标)
C:绘制三次⻉塞尔曲线(绝对坐标)
c:绘制三次⻉塞尔曲线(相对坐标)
S:平滑的三次⻉塞尔曲线(绝对坐标)
s:平滑的三次⻉塞尔曲线(相对坐标)
Q:绘制二次⻉塞尔曲线(绝对坐标)
q:绘制二次⻉塞尔曲线(相对坐标)
T:平滑的二次⻉塞尔曲线(绝对坐标)
t:平滑的二次⻉塞尔曲线(相对坐标)
A:绘制椭圆弧(绝对坐标)
a:绘制椭圆弧(相对坐标)
Z:关闭路径
# Canvas
Canvas API 提供了一个通过JavaScript 和 HTML的 <canvas> 元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。
CanvasRenderingContext2D (opens new window)
fillStyle: 设置图形的填充颜色或样式。
strokeStyle: 设置图形的边框颜色或样式。
fillRect(x, y, width, height): 绘制一个填充的矩形。
strokeRect(x, y, width, height): 绘制一个矩形的边框。
clearRect(x, y, width, height): 清除指定矩形区域内的像素,使其变为透明。
beginPath(): 开始绘制路径。
moveTo(x, y): 将绘图游标移动到指定的坐标点。
lineTo(x, y): 绘制一条直线,从当前点到指定的坐标点。
closePath(): 封闭路径,连接起点和终点。
fill(): 填充当前路径的内部区域。
stroke(): 绘制当前路径的边框。
arc(x, y, radius, startAngle, endAngle, clockwise): 绘制弧或圆。
drawImage(image, x, y): 在指定位置绘制图像。
translate(x, y): 平移坐标系统的原点。
scale(scaleX, scaleY): 缩放坐标系统。
rotate(angle): 旋转坐标系统。
绘制矩形
绘制圆弧与圆形
绘制路径曲线
贝塞尔曲线
# Echarts
Q: Echarts是如何通过canvas绘制图表?
Echarts在canvas绘制库 ZRender的上层进行继续封装。
Echarts > Zrender > canvas
# 3D图形:WebGL
OpenGL是一种跨平台的图形编程接口,用于渲染2D和3D图形。它提供了一系列函数和命令,用于操作图形硬件以进行高性能的图形渲染。
WebGL(Web 图形库)是一个 JavaScript API,可在任何兼容的 Web 浏览器中渲染高性能的交互式3D 和 2D 图形,而无需使用插件。WebGL 通过引入一个与 OpenGL ES 2.0 非常一致的 API 来做到这一点,该 API 可以在 HTML5 <canvas> 元素中使用。这种一致性使 API 可以利用用戶设备提供的硬件图形加速。
Q: openGL和WebGL是什么关系?
WebGL(Web Graphics Library)则是一种基于OpenGL的Web标准,用于在Web浏览器中进行图形渲染。WebGL是HTML5的一部分,使用JavaScript API与浏览器的图形引擎进行交互,将OpenGL的功能暴露给Web开发者。
WebGL使用OpenGL ES 2.0着色器语言来编写顶点着色器和片段着色器。
WebGL核心概念
- 顶点缓冲区(VertexBuffer):顶点缓冲区是存储顶点数据的内存缓冲区,用于描述3D模型的几何形状。开发者将顶点数据加载到顶点缓冲区中,然后通过WebGL绘制指令使用这些顶点进行渲染。
- 着色器(Shader):着色器是一段在GPU上执行的程序,用于控制WebGL渲染管线中的不同阶段。WebGL使用顶点着色器(VertexShader)和片元着色器(FragmentShader)来处理顶点和像素的计算和渲染。
- 纹理(Texture):纹理是应用到3D模型表面的图像或图案。WebGL支持加载和使用纹理,可以将纹理映射到几何形状的表面,实现真实感和细节。
WebGL 核心API:
gl.POINTSgl.LINES-gl.T.TRIANGLES
只能会点、线、三⻆形,所有的图形都是通过 这三种基础图形构成。
# ThreeJS
ThreeJS提供了更简单、高级的方式来创建和渲染3D场景。提供了许多有用的功能和工具,如相机、灯光、几何体、纹理映射、动画等,使开发者能够更轻松地构建复杂的3D场景。
https://threejs.org/docs/index.html (opens new window)
ThreeJS: 对WebGL的封装 > WebGL: OpenGL在web场景下的封装 > OpenGL
在react下方便快速地使用封装的ThreeJS
# Web可视化
Web可视化
- 数据大屏
- 数据平台
- 地图
- 更多..
可视化(Visualization)是利用计算机图形学和图像处理技术,将数据转换成图形或图像在屏幕上显示出来,并进行交互处理的理论、方法和技术。
主流web可视化库:
- Echarts55kstars
- D3.js106kstars
- HighCharts11kstarts
- Chartjs5kstars
- AntV2kstars
# Echarts应用及原理
- 手写Echart折线图:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas手写chart折线图</title>
<style>
#myCanvas {
border: 1px solid red;
}
</style>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// 设置画布尺寸
canvas.width = 500;
canvas.height = 300;
const option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line'
}
]
};
const xAxisData = option.xAxis.data;
const yAxisData = option.series[0].data;
const maxValue = Math.max(...yAxisData);
const minValue = 0;
const dataLength = xAxisData.length;
// 绘制坐标轴
const padding = 40; // 坐标轴与画布边界的距离
const xAxisHeight = canvas.height - padding; // x 轴的高度
const yAxisWidth = canvas.width - padding; // y 轴的宽度
// 绘制 x 轴
ctx.beginPath();
ctx.moveTo(padding, xAxisHeight);
ctx.lineTo(yAxisWidth, xAxisHeight);
ctx.strokeStyle = 'black';
ctx.stroke();
// 绘制 y 轴
ctx.beginPath();
ctx.moveTo(padding, xAxisHeight);
ctx.lineTo(padding, padding);
ctx.strokeStyle = 'black';
ctx.stroke();
// 绘制 x 轴刻度线和刻度标签
const xLabelInterval = (yAxisWidth - padding) / (dataLength - 1); // x 轴刻度标签间隔
for (let i = 0; i < dataLength; i++) {
const x = padding + i * xLabelInterval;
const y = xAxisHeight + 15; // 将刻度标签下移
// 绘制刻度线
ctx.beginPath();
ctx.moveTo(x, xAxisHeight);
ctx.lineTo(x, xAxisHeight - 5);
ctx.strokeStyle = 'black';
ctx.stroke();
// 绘制刻度标签
ctx.fillStyle = 'black';
ctx.textAlign = 'center';
ctx.fillText(xAxisData[i], x, y);
}
// 绘制 y 轴刻度线和刻度标签
const yLabelCount = 5; // y 轴刻度标签数量
const yLabelInterval = (xAxisHeight - padding) / yLabelCount; // y 轴刻度标签间隔
const yValueInterval = maxValue / yLabelCount; // y 轴刻度值间隔
for (let i = 0; i <= yLabelCount; i++) {
const x = padding - 5;
const y = xAxisHeight - i * yLabelInterval;
// 绘制刻度线
ctx.beginPath();
ctx.moveTo(padding, y);
ctx.lineTo(padding + 5, y);
ctx.strokeStyle = 'black';
ctx.stroke();
// 绘制刻度标签
ctx.fillStyle = 'black';
ctx.textAlign = 'right';
ctx.fillText((i * yValueInterval).toString(), x, y + 5);
}
// 绘制折线图
const xInterval = (yAxisWidth - padding) / (dataLength - 1); // x 轴坐标间隔
const yRatio = (xAxisHeight - padding) / maxValue; // y 轴数值比例
ctx.beginPath();
ctx.moveTo(padding, xAxisHeight - (yAxisData[0] - minValue) * yRatio);
for (let i = 0; i < dataLength; i++) {
const x = padding + i * xInterval;
const y = xAxisHeight - (yAxisData[i] - minValue) * yRatio;
// 绘制折线
ctx.lineTo(x, y);
ctx.strokeStyle = 'blue';
ctx.lineWidth = 2;
}
ctx.stroke();
</script>
</html>
# 备注
- svg 与 canvas 有什么区别?
- 标签上的
width和height:- svg: css上的宽高会覆盖写svg标签上的宽高;
- canvas: css上的宽高也覆盖写标签上的宽高,一旦canvas标签的width和height确定了,再通过css修改宽高,图像会被拉伸
canvas是标量图,绘制最小的点位是一个像素点;svg绘制的最小单位是svg内部的元素;
问题:canvas的width和height与css中的width、height是什么关系?会冲突么?
Canvas和SVG的区别是什么?如何技术选型?
| 操作对象 | 渲染方式 | 适用场景 | |
|---|---|---|---|
| canvas | 像素 | 像素 | 性能优先,自由度优先SVG |
| SVG | XML矢量描述标签 | DOM | 缩放还原度优先 |
- 如何优化Echarts性能?
思考:
- 开源:
- Web worker => 纯逻辑计算,并且字符串 => 放弃
- 切换渲染引擎 => svg or canvas => svg元素 or canvas像素点
- 内存泄漏 => 及时销毁echarts实例
- 节流:
- 采样 Samping:采样率为10%,即每10个数据里面选择一个数据进行展示
- 数据懒加载:
渲染性能
- 降低渲染压力
- 降低渲染数据量
- 数据懒加载: 懒加载、异步加载
- 采样率控制
- 数据项处理:过滤,缓存
- 引入缩放、视图切换
- 降低渲染动画
- 组件懒加载
- Canvas Or Svg
- 降低渲染数据量
- 提供渲染性能
- WebWorker
- 切换页面销毁echarts实例