为什么 d3 更新整个数据

2024-01-11

我有一个 svg 元素,其数据是这样创建的:

var chart = d3.select("#my-div").append("svg");
var chartData = [];
chartData.push([{x: 1, y: 3}, {x: 2, y: 5}]);
chartData.push([{x: 1, y: 2}, {x: 2, y: 3}]);

          .domain([1, 5]);
var lineFunc = d3.svg.line()
    .x(function (d) {
        return xRange(d.x);
    })
    .y(function (d) {
        return yRange(d.y);
    })
    .interpolate('linear');

chart.append('g').classed('lines', true).selectAll('path').data(chartData).enter()
    .append('path')
    .attr('d', function(d) {
        return lineFunc(d);
    })
    .attr('stroke', 'black')
    .attr('stroke-width', 1)
    .attr('fill', 'none');

之后我尝试更新我的数据并更新图表:

chartData[1].push({x: 5, y: 5});
chart.selectAll('g.lines').selectAll('path').data(chartData)
    .attr('d', function(d) {
        console.log('updating:');
        console.log(d);
        return lineFunc(d);
    })
    .attr('stroke', 'black')
    .attr('stroke-width', 1)
    .attr('fill', 'none');

但它打印'updating' 两次(对于两个图表数据元素),但我只更改了一个(chartData[1])。如何防止它不更新我没有更改的内容?我会有很多功能,所以当只有一个改变时,更新所有功能是低效的。

// 编辑@mef的答案

我将数据更改为(我不介意更新整个图表数据[X]数据,我只是想避免更新整个图表数据):

chartData.push({key: 'A', data: [{x: 1, y: 3}, {x: 2, y: 5}]});
chartData.push({key: 'B', data: [{x: 1, y: 2}, {x: 2, y: 3}]});

然后当我添加数据时.data(chartData, function(d) {return d.key})更新时我也做了同样的事情,但它仍然更新了两者。

我也尝试把.data(chartData, function(d) {return 'A'}) or .data(chartData, function(d) {return 'B'})更新数据时,它只更新一个,但总是更新数据Akey(该函数是否返回A or B).

所以整个代码看起来像这样:

var chart = d3.select("#my-div").append("svg");
var chartData = [];
chartData.push({key: 'A', data: [{x: 1, y: 3}, {x: 2, y: 5}]});
chartData.push({key: 'B', data: [{x: 1, y: 2}, {x: 2, y: 3}]});

var xRange = d3.scale.linear().range([50, 780]).domain([1, 5]);
var yRange = d3.scale.linear().range([380, 20]).domain([2, 9]);

var lineFunc = d3.svg.line()
    .x(function (d) {
        return xRange(d.x);
    })
    .y(function (d) {
        return yRange(d.y);
    })
    .interpolate('linear');

chart.append('g').classed('lines', true).selectAll('path')
    .data(chartData, function(d) {return d.key}).enter()
    .append('path')
    .attr('d', function(d) {
        return lineFunc(d.data);
    })
    .attr('stroke', 'black')
    .attr('stroke-width', 1)
    .attr('fill', 'none');

更新数据

chartData[1].data.push({x: 5, y: 5});
chart.selectAll('g.lines').selectAll('path')
    .data(chartData, function(d) {return d.key})
    .attr('d', function(d) {
        console.log('updating:');
        console.log(d);
        return lineFunc(d.data);
    })
    .attr('stroke', 'black')
    .attr('stroke-width', 1)
    .attr('fill', 'none');

好的,可以做到...

选项 1 - 使用密钥

这是一种懒惰的方法......

Strategy

  1. 创建一个检测数据变化的关键函数。
    通过读取节点属性字符串并将其与在数据上调用的属性生成器函数结果进行比较来完成此操作。
  2. 检测 d3 数据绑定过程的阶段(节点上的密钥或数据上的密钥)并为每个阶段使用不同的密钥:
    var k = Array.isArray(this) ? lineD(d, lineFunc) : d3.select(this).attr("d");

  3. 在“数据密钥”阶段,通过从虚拟节点写入和读回来对齐两个密钥值的格式。 (这就是懒惰的部分!)

  4. 为更新、退出和输入选择保留单独的引用,以解耦它们的行为。

Code

var chart = d3.select("#my-div").append("svg")
      .attr("height", 600)
      .attr("width", 900);
var chartData = [];
chartData.push([{x: 1, y: 3}, {x: 2, y: 5}]);
chartData.push([{x: 1, y: 2}, {x: 2, y: 3}]);

var xRange = d3.scale.linear().range([50, 780]).domain([1, 5]);
var yRange = d3.scale.linear().range([380, 20]).domain([2, 9]);

var lineFunc = d3.svg.line()
    .x(function (d) {
      return xRange(d.x);
    })
    .y(function (d) {
      return yRange(d.y);
    })
    .interpolate('linear');

chart.append('g').classed('lines', true).selectAll('path')
    .data(chartData, key)
    .enter().append('path')
    .attr('d', function(d) {
      return lineFunc(d);
    })
    .attr('stroke', 'black')
    .attr('stroke-width', 1)
    .attr('fill', 'none');
//updating data

chartData[1].push({x: 5, y: 5});

var update = chart.selectAll('g.lines').selectAll('path')
      .data(chartData, key);
update.enter().append('path')
      .attr('d', function (d) {
        console.log('updating:');
        console.log(d);
        return lineFunc(d);
      })
      .attr('stroke', 'black')
      .attr('stroke-width', 1)
      .attr('fill', 'none');
update.exit().remove();

function key(d, i, j) {
  var k = Array.isArray(this) ? lineAttr(d, lineFunc, "d") : d3.select(this).attr("d");
  console.log((Array.isArray(this) ? "data\t" : "node\t") + k)
  return k;

  function lineAttr(d, lineFunct, attribute) {
    var l = d3.select("svg").selectAll("g")
      .append("path").style("display", "none")
      .attr(attribute, lineFunct(d))
    d = l.attr(attribute);
    l.remove();
    return d;
  }
}

Output

node    M50,328.57142857142856L232.5,225.71428571428572          
node    M50,380L232.5,328.57142857142856                         
data    M50,328.57142857142856L232.5,225.71428571428572          
data    M50,380L232.5,328.57142857142856L780,225.71428571428572

updating:                                                      
Array[3]0: Object1: Object2: Objectlength: 3__proto__: Array[0]

选项 2 - 使用过滤器

这更有效,但仅适用于您知道只有线上的点数会改变且线数固定的情况。

Strategy

  1. 连接数据而无需key函数并通过比较进行过滤 从绑定数据计算出的属性字符串到 DOM 元素中的当前属性字符串。
  2. 与选项 1 一样,使用虚拟节点作为惰性(跨浏览器)方式来对齐节点属性和计算属性文本的格式。

Code

//updating data

chartData[1].push({x: 5, y: 5});

chart.selectAll('g.lines').selectAll('path')
  .data(chartData)
  .filter(changed)
  .attr('d', function (d) {
    console.log('updating:');
    console.log(d);
    return lineFunc(d);
  })
  .attr('stroke', 'black')
  .attr('stroke-width', 1)
  .attr('fill', 'none');

function changed(d) {
  var s = d3.select(this);
  console.log("data\t" + lineAttr(s.datum(), lineFunc, "d"));
  console.log("node\t" + s.attr("d")); console.log("\n")
  return lineAttr(s.datum(), lineFunc, "d") != s.attr("d");

  function lineAttr(d, lineFunct, attribute) {
    var l = d3.select("svg").selectAll("g")
      .append("path").style("display", "none")
      .attr(attribute, lineFunct(d))
    d = l.attr(attribute);
    l.remove();
    return d;
  }
}

Output

data    M50,328.57142857142856L232.5,225.71428571428572
node    M50,328.57142857142856L232.5,225.71428571428572

data    M50,380L232.5,328.57142857142856L780,225.71428571428572
node    M50,380L232.5,328.57142857142856

updating:
Array[3]

选项 3 - 两全其美

Strategy

  1. 使用标准更新/进入/退出模式。
  2. 在对其进行操作之前,过滤更新选择以形成“已更改”选择。

Code

//updating data

alert("base");
chartData[1].push({ x: 5, y: 5 });
updateViz();
alert("change");
chartData.push([{x: 3, y: 1}, {x: 5, y: 2}])
updateViz();
alert("enter");
chartData.shift();
updateViz();
alert("exit");

function updateViz() {
  var update = chart.selectAll('g.lines').selectAll('path')
      .data(chartData),

      enter = update.enter()
        .append('path')
        .attr('d', function (d) {
          return lineFunc(d);
        })
        .attr('stroke', 'black')
        .attr('stroke-width', 1)
        .attr('fill', 'none'),

      changed = update.filter(changed)
        .attr('d', function (d) {
          console.log('updating:');
          console.log(d);
          return lineFunc(d);
        });

  update.exit().remove();

  function changed(d) {
    var s = d3.select(this);
    console.log("data\t" + lineAttr(s.datum(), lineFunc, "d"));
    console.log("node\t" + s.attr("d")); console.log("\n")
    return lineAttr(s.datum(), lineFunc, "d") != s.attr("d");

    function lineAttr(d, lineFunct, attribute) {
      var l = d3.select("svg").selectAll("g")
        .append("path").style("display", "none")
        .attr(attribute, lineFunct(d))
      d = l.attr(attribute);
      l.remove();
      return d;
    }
  }
}

背景

Read this https://github.com/mbostock/d3/wiki/Selections#data

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 d3 更新整个数据 的相关文章

随机推荐

  • 如何验证Java线程堆栈大小是否固定或有限?

    我试图验证 Java 堆栈大小是否固定 在开始时设置 或有限 增长到一定限制 我试图用一个简单的程序来测量这一点 该程序创建一定数量的线程 设置 Xss 但到目前为止我只发现 RSS 是每个进程的 并且出于明显的原因 知道堆大小在这里毫无意
  • Linq 完全外连接与数据表中的 NULL 记录 C#

    请问有人可以帮忙吗 我需要在 Extn In Call Records Extn Number 上返回一个表 如果任一侧不匹配 仍然返回一个计算 就像 SQL 完全外连接一样 我花了几个小时看这个 但无法让它工作 如果删除联合 我可以让代码
  • Monodroid - EditText 输入法不接受数字

    我在使用 Mono for Android 中的 EditText 控件时遇到一些非常奇怪的问题 我的解决方案针对的是 2 3 并且我正在 T Mobile VivaCity 上进行调试 这是我的 EditText 的 AXML
  • 如何阻止 git 在结账时破坏编码

    我最近使用以下设置将 gitattributes 文件添加到 c 存储库 text auto cs text diff csharp 我重新规范化了存储库按照 github 上的这些说明进行操作 https help github com
  • 更干净的元组 groupBy

    我有一系列键值对 String Int 我想按键将它们分组为值序列 即Seq String Int gt Map String Iterable Int 明显地 toMap在这里没有用 并且groupBy将值维护为元组 我想出的最好的办法是
  • Android Things:截图

    如何通过 ADB for Android Things 截屏 我努力了 adb shell screencap p sdcard screen png adb pull sdcard screen png adb shell rm sdca
  • Angular UI-Routing,页面刷新时自动重定向到父状态

    我正在开发一个使用 Angular UI 路由的项目 当我尝试刷新网页或直接输入 URL 时 它会被重定向到父状态 它确实加载了我重新加载的 URL 的状态 但随后快速重定向到父状态 这是我的状态路由 stateProvider state
  • 如何在 Objective C 中初始化一个空的可变数组

    我有一个对象 卡车 列表 其中包含填充表格视图的各种属性 当您点击它们时 它们会转到单独的卡车页面 有一个添加按钮 可以将它们添加到另一个表格视图中的收藏夹列表中 如何在 Cocoa 中初始化一个空的可变数组 我有以下代码 IBAction
  • bash脚本杀死超过一小时的php进程

    我有以下内容 kill 9 ps aux grep php awk 9 0 9 0 9 awk print 2 它的作用是杀死被 fcgid 放弃的进程并杀死它们以释放 RAM 我想每小时运行一次 cron 但想杀死早于一小时的进程 我只是
  • Textmate 到处检查拼写

    有什么方法可以检查我在 Textmate 中输入的所有单词的拼写吗 很难相信 但我实际上使用合法的英语单词来表示我的所有变量和类名 因此未突出显示的拼写错误简直要了我的命 如果有一种方法可以检查带有特殊字符的单词的拼写 那就太好了 uesr
  • 删除 PostgreSQL 中数字列的所有尾随零

    我有这张桌子properties其中有一个列atomic mass类型的NUMERIC 9 6 atomic mass 1 008000 4 002600 6 940000 9 012200 10 810000 12 011000 14 0
  • 如何访问类的静态成员?

    我正在尝试访问类的静态成员 我的班级是 class A public static strName A is my name public function xyz Since I have bunch of classes stored
  • 使用 perl 和 DBI 将非常大的表从一个 DB2 复制到另一个 DB2

    我每天需要将一个非常大 数百万行 的表从一个 DB2 数据库复制到另一个 DB2 数据库 并且我需要使用 perl 和 DBI 有没有比简单地从第一个数据库中获取每一行并将它们逐一插入到第二个数据库中更快的方法 这是我得到的 sth1 ud
  • 谷歌地图,没有启动导航的选项,只有预览

    在我的应用程序中 我在以下代码集的帮助下启动 Google 导航 String uri http maps google com maps saddr gpsLatitude gpsLongitude daddr updateAccepte
  • OSX Yosemite 升级后 adb(android 调试桥)出现问题

    我昨天将我的 2011 款 13 英寸 Macbook 升级到了 Yosemite 现在我在使用 adb 工具 1 0 31 1 0 32 时遇到问题 例如在设备上安装构建时 通过 ddms 复制文件 从eclipse android st
  • jsplumb 1.4.1 通过 uuid 或对象示例删除Endpoint

    我有一些 div 元素 每个元素有 2 个端点 一个在左侧 一个在右侧 现在我想删除每个右侧端点 每个端点都有自己唯一的 uuid 我得到了右侧端点的每个 uuid 的数组 gt 遍历它们并删除其中的每一个 但这不起作用 谁能给我一个通过
  • 使用内收益回报

    如果我没记错的话 当我在里面使用yield时using SqlConnection阻止我遇到运行时异常 using var connection new SqlConnection connectionString var command
  • 如何在 Java Swing 中显示英镑 (£) 符号?

    目前 我向 Java 源代码添加了英镑 符号 并编译生成的 Swing 组件 显示为方形 不支持的字符 符号 我怀疑这是一个编码问题 Java源文件被编码为cp1252 Eclipse似乎默认是这样 解决这个问题的正确方法是什么 使用 u0
  • PHP 命令行不运行 PHP 文件?

    我目前正在从 Windows 命令提示符处触发 PHP 使用 C xampp php gt php f c Uncrypt php 哪个输出 根据帮助文档 这很奇怪php h 的开关 f should f 解析并执行 但是 这不起作用 PH
  • 为什么 d3 更新整个数据

    我有一个 svg 元素 其数据是这样创建的 var chart d3 select my div append svg var chartData chartData push x 1 y 3 x 2 y 5 chartData push