为什么 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 更新整个数据 的相关文章

  • 从 thymeleaf 获取数据到模态引导程序、jquery

    我正在尝试获取模态视图的 id 这是为了更新 onclick 元素 但我找不到方法 知道如何为 boostrap 5 完成此操作 或我可以用其他方法吗 谢谢 tr a inactivate a div class modal fade mo
  • 如何检测浏览器是否支持自定义元素

    我正在查看 Modernizr 它应该有助于功能检测 这应该可以帮助确定您的网站是否与给定的 Web 浏览器兼容 但我没有看到任何表明我可以使用它来检测自定义 HTML 的内容我们在内容中创建和定义的元素 如果不是 Modernizr 我如
  • 将 OoXml 插入单词抛出错误:未知

    我一直在尝试通过office js将OOXML插入到word文档的正文内容中insertOoXML 方法 我什至尝试过最简单的实现 认为我在尝试替换 XML 本身中的 fieldCodes 时做了一些不正确的事情 所有结果都是这样Error
  • 使用 vscode 调试器调试 next.js

    我已经使用安装了一个项目创建下一个应用程序 https github com segmentio create next app 我需要使用我的编辑器 vscode 调试服务器端渲染 所以我访问过vscode recipes 如何调试 ne
  • TypeError: props.render 不是一个函数(React hook 形式)

    我将方法作为我用react hook form制作的形式的道具传递 当从react hook form添加控制器时 它给了我 TypeError props render不是一个函数 我在网上找不到任何解决方案 因此感谢任何帮助 impor
  • 使用模数按字母顺序对列表进行排序

    我在获取元素列表并按字母顺序对它们进行排序方面没有任何问题 但我很难理解如何使用模数来做到这一点 更新 这是按我的方式工作的代码 但是 我更喜欢下面提供的答案的可重用性 因此接受了该答案
  • 检查 JavaScript 字符串是否为 URL

    JavaScript 有没有办法检查字符串是否是 URL 正则表达式被排除在外 因为 URL 很可能是这样写的stackoverflow 也就是说它可能没有 com www or http 如果你想检查一个字符串是否是有效的 HTTP UR
  • Node.js:如何在检索数据(块)时关闭响应/请求

    我正在用 node js 构建一个应用程序 它加载多个页面并分析内容 因为 node js 发送块 所以我可以分析这些块 如果一个块包含例如索引 nofollow 我想关闭该连接并继续其余部分 var host example com to
  • 从未用 @flow 标记的导入文件中获取类型定义

    TL DR我怎么告诉flow从未声明的导入模块导入类型定义 flow 加长版 流接缝能够从不使用流语法的文件中派生类型 请参阅示例 示例文件 flow js if Math random lt 0 5 var y hello else va
  • 为什么是 javascript:history.go(-1);无法在移动设备上工作?

    首先 一些背景 我有一个向用户呈现搜索页面 html 表单 的应用程序 填写标准并单击 搜索 按钮后 结果将显示在标准部分下方 在结果列表中 您可以通过单击将您带到新页面的链接来查看单个结果的详细信息 在详细信息页面中 我添加了一个 返回结
  • 标签获取 href 值

    我有以下 html div class threeimages a img alt Australia src Images Services 20button tcm7 9688 gif a div class text h2 a hre
  • MVC 在布局代码之前执行视图代码并破坏我的脚本顺序

    我正在尝试将所有 javascript 包含内容移至页面底部 我正在将 MVC 与 Razor 一起使用 我编写了一个辅助方法来注册脚本 它按注册顺序保留脚本 并排除重复的内容 Html RegisterScript scripts som
  • Meteor - 从客户端取消服务器方法

    我正在通过服务器方法执行数据库计数 用户可以选择他们希望如何执行计数 然后调用该方法 我的问题是 计数可能需要一些时间 并且用户可能会在方法运行时改变主意并请求不同的计数 有什么方法可以取消调用的方法并运行新的计数吗 我认为 this un
  • 表单计算器脚本基本价格未加载 OnLoad

    我的表单中有一个计算器来计算我的下拉选项选择 function select calculate on change calc input type checkbox calculate on click calc function cal
  • 如何在react-native中获取Text组件的onPress值

    我是一名新的 React Native 开发人员 我想使用 onPress 获取 Text 组件的值并将其传递给函数
  • Angular 2+ 安全性;保护服务器上的延迟加载模块

    我有一个 Angular 2 应用程序 用户可以在其中输入个人数据 该数据在应用程序的另一部分进行分析 该部分仅适用于具有特定权限的人员 问题是我们不想让未经授权的人知道how我们正在分析这些数据 因此 如果他们能够在应用程序中查看模板 那
  • 为 illustrator 导出脚本以保存为 web jpg

    任何人都可以帮我为 illustrator CC2017 编写一个脚本 将文件以 JPG 格式导出到网络 旧版 然后保存文件并关闭 我有 700 个文件 每个文件有 2 个画板 单击 文件 gt 导出 gt 另存为 Web 旧版 然后右键文
  • 为什么在 Internet Explorer 中访问 localStorage 对象会引发错误?

    我正在解决一个客户端问题 Modernizr 意外地没有检测到对localStorageInternet Explorer 9 中的对象 我的页面正确使用 HTML 5 文档类型 并且开发人员工具报告该页面具有 IE9 的浏览器模式和 IE
  • JQuery 图像上传不适用于未来的活动

    我希望我的用户可以通过帖子上传图像 因此 每个回复表单都有一个上传表单 用户可以通过单击上传按钮上传图像 然后单击提交来提交帖子 现在我的上传表单可以上传第一个回复的图像 但第二个回复的上传不起作用 我的提交过程 Ajax 在 php 提交
  • 使用 Ajax 请求作为源数据的 Jquery 自动完成搜索

    我想做的事 我想使用 jquery 自动完成函数创建一个输入文本字段 该函数从跨域curl 请求获取源数据 结果应该与此示例完全相同 CSS 在这里并不重要 http abload de img jquerydblf5 png http a

随机推荐

  • 如何验证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