D3.js 开发实战——散点图(二)响应性(方案一)

613 阅读2分钟

原文(持续更新):datavis-note.benbinbin.com/article/d3/…


系列文章可以查看《数据可视化》专栏


💡 本文的代码需要依赖 D3 环境,版本为 v7.3.0

🔍 所参考的 Observable Notebook:Scatterplot

Observable Notebook 官方样例是较通用的代码,下一步是结合 notebook 里的演示数据改写代码,虽然会降低了代码的通用性,但可以将代码进行简化,然后在 Codepen 里复现,这个散点图是宽高固定为 width = 640, height = 400 然后基于它进行改进,为图表添加响应页面大小变化的功能。

实现图表的随页面大小响应式变化功能有两种方案:

方案一:只设置 svg 元素的宽高,即整体缩放图表来实现(主要使用 CSS 的 transform scale 属性实现),但是可能造成图表元素过大或过小的问题

⚙️ 代码具体演示效果可以查看这个 Codepen

scatterplot-responsive-version-1.gif

其核心代码如下

/**
*
* 监听页面调整大小的操作,并相应地调整散点图的大小
*
*/
// 监听页面(容器)的大小变化
const container = document.getElementById("container");

let width = container.clientWidth;
let height = container.clientHeight;

let timer = null;

function debounce(delay = 500) {
if (timer) {
  // (如果倒计时的时间未到,而再次触发 debounce 函数)阻止计时器执行回调函数
  clearTimeout(timer);
}

// 重新设置计时器,倒计时重新计算
timer = setTimeout(function () {
  // 经过延迟后,执行核心代码
  // 获取当前容器的的宽高值
  const w = container.clientWidth;
  const h = container.clientHeight;

  // 当页面的宽度或高度改变时
  if (w !== width || h !== height) {
    width = w;
    height = h;
    // 重新设置 svg 画布参数
    svg.attr("width", w)
    .attr("height", h)
      .attr("viewBox", [0, 0, w, h])
  }

  // 执行完核心代码后,清空计时器 timer
  timer = null;
}, delay);
}

function resized() {
// 实际使用防抖函数时,可以设置延迟时间
// 这里设置为延迟 1000 毫秒
debounce(500);
}

// 监听页面调整大小时分发的 resize 事件
function setListener() {
window.addEventListener("resize", resized);
return function removeListener() {
  window.removeEventListener("resize", resized);
};
}

// 当需要时调用方法注销监听器(例如移除图表时)
const removeListener = setListener();

从演示可知该方案是对整个 SVG 进行缩放,在页面较小时图表的可视性可能较差