使用 d3js 根据用户选择调用备用图表绘制功能 [英] Calling alternate chart drawing function based on user selection with d3js

查看:20
本文介绍了使用 d3js 根据用户选择调用备用图表绘制功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 d3js 实现可重复使用的图表,其中图表类型根据用户从下拉菜单中的选择进行更改.

I am trying to implement reusable charting with d3js, where chart type is changed based on user selection from drop-down menu.

我的代码在这里:http://tributary.io/inlet/8085642

目标:当用户从下拉菜单中选择类型时,重新绘制新图表类型以代替旧图表.

GOAL: redraw new chart type in place of old chart when user selects type from the drop down menu.

我已根据需要设置了所有内容:可以手动自行绘制每个图表,下拉菜单将 console.log 我要绘制的图表类型的名称(线、区域、蜡烛图),但显然目标是以编程方式执行此操作.

I have everything set up as needed: can draw each chart on its own manually, the drop-down menu will console.log the name of the chart type I want to draw (line, area, candle), but obviously the goal is to do this programatically.

从下面删除,与上面的原始问题无关.

eliminated aside from below, not related to original question above.

推荐答案

正如 Lars 所说,问题不在于让可重用图表工作.(事实上​​,从传递参数的可自定义图表函数的意义上讲,我不会真正称其为可重用图表";您只是有多个不同的函数.)但无论如何:您的代码在不同选项下都能正常工作您在其他函数调用中发表评论.所缺少的只是触发调用的 Javascript 和一些清理工作.我在下面讨论了如何做到这一点,但可能会将标题/问题更新为根据用户选择调用备用图表绘制功能"或类似内容.

As Lars said, the problem isn't one of getting the reusable chart to work. (In fact, I wouldn't really call this a "reusable chart" in the sense of a customizable chart function to which you pass parameters; you just have multiple different functions.) But regardless: Your code works fine with the different options when you comment in the other function calls. All that is missing is the Javascript to trigger the call and some clean-up. I've got a discussion below for how to do that, but maybe update the title/question to "Calling alternate chart drawing function based on user selection" or some such.

你需要三样东西:

  1. 附加到下拉菜单的事件侦听器,以便在选择更改时触发代码,
  2. 一种删除或隐藏当前图表数据的方法,以及
  3. 一个函数来读取选定的值并调用相应的绘制函数.

您已经在此处获得了事件侦听器:

You've already got the event listener here:

 d3.select("#drop-down").on("change", function () { 
    selected = this.value;
    console.log(selected);
 });

它在控制台上返回的值很好,但您需要实际调用适当的方法,如下所示:

It's returning the value fine on the console, but instead you need to actually call the appropriate method, like this:

 d3.select("#drop-down").on("change", function () { 
    selected = this.value;
    if(selected == "line"){chartDraw.line()}
    else if(selected == "area"){chartDraw.area()}
    else if(selected == "candle"){chartDraw.candle()}
 });

如果您有很多案例,您可能希望将其重新编写为 switch 语句.

If you have a lot of cases, you would probably want to re-write this as a switch statement.

然而,这还不是您想要的——新图形只是在旧图形之上绘制.您需要的是一种重新选择每种图形类型独有元素的方法,以便您可以将其删除.为此,您需要向在 chartDraw 方法中创建的所有元素添加一个类,例如 .attr("class" "line alt-view") 或candle alt-view" 等,然后在您的事件处理函数中再添加一行:

However, this isn't quite what you want yet -- the new graph just gets drawn overtop of the old. What you need is a way to re-select the elements that are unique to each type of graph so you can remove them. To do this, you'll need to add a class to all the elements created within the chartDraw methods, something like .attr("class" "line alt-view"),or "candle alt-view", etc., then add one more line to your event handler function:

 d3.select("#drop-down").on("change", function () { 
    selected = this.value;
    d3.selectAll(".alt-view").remove();
    if(selected == "line"){chartDraw.line()}
    else if(selected == "area"){chartDraw.area()}
    else if(selected == "candle"){chartDraw.candle()}
 });

这会为您的重新绘制创建一个干净的画布(不会删除您的轴和其他常量元素).

That creates a clean canvas for your re-draw (without deleting your axis and other constant elements).

这应该可以让它工作,但你仍然可以让它更有效率,这取决于你期望它的使用方式.如果您希望用户在不同的视图之间来回切换(并且不希望数据在此期间发生变化)您可能只想隐藏替代视图而不是删除然后重新绘制它们.

That should get it working, but you can still make it more efficient, depending on how you expect it to be used. If you expect that users will be flipping back and forth between the different views (and don't expect the data to change in the meantime) you may want to just hide the alternate views instead of deleting and then re-drawing them.

隐藏很容易;只需将上面的 .remove() 替换为 .style("visibility", "hidden").但是您还需要一种方法来测试您是否已经绘制了特定的图表视图,以便您可以使用 .style("visibility", "visible") 来显示它,而不是重新绘制.我的建议?只需创建布尔变量并在第一次绘制每个图表时设置它们,然后在图表绘制方法中检查它们:

Hiding is easy; just replace the .remove() above with .style("visibility", "hidden"). But you also need a way to test whether you've already drawn a specific chart view so you can just show it with .style("visibility", "visible") instead of re-drawing. My suggestion? Just create boolean variables and set them the first time you draw each chart, then check them in the chart-drawing method:

var areaDrawn=false, lineDrawn=false, candleDrawn=false; 

(或将这些全部收集到一个对象中:viewDrawn = {area:false, line:false, 等...并相应地更改以下代码)

(or collect these all into an object: viewDrawn = {area:false, line:false, etc... and change the below code accordingly)

//inside the chartDraw object
   area: function (){
     if(areaDrawn){
        d3.selectAll(".area.alt-view").style("visibility", "visible");
     }
     else {  
      canvas.append("path")
        .datum(sample2)
        .attr("class", "area alt-view")
        .attr("d", area);

      areaDrawn=true;
     }
    }
//and similar for the other functions

最后一件事我无法弄清楚:当您从下拉菜单中选择某些内容时,菜单不会立即使用所选值重新绘制.值发生变化,如果我退出并返回正确的值,则会显示正确的值,但不会立即显示.我不确定这是在支流中发生的事情还是与 Chrome 处理 SVG 中的外来对象的方式有关.无论哪种方式,都需要进行测试,也许可以考虑在 SVG 之外为您的生产代码创建菜单(由容器 div 组合在一起).

There is one final thing I can't figure out: when you select something from the drop-down menu, the menu doesn't redraw right away with the selected value. The value changes, and if I tab away and come back the correct value is shown, but not right away. I'm not sure if this is something going on in Tributary or something to do with the way Chrome handles foreignObjects in SVG. Either way, it's something to test and perhaps consider creating the menu outside of the SVG (grouped together by a container div) for your production code.

希望一切都有意义,我已经尝试一步一步地去做,
--ABR

Hope that all makes sense, I've tried to do it step-by-step,
--ABR

这篇关于使用 d3js 根据用户选择调用备用图表绘制功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆