web渲染可视化相关

Posted by Qz on July 26, 2023

“Yeah It’s on. ”

可视化

前端可视化入门

可视化是通过图形、图像、图表等视觉元素来呈现数据信息概念的过程。它将抽象的、复杂的或大量的数据转化为可视化形式,以便人们能够更直观、更容易地理解和分析。

WebGL

WebGL(Web Graphics Library) 的诞生是为了在 Web 浏览器中实现高性能的 3D 图形渲染。它是基于 OpenGL ES(OpenGL for Embedded Systems)标准的一个 JavaScript API。

WebGL是一种用于在web浏览器中渲染交互式3D图形的Web标准。它是在HTML5和JavaScript技术的基础上开发的,允许开发者在浏览器中使用硬件加速的图形渲染,实现高性能的3D和2D图形效果。WebGL通过在浏览器中运行OpenGL ES API,将3D图形渲染功能带到了Web平台,使用者可以在任何支持WebGL的浏览器中无需安装插件的情况下访问和运行WebGL应用程序。WebGL应用程序通常用于游戏开发、数据可视化、虚拟现实、建筑和工程模拟等领域。

Shader着色器

操作 WebGL 的三维图形 API 本质上其实就是处理着色器 Shader。

Shader(着色器)是计算机图形学中用于描述光照、材质和渲染效果的程序。它是一种在图形渲染管线中执行的小型程序,用于控制图形的绘制和渲染过程。

Shader 着色器通常由两个主要部分组成:顶点着色器(Vertex Shader)和片段着色器(Fragment Shader)。

  • 顶点着色器是在图形渲染管线的顶点处理阶段执行的程序。它接收输入的顶点数据,并对每个顶点进行一系列的计算和变换,如位置变换、法线变换、纹理坐标变换等并输出。
  • 片段着色器是在图形渲染管线的片段处理阶段执行的程序。它接收顶点着色器传递过来的数据,并对每个片段(像素)进行计算。片段着色器通常用于计算光照、纹理采样、颜色插值等操作,并最终确定片段的最终颜色。也就是屏幕的显示效果是它来决定的。

可以使用canvas标签

WebGL可以在canvas标签上进行渲染是因为WebGL的渲染上下文(RenderingContext)会被绑定到canvas元素上。当使用WebGL时,可以通过获取canvas的上下文并进行一系列的WebGL操作,如创建图形对象、定义顶点和片元着色器、设置顶点缓冲区等。

在使用WebGL时,可以通过canvas的上下文调用WebGL API来绘制和渲染复杂的图形,包括3D模型、纹理映射、光照效果等。在canvas标签上进行绘制,可以通过CSS样式对其进行定位、大小和样式的调整,以实现所需的页面布局和美观效果。

WebGL和Canvas的区别

  1. 渲染方式:Canvas使用2D渲染引擎,而WebGL使用3D渲染引擎。Canvas通过绘制2D图形,如矩形、圆形和线条来渲染图像。而WebGL使用OpenGL ES的API来进行3D图形渲染。
  2. 功能和复杂性:WebGL相对于Canvas提供更强大的图形渲染功能。WebGL可以进行复杂的3D图形渲染、纹理映射、光照效果等。而Canvas则主要适用于简单的2D图形渲染,对于复杂的3D渲染需要使用其他库或框架。
  3. 性能:由于WebGL使用了硬件加速和GPU进行图形渲染,相对于Canvas具有更好的性能。特别是对于复杂的图形、动画和大规模数据可视化等场景,WebGL能够提供更流畅的体验。
  4. 学习曲线:相对于Canvas,WebGL对于开发人员来说学习曲线更陡峭。WebGL需要熟悉OpenGL ES的API和图形编程的基本原理。而Canvas则相对简单,只需要了解2D绘图的基本概念和API即可。

因此,选择使用WebGL还是Canvas取决于项目的需求和复杂性。对于简单的2D图形渲染,选择Canvas更加方便和易于上手。而对于复杂的3D场景或需要更高性能的图形渲染,选择WebGL是更好的选择。


Canvas它的绘制过程其实都是在CPU里面完成的,消耗的都是CPU的计算时间,最后产出一帧图像,copy到了显存,让GPU显示就完了。

canvas

绘制

    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
    ctx.strokeStyle = "white"
    ctx.lineWidth = 4;
    ctx.beginPath()
    ctx.moveTo(10, 10)
    ctx.lineTo(300, 600)
    ctx.stroke() // tip: 注意这个,如果没有绘制不生效
    ctx.closePath()

width/height

canvas 元素有两个属性 widthheight,用于定义画布的尺寸。width 定义画布的宽度,height 定义画布的高度。这两个属性需要使用具体的数值来设置,例如 width="500"height="300"

style 属性用于定义元素的样式,包括宽度和高度。它可以接受各种 CSS 值,如像素值、百分比、em 等。通过 style 属性,可以使用 CSS 来定义 canvas 元素的宽度和高度,例如 style="width: 500px; height: 300px;"

两者的区别在于:

  1. widthheight 是 HTML5 中 canvas 元素的特定属性,用于定义画布的尺寸。它们是数值,表示具体的像素值。而 style 是一个通用的属性,可以用于任何元素,用于定义元素的样式。
  2. widthheightcanvas 元素控制画布的大小。通过设置这两个属性,实际的绘图区域会被调整到对应的尺寸。而 style 只是用于定义元素的展示样式,并不会改变元素的实际大小。
  3. 优先级不同:style 属性可以通过 CSS 样式表或内联样式来设置,它的优先级会受到 CSS 规则的影响。而 widthheight 是作为元素属性直接设置的,它们的优先级更高,优先级高于 style 属性的值。

综上所述,widthheight 是用于定义 canvas 元素的实际大小的属性,style 是用于定义元素的样式,其中包括宽度和高度。在设置 canvas 元素的尺寸时,widthheight 的优先级更高,会覆盖 style 属性中的宽度和高度设置。

多次fill覆盖

https://juejin.cn/post/7007691485160144904

在使用 canvas 绘制图形时,遇到了一个问题:在绘制图形时,后面设置的图形样式(颜色、线宽等)覆盖了前面绘制图形的样式。

每次画新线段的路径前,都要用ctx.beginPath()

restore/save

https://juejin.cn/post/6844903879599996942

function draw() {
    //初始的样式(绘制状态)并绘制矩形
    ctx.fillStyle = '#FA6900';
    ctx.shadowOffsetX = 5;
    ctx.shadowOffsetY = 5;
    ctx.shadowBlur    = 4;
    ctx.shadowColor   = 'rgba(204, 204, 204, 0.5)';
    ctx.fillRect(0,0,15,150);
    ctx.save(); //保存上述设置的绘制状态
    
    //重新定义新的绘制状态,并绘制矩形
    ctx.fillStyle = '#E0E4CD';
    ctx.shadowOffsetX = 10;
    ctx.shadowOffsetY = 10;
    ctx.shadowBlur    = 4;
    ctx.shadowColor   = 'rgba(204, 204, 204, 0.5)';
    ctx.fillRect(30,0,30,150);
    
    //绘制完之后,恢复到初始的绘制状态,继续进行绘画。并绘制圆形,并不会恢复初始状态下绘制的矩形。
    ctx.restore();
  	// 绘制圆形
    ctx.beginPath();
    ctx.arc(305, 75, 8, 0, Math.PI*2, true);
    ctx.closePath();
    ctx.fill();
    }

我们发现最后绘制的圆形的填充色和阴影和第一个矩形的保持了一致,这是因为restore之后,使用了初始绘制状态。

离屏渲染

https://developer.mozilla.org/zh-CN/docs/Web/API/OffscreenCanvas

举个例子:

let offscreenCanvas = new OffscreenCanvas(300, 600)
let offscreenCtx = offscreenCanvas.getContext("2d")!
    
//  利用 offscreenCtx 绘制一些东西
// ...
    
let bitmap = offscreenCanvas.transferToImageBitmap()
ctx.drawImage(bitmap, 0, 0); // 在别的 canvas 的 context 上绘制

convertToBlob

let blob = await offscreenCanvas.convertToBlob()

让后我们可以将blob转 url 在页面中显示

const url = URL.createObjectURL(blob)
var img = document.createElement('img');
// 将临时URL分配给图像的src属性
img.src = url;
// 将图像元素添加到DOM中
document.body.appendChild(img);

pixi

https://pixijs.com/

自适应屏幕宽高

  useEffect(()=>{
    const resize = () => {
      location.reload()
    }
    window.addEventListener('resize', resize)
    return () => {
      window.removeEventListener('resize', resize)
    }
  },[])

雪碧图

http://pixijs.huashengweilai.com/guide/start/8.make-sprite-from-a-tileset-sub-image.html#%E9%9B%AA%E7%A2%A7%E5%9B%BE

资源预加载

import * as PIXI from 'pixi.js';

PIXI.Assets.add("down", "/assets/avatar_down.png")
PIXI.Assets.add("up", "/assets/avatar_up.png")
PIXI.Assets.add("left", "/assets/avatar_left.png")
PIXI.Assets.add("right", "/assets/avatar_right.png")

await PIXI.Assets.load(["down", "up", "left", "right"])


// 使用 
const downTexture = PIXI.Texture.from('down');

设置人物位置

https://cloud.tencent.com/developer/article/1900019

人物都是出现在屏幕中央,并且还需要设置 人物的中心为 元素的基点,这样人物缩放和其他操作就以中心为原点,符合视觉习惯。

另外如果会出现有多个人物叠加出现的情况,需要设置一个偏移值 => 是为了保证添加多个人物的时候,不会互相重叠

let addedNum = 0; // 当前人物是添加的第几个
const offsetList = [0, 20, 40];

class Person{
 createPerson(){
    // ...省略创建container 等其他代码
    this.setCenterPosition()
 }
 setCenterPosition(container) {
    const { screen } = this.app;

    // 人物放置在中央,并且有一定的偏差
    container.x = screen.width / 2 + offsetList[addedNum++ % 3];
    container.y = screen.height / 2;

    // 设置人物容器的基点为中心点
    container.pivot.x = container.width / 2;
    container.pivot.y = container.height / 2;
  }
}

D3.js

基于 JavaScript 的可视化编程库,可以帮助开发人员创建交互式数据可视化。D3.js 提供了强大的 SVG 和 CSS 支持,使得用户能够轻松创建高品质的可视化图表。

Three.js

Three.js 是一个基于 JavaScript 的开源 3D 图形库,用于在网页上创建和展示交互式的 3D 图形和动画。它是构建在 WebGL 技术之上的高级抽象层,使得使用 WebGL 更加简单和方便。

WebGPU

WebGPU 是一种新的 Web 标准,用于在 Web 浏览器中进行高性能图形渲染和计算。它旨在提供比 WebGL 更底层、更直接的硬件访问,并且更好地与现代图形 API(如 Vulkan、Metal 和 Direct3D 12)对接。

WebGPU 的设计目标是提供一个跨平台、高性能的图形和计算编程接口,使开发者能够更好地利用 GPU 的计算能力。它为开发者提供了更多的控制权和灵活性,以实现更高效、更复杂的图形渲染和计算任务。