ResizeObserver

76 阅读5分钟

当折叠左侧导航栏的时候,整个视图区会自适应伸缩,需要对echarts图表进行重绘,这是仅对进行resize监听是不够的,因为可视窗口并没有发生改变。这时候需要更细粒度的监听。这时候对图表所在元素的父元素进行监听,实现了针对特定dom的监听,相比传统方法获取元素offset性能更高,因为频繁获取dom offsetwidth会触发重排,耗费浏览器性能容易造成卡顿。

resizeObserver优点 1、按需触发,减少不必要调用 2、回调在微任务队列执行,确保布局计算完成后触发,数据准确性高

使用resizeObserver

const observer = new ResizeObserver(entries => {
  const entry = entries[0];
  console.log('元素宽度:', entry.contentRect.width);
  echartEnstance.resize()
});
observer.observe(document.querySelector('.responsive-box'));

对dom offsetWidth进行监听

watch(()=>document.querySelector('.responsive-box').offsetWidth进行监听,()=>{
    echartEnstance.resize()
})

内穿穿透,多隧道的开启,

  1. 首先,维护一个轮询池(set集合),用于记录正在开启的隧道id,
  2. 当开启一个隧道时,将其添加进轮询池,这时开始轮询后台接口,每两秒向后台发起请求,验证开启结果,若状态为pending,继续轮询,若为failed,则返回失败结果,将其从轮询池移除,若成功,则返回成功状态,关闭loading

image.png

image.png

这段代码实现了一个彩虹尺标记器组件,我来用通俗易懂的话解释它的主要功能:

  1. 整体功能

    • 这是一个类似于彩虹尺的可视化组件,可以在一个水平的刻度尺上展示多个数据点
    • 每个数据点都用一个"棒棒糖"样式的标记来表示
    • 底部有一个彩虹渐变色的刻度尺,用来显示数值范围
  2. 主要特点

    • 棒棒糖标记:

      • 每个标记由一个"柄"和一个圆形的"头部"组成
      • 头部显示一个随机图片
      • 标记的颜色会根据其在彩虹尺上的位置自动匹配对应的渐变色
    • 交互效果:

      • 鼠标悬停在标记上时会显示提示框,包含该点的具体数值和序号
      • 当悬停在某个标记上时,其他标记会变暗,突出显示当前选中的标记
  3. 可配置参数

    • minValue:刻度尺的最小值(默认 -90)
    • maxValue:刻度尺的最大值(默认 -30)
    • step:刻度间隔(默认 5)
    • markerList:数据点列表,每个点包含值和对应的图片URL
  4. 自适应特性

    • 组件会自动适应容器宽度
    • 当窗口大小改变时,所有标记的位置会自动重新计算
    • 彩虹渐变背景会随着容器宽度变化而伸缩
  5. 视觉效果

    • 底部是一个从红色到紫色的彩虹渐变刻度尺
    • 每个数据点的颜色会根据其在彩虹尺上的位置自动取对应的渐变色
    • 刻度值均匀分布在底部,方便读数

这个组件适合用于需要在一个范围内展示多个数据点的场景,特别是当你想要给这些数据点添加视觉差异和交互效果时。比如可以用于展示温度分布、评分分布等数据可视化场景。

彩虹尺功能介绍:

  1. 这是一个彩虹尺的可视化组件,可以在一个水平的刻度尺上展示多个数据点,每个数据点表示不同强度的AP
  2. 每一个AP的颜色边框会根据其在彩虹尺上的位置自动匹配对应的渐变色
  3. 彩虹尺底部有一个彩虹渐变色的刻度尺,用来显示数值范围,最大值和最小值动态设置
  4. 鼠标悬停在标记上时会显示提示框,包含该点的具体数值和序号,当悬停在某个标记上时,其他标记会变暗,突出显示当前选中的标记
// createGradient 函数:创建线性渐变色
function createGradient(ctx) {
    // 创建一个水平方向的线性渐变对象
    // 参数分别是:起点x(0),起点y(0),终点x(width.value),终点y(0)
    const gradient = ctx.createLinearGradient(0, 0, width.value, 0)
    
    // 下面通过 addColorStop 方法设置渐变的颜色停止点
    // 参数1是位置(0-1之间的数值),参数2是对应位置的颜色
    gradient.addColorStop(0, 'red')          // 0% 位置是红色
    gradient.addColorStop(0.1666, 'orange')  // 16.66% 位置是橙色
    gradient.addColorStop(0.3333, 'yellow')  // 33.33% 位置是黄色
    gradient.addColorStop(0.5, 'green')      // 50% 位置是绿色
    gradient.addColorStop(0.6666, 'cyan')    // 66.66% 位置是青色
    gradient.addColorStop(0.8333, 'blue')    // 83.33% 位置是蓝色
    gradient.addColorStop(1, 'violet')       // 100% 位置是紫色
    
    return gradient  // 返回创建好的渐变对象
}

// getColorAtPosition 函数:获取渐变中特定位置的颜色值
function getColorAtPosition(element, x) {
    // 创建一个临时的 canvas 元素
    const canvas = document.createElement('canvas')
    // 获取 canvas 的 2D 绘图上下文
    const ctx = canvas.getContext('2d')
    // 设置 canvas 的宽度为组件宽度
    canvas.width = width.value
    // 设置 canvas 的高度为1像素(因为我们只需要一行颜色数据)
    canvas.height = 1

    // 创建渐变对象
    const gradient = createGradient(ctx)
    // 将渐变设置为填充样式
    ctx.fillStyle = gradient
    // 用渐变色填充整个 canvas
    // 参数分别是:起点x,起点y,宽度,高度
    ctx.fillRect(0, 0, width.value, 1)

    // 获取指定位置(x,0)处1x1像素的颜色数据
    // pixelData 是一个包含 RGBA 值的数组 [R, G, B, A]
    const pixelData = ctx.getImageData(x, 0, 1, 1).data
    // 返回 RGB 格式的颜色字符串
    return `rgb(${pixelData[0]}, ${pixelData[1]}, ${pixelData[2]})`
}

难点: 1、(视觉效果还原)每个数据点边框颜色的计算,(通过 Canvas API 来处理颜色计算,既保证了视觉效果,又提供了精确的颜色获取功能。)

  1. 创建一个临时的canvas元素,获取到这个元素的2D绘图上下文
  2. 设置canvas 的宽度为组件宽度,高度为1像素(因为我们只需要一行颜色数据)
  3. 创建渐变对象的样式,这对象表示一个长度为彩虹尺宽度的线性渐变
  4. 用这个渐变对象填充整个 canvas,相当于创建了一个map,key是彩虹尺上的信号强度值,value是该点对应的rgb颜色值,通过传入的信号强度值就能获取到该值对应的RGB 格式的颜色字符串

2、(自适应特性

  • 组件会自动适应容器宽度
  • 当窗口大小改变时,所有标记的位置会自动重新计算
  • 彩虹渐变背景会随着容器宽度变化而伸缩