NVD3图表无法在隐藏选项卡中正确呈现

时间:2014-02-04 21:16:20

标签: d3.js twitter-bootstrap-3 hidden-field nvd3.js bootstrap-tabs

我正在构建一个包含许多图表的页面,这些图表会根据您正在查看的标签一次显示一个。

初始活动标签中的图表正确呈现。但是,当我单击另一个选项卡时,图表无法正确呈现。

据推测,这是因为隐藏字段在可见之前没有尺寸。事实上,如果我调整窗口大小,图表将更正它的比例,并进行渲染以使其填充可用宽度。

我可以通过css明确定义图表大小来解决这个问题,但这会破坏图表的响应方面。

有谁可以告诉我如何触发相同的NVD3事件,当窗口调整大小时会被激活?这样我就可以将它绑定到新选项卡的选择上,并希望能够解决渲染问题。

7 个答案:

答案 0 :(得分:15)

我有同样的问题(多个标签上的图表),这是我唯一可以开始工作的事情。

$(function () {
    $(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
        window.dispatchEvent(new Event('resize'));
    });
});

然而,我感觉所有图表都在重新渲染,无论它们是在活动标签上(可见)还是在非选定标签(隐藏)中。

有谁知道如何确保只调整活动图表的大小/重新绘制?

答案 1 :(得分:12)

我想出了如何触发我需要的调整大小事件。在我的情况下,选项卡由引导程序驱动。所以我只是修改了我的bootstrap show tab事件以触发页面调整大小事件。这有点间接,但它完成了工作:

jQuery('#myTab a').click(function (e) {
    e.preventDefault()
    jQuery(this).tab('show')
    jQuery(window).trigger('resize'); // Added this line to force NVD3 to redraw the chart
})

答案 2 :(得分:8)

只需添加此JavaScript:

$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
  window.dispatchEvent(new Event('resize'));
})

hidden.bs.tab是根据Bootstrap文档显示新选项卡后触发的事件。每次更改标签后,此代码都会触发调整大小事件。

答案 3 :(得分:4)

新答案的原因

2018 中的很多人都需要使用Vanilla Javascript。由于当今存在的许多框架和Javascript库与jQuery不兼容。曾几何时使用jQuery解决方案回答所有Javascript问题是可以接受的,但它已不再可行。

<强>问题

加载C3.js或D3.js图形时,如果在页面加载期间视口不在站点中,则图形无法正确呈现。

示例

  1. 如果您输入网址,请打开新标签页,然后在页面加载后返回。

  2. 如果您刷新包含图表的页面,请最小化浏览器并在页面加载后重新打开它。

  3. 如果您刷新或转到带有图表的页面,请轻扫到计算机上的新窗口。然后在加载后返回带有图表的页面。

  4. 在所有这些情况下,您的C3.js / D3.js图形将无法正确呈现。通常,您将看到一个空白画布。因此,如果您期望条形图,则会看到没有绘制条形图的画布。

    <强>背景

    虽然我已经看到这个问题得到解答但我需要一个 NOT 使用jQuery的答案。既然我们已经达到了无法用jQuery修复所有东西的日子,我认为似乎很适合为这个问题提供一个普通的Javascript答案。

    我的团队面临的问题是,如果刷新页面并刷掉或最小化,C3.js / D3.js图表​​将无法加载。基本上,如果你没有停留在页面并将其保留在网站中,直到它完成加载,你将看不到图表,直到你再次调整页面大小。我知道这是使用C3.js / D3.js的每个人都会遇到的问题,但我们在Salesforce中专门使用Lightning。

    <强>答案

    我们的修复是在初始化图表的控制器功能中添加它。任何人都可以在他们编写的任何函数中使用它来初始化他们的C3.js / D3.js图形而不管它们的堆栈。这不依赖于Salesforce,但如果您在Salesforce中遇到此问题,它确实有效。

    document.addEventListener('visibilitychange', () => {
       console.log(document.visibilityState);
       window.dispatchEvent(new Event('resize'));
    });
    

答案 4 :(得分:3)

我遇到了同样的问题。我正在使用 ng-show 来隐藏div。一旦我用 ng-if 替换ng-show,我就可以看到以预期行为绘制的图形。说明:

  1. 当我们使用ng-show或 ng-hide 来隐藏div时,只会将其更改为显示属性,但div将位于dom中。

  2. 当我们使用 ng-if div从dom中删除并再次添加到dom内部时它也会在nvd3图上执行重绘操作。因此,我们看到正确的图形而不是压扁的图形。

答案 5 :(得分:0)

通常触发重绘的事件是窗口resize事件 - NVD3不为此使用自定义事件。你可以自己控制它;通常的定义是

nv.utils.windowResize(function() { d3.select('#chart svg').call(chart); });

(其中“#chart”是包含图表的元素)。没有什么能阻止你在另一个事件上触发代码,甚至在你更改标签时明确地运行重绘代码。

答案 6 :(得分:0)

更有效的方法是使用chart.update()方法

var chart_x = nv.models.somechart()
var chart_y = nv.models.somechart()

.....显示图表

jQuery('#myTab a').click(function (e) {
    e.preventDefault()
    jQuery(this).tab('show')
    if(jQuery(this)...something === '..x..')
      chart_x.update(); //CALL THE UPDATE
    else ...  

})