Highcharts首次加载时宽度超出容器div

38

我正在使用jQuery Mobile和Highcharts。

我正在jQM data-role="content" 容器内绘制面积图,并且在该容器内,我有以下的div:

<div style="padding-top: 5px; padding-bottom: 10px; position: relative; width: 100%;">
    <div id="hg_graph" style="width: 100%"></div>
</div>

我的高级图表是从Highcharts的一个示例中获取的基本图表,我没有设置图表width属性。

在第一次加载时,图表超出了包含div的宽度,但当我调整浏览器大小时,它会自动适应到适当的宽度。

如何让它在第一页加载时就正确显示宽度,而不仅仅在调整大小时才显示正确?

我已经查看了Stack Overflow上的类似帖子,但没有解决方案似乎有效。

更新

  1. 我已经确定问题是由于Highcharts动态生成的<rect>标签在页面加载时占用了整个浏览器窗口的宽度,根本没有从容器div的宽度中获取。以下是我检查时生成的HTML:

    <rect rx="5" ry="5" fill="#FFFFFF" x="0" y="0" **width="1920"** height="200"></rect>

  2. 我尝试在JSFiddle中复制此问题,但似乎在那里运行良好,这真的让我感到困惑。以下是我的JSFiddle代码:http://jsfiddle.net/meandnotyou/rMXnY


问题已解决,对吗? - Sebastian Bochan
1
@SebastianBochan 不是解决了。最受欢迎的答案只是截断了图形! - Andy Hayden
仍未解决。这个问题在它的 GitHub 存储库中已经发布为问题了吗? - Jefsama
我也被这个破事卡住了!:( - Jerome
21个回答

45

1
这是最好的答案。这是正确的方法。这是唯一对我起作用的事情。谢谢!!!解决了数小时的挫败感。 - PALEN
2
我为那些没有看到这个答案的人感到遗憾。赞同此答案! - wetjosh
你怎么调用chart.reflow()方法?我在文档中找不到它。我看到了chart属性,但找不到要调用的方法。 - dr4g1116
这是一个例子: http://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/chart/reflow-false/this.chart = new Highcharts.Chart(this.opts); this.chart.reflow(); - Lyudmyla
抱歉,但在我的情况下,这并不起作用,因为我有三个图表并排放置,然而,上面的解决方案可以解决问题,其中宽度和高度设置为100%。 - AdityaKapreShrewsburyBoston
对于仅使用CSS的解决方法,可以参考我的解决方案https://dev59.com/12Ml5IYBdhLWcg3woYTa#67324020 - Ahmad

34

这就像魔法一样有效。

在你的CSS文件中添加以下内容。

.highcharts-container {
    width:100% !important;
    height:100% !important;
}

32
这会隐藏掉图表的一部分。 - jperelli
1
你有没有想过我为了让这个工作而花费了多长时间。而它其实就是这么简单。非常感谢! - jaredwilli
对我来说,使用将highcharts-container的位置设置为absolute以及将父容器的位置设置为relative与此响应一起使用是有效的。 - kitimenpolku
这并不使图表适应,它只是强制其容器不会突破父容器。这使得图表延伸到highcharts-container之外,不再显示滚动条。这绝不是解决根本问题的方法。 - user909694
它的工作区宽度没问题,但数据没有显示。如果我移动窗口屏幕,数据会首次出现,现在数据可见。 - Kondal
显示剩余4条评论

13

我有同样的问题,在我的情况下,有一个高图的图表,需要点击按钮才会显示出来。在show事件之后,我加入了$(window).resize();,这样可以正确地解决问题。希望对你有所帮助。


我使用了相同的方法,看起来是这个页面上最优雅的解决方案。 - nickspiel
对于那些因为Highchart在页面加载时未显示的容器中开始而出现大小问题的人,这种方法将为您提供最一致的结果。 - John Meinken
这就是我一直在做的事情,直到升级到第6版之后才出现了问题:( - webaholik

6

设置图表的宽度。这是唯一有效的选项。

chart: {
            type: 'line',
            width: 835
        },

如果我们使用响应式设计,它只能在大屏幕上动态工作。 - Kondal

4

在文档就绪时定义highcharts:

<div style="width:50%" id="charts">

以及脚本:

$(document).ready(function(){
    $(#chart).highcharts(){
    ...
    });
)};

希望它能够正常工作;)

3

对于使用angular和自定义组件的用户,请记得在css中定义一个有尺寸的display(例如blockflex)用于宿主元素。

当图表容器具有填充时,您可能会发现这是必不可少的:

html

<chart (load)="saveInstance($event.context)">
...
</chart>

ts

  saveInstance(chartInstance: any) {
    this.chart = chartInstance;
    setTimeout(() => {
      this.chart.reflow();
    }, 0);
  }

否则,图表将在加载时超出容器并仅在下一次浏览器回流(例如,当您开始调整窗口大小)时获得其正确的宽度。

你好 我尝试了这个,但是它给了我以下错误:[ts]属性“reflow”在类型“Chart”上不存在。 - Optimum Creative
最近没有关注Highcharts,可能API已经改变了,现在无法提供帮助,抱歉。 - user776686

3

我曾经遇到过类似的问题,即高级图表在居中方面出现了问题。它可以在某些分辨率下正确居中和调整大小,但不是所有情况都是如此。当它无法正确居中时,我遇到了你在这里描述的完全相同的症状。

我通过附加/覆盖高级图表默认样式的其他css来解决了这个问题。

因此,在自定义的css文件中添加以下内容:

.highcharts-container{
/** Rules it should follow **/
}

假设您的div "hg-graph"中只包含Highcharts,则应该解决您的问题。

我尝试使用各种属性覆盖包含highchart图表的div,但似乎无法正确实现。你能发布一下你使用的CSS规则的示例吗?另外,我已经更新了我的帖子并提供了更多信息。 - activelogic
我使用的是 {margin: 0 auto;},因为我想把它居中。你需要覆盖的类可能不是我提到的那个。如果你在页面上查看源代码,检查 hg_graph div 并找到 Highcharts 使用的底层容器。 - Tim Z.
1
嗨,Tim。我找到了这个类,它是.highcharts-container。我尝试指定width: 100% !important或在Chrome的DevTools中进行内联编辑,这确实成功地将容器限制为正确的宽度,但图表仍然是1920像素宽并且溢出,但隐藏在容器之外。问题似乎在于首次加载时由Highcarts生成的<SVG>元素具有定义的像素宽度,因此更改容器实际上并没有做任何事情,因为图表将继续溢出。 - activelogic
很抱歉我不能提供更多帮助,因为我只是为PC建造它而不是移动设备。另一件事是,我不确定你想要实现什么目标。你是想通过缩放来限制图表尺寸吗?因为屏幕的100%将占据整个屏幕,而100%的100%仍然是整个屏幕...所以这可能是你的溢出问题? - Tim Z.
1
谢谢尝试。我现在正在我的PC上使用Chrome测试,所以与手机有没有关系。基本上我有一个父容器,它有padding: 1%。在该容器中是hg_graph div,其宽度为100%。因此,它的宽度应该是总屏幕大小的98%。当HighCharts生成图表时,它会获取整个页面宽度而不是hg_graph的宽度(98%)。这只发生在第一页加载时。如果我调整浏览器大小,Highcharts会自动重新呈现到正确的宽度(98%)。 - activelogic

2
最好的方法是在渲染事件函数中调用chart.reflow。具体请参见文档
 Highcharts.stockChart( 'chartContainer', {
 chart: {
  events: {
    render: function() {
      this.reflow();
    }
  },
  zoomType: 'x',
   ...
},

记得在图表容器中将 min-width 设为零,并将 overflow 设为 hidden。

#chartContainter {
  min-width: 0;
  overflow: hidden;
  }

1
我今天遇到了同样的问题——不是在移动设备上,而是在窗口大小在第一次页面加载时较小的情况下。当页面加载时,图表被隐藏,然后在页面上进行一些选择后,我们创建了图表。我们在css中为容器设置了最小宽度和最大宽度,但没有设置宽度。
当图表被创建时,需要确定创建SVG的尺寸。由于图表被隐藏,无法正确获取尺寸,因此代码克隆图表容器,将其定位到屏幕外并附加到主体上,以便确定高度/宽度。
由于未设置宽度,克隆的div会尝试占用尽可能多的空间,直到达到我设置的最大宽度。使用该宽度创建SVG元素,但添加到当前较小的图表容器div中(基于屏幕大小)。结果是图表超出了容器div的边界。
图表首次呈现后,已知屏幕尺寸,因此不再调用克隆函数。这意味着任何窗口调整大小或重新加载图表数据都会导致图表正确缩放。

我通过覆盖Highcharts函数cloneRenderTo来解决了这个初始加载问题,该函数克隆div以获取尺寸:

(function (H) {
    // encapsulated variables
    var ABSOLUTE = 'absolute';

    /**
    * override cloneRenderTo to get the first chart display to fit in a smaller container based on the viewport size
    */
    H.Chart.prototype.cloneRenderTo = function (revert) {
        var clone = this.renderToClone,
            container = this.container;

        // Destroy the clone and bring the container back to the real renderTo div
        if (revert) {
            if (clone) {
                this.renderTo.appendChild(container);
                H.discardElement(clone);
                delete this.renderToClone;
            }

            // Set up the clone
        } else {
            if (container && container.parentNode === this.renderTo) {
                this.renderTo.removeChild(container); // do not clone this
            }
            this.renderToClone = clone = this.renderTo.cloneNode(0);
            H.css(clone, {
                position: ABSOLUTE,
                top: '-9999px',
                display: 'block' // #833
            });
            if (clone.style.setProperty) { // #2631
                clone.style.setProperty('display', 'block', 'important');
            }
            doc.body.appendChild(clone);

            //SA: constrain cloned element to width of parent element
            if (clone.clientWidth > this.renderTo.parentElement.clientWidth){
                clone.style.width = '' + this.renderTo.parentElement.clientWidth + 'px';
            }

            if (container) {
                clone.appendChild(container);
            }
        }
    }

})(Highcharts);

我将这个函数保存在一个单独的脚本文件中,该文件会在 Highchart.js 脚本加载后加载。


0
我解决了这个问题(对于我的情况),方法是确保包含的UI元素在图表之前呈现,从而使Highcharts能够计算出正确的宽度。
例如:
之前:
var renderChart = function(){
...
};
renderChart();

之后:

var renderChart = function(){
...
};
setTimeout(renderChart, 0);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接