web-dev-qa-db-ja.com

amChartsは最初に非表示のdivのグラフを表示しません

amChartsRaphaël を舞台裏で使用)を使用してレンダリングしています一部のグラフはSVGです。また、SVGが最初は非表示のdivでレンダリングされた場合、divが表示されてもブラウザーはすぐに画像をレンダリングしないことに注意してください。ただし、表示を変更した場合は、ブラウザのサイズを変更するか、Ctrlキーとマウスホイールでズームすると、ページが再描画されたときにSVG画像が期待どおりにレンダリングされます。

Divの表示切り替えの正確な方法は、 Bootstrapのタブ付きnavbar を使用する方法です。

SVGの経験があまりないことを認めます-これはブラウザーのレンダリング、またはamChartsのSVGマークアップの問題ですか、それともSVGの可視性が変更されたことがわかると、何らかの再描画メソッドを明示的に呼び出す必要がありますか?

これは、問題を説明する jsFiddleです ;セクション2に切り替えると(Chrome、Firefoxの場合)、チャートは最初は表示されません。ディスプレイのサイズを変更すると表示されます。

20
Andrzej Doyle

最初の動作と回避策の両方の理由を見つけました-それはすべてamCharts固有(SVG自体には関係ありません)なので、それに応じてタイトルを言い換えます。

AmChartsがSVGを作成するときに、絶対的な用語で幅と高さを定義する(または少なくとも決定する)必要があるということです。これらは、offsetWidthおよびoffsetHeightプロパティを介して取得されるターゲットdivのサイズに基づいています。

非アクティブなタブにはdisplay: noneプロパティが設定されており、その結果、DOMのこの部分はレンダリングされないため、両方のサイズプロパティに対してゼロを返します。これにより、最終的にchart.writeが非表示のdivに対して呼び出されたときに、amChartsが0x0 SVGチャートを作成します。

各チャートは、チャートのonresizeメソッドを呼び出すhandleResizeウィンドウイベントにリスナーを登録するため、サイズを変更すると状況が修正されます。これにより、divの新しい(現在の)寸法に基づいて、幅と高さが再計算されます。


結論として、これを処理するには2つの代替方法があると思います。

  • chart.writeを呼び出して、タブが表示されるようになったときだけチャートを表示します。
  • タブが変更されたら、各グラフのhandleResizeメソッドを呼び出します。

(最初のオプションは、非表示のグラフをレンダリングする最初のヒットを回避しますが、タブが変更されるたびに完全な再描画を行います。後者は、最初にヒットを受け取りますが、その後はより高速です。ボーナスマークの場合、最良の解決策は各チャートを各サイズ変更の間に正確に1回表示するには、最初に表示されますが、特に、デフォルトのイベントリスナーとの干渉が発生するため、はるかに複雑です。

更新:非表示のグラフのレンダリングにはさらに複雑な問題があります。特に、高さの計算でドメイン軸に必要なスペースが考慮されていないため、グラフをdivから引き伸ばす際に問題が見つかりました。これはhandleResizeを呼び出しても修正されませんでした。measureMarginsを呼び出すと、正常に機能するように見えましたが、機能しませんでした。 (おそらく、この後でresetMarginsのように機能させるために呼び出すことができる別のメソッドがあるでしょうが、この時点で非常に不安定に感じ始めました...)

そのため、非表示のdivで初めてチャートをレンダリングすることは現実的ではないと思うので、上記の箇条書きのいくつかの組み合わせを使用しました。チャートのタブが初めて表示されたときにリッスンし、適切なチャートオブジェクトに対してchart.writeを呼び出します-タブが変更されるたびに、all以前にレンダリングされたチャートは、サイズ変更を処理するように指示されます。

24
Andrzej Doyle

*編集済み*

これが更新された fiddle です。キャンバスは、タブが表示されたときにのみレンダリングされます。 chartdiv IDを配列に格納し、そこにあるかどうかを確認します。

*編集済み*

私が見つけた唯一の解決策は、特定のタブが表示された後にグラフを表示することでした。

これを見ると jsFiddle です。

var tabs = $('.tabbable').tab()

tabs.on('shown', function(e){
   id = $(e.target).attr('href');        
   chartdiv_id = $(id).find('.chartdiv').attr('id');                        
   doChart(chartdiv_id, true);
});

それはあなたが探しているものとは正確には違うと思いますが、それが今のところ役に立てば幸いです。

4
Robert Merten

私は同じ問題を抱えていましたが、私の解決策はdisplay:noneの代わりです:CSSでこのクラスを使用できます

.hidden {
   position: absolute !important;
   top: -9999px !important;
   left: -9999px !important;
}

画面が消えるが、アンチャートでは表示されるため、チャートの解像度がサイズを失うことはありません!!!!

3
DonVidela
<a href="#" class="show_charts">Show me charts</a>
<div class="charts_div" style="display:hidden;">
some charts here
</div>
<script>
    $(document).on('click', '.show_charts', function(){
        $('.charts_div').toggle();
        //just redraw all charts available on the page
        for(var i = 0; i < AmCharts.charts.length; i++) {
            AmCharts.charts[i].validateData();
        }
    });
</script>
1
RSV_70
var chart = null;
AmCharts.ready(function () {
    chart = AmCharts.makeChart('chart', .....);
});
$(document).ready(function(){
    $("#view_chart").click(function(){
        chart.validateSize();
    });
});


<button type="button" id="view_chart">View Chart</button>
<div style="display:none;" id="chart"></div>
1
yassine

これは、問題の解決に役立つ場合があります。アンチャートを別のタブパンに表示しています。 SVGコンポーネントでは、サイズ変更の問題により、そのdivを表示できません。

$(window).resize(function() {
    setTimeout(function() {
        chart.write("chartdiv1");
    }, 300);
});

チャートを作成しながら、ウィンドウのサイズを再度変更します。

1
chetnashahu

私はアンジェイ・ドイルに完全に同意します。

選択したdiv(タブ)をクリックしたときにチャートでhandleresizeを発行すると、カスタムタブ(jqueryタブではない)を備えたcs-cartで機能します。

以下は、カートがグローバルに定義されているときに機能します。

    function refreshchart(){
        chart.handleResize();
    };

私も問題に遭遇し、初期化子を関数にすることで修正しました。 作業フィドル

$("#button").click(function(){
    $("#chartdiv").toggle();
    makeChart();
});

function makeChart() {
     var chart = AmCharts.makeChart("chartdiv", {
         //all the stuff
     });
}
1
Perry

異なるタブに2つのアンチャートがあります。 #chartdivに配置する株価チャートと#chartdivpieに配置する円グラフ。これは私が私の問題を解決した方法です。

私のカスタムCSS-上書きするbootstrap-

#chartdivpie { width: 1138px; height: 500px; }
.tab-content .tab-pane {
   position: absolute;
   top: -9999px;
   left: -9999px;
   display: inline;
}
.tab-content .tab-pane.active {
    position: inherit !important;
}

JQuery呼び出し

$('#myTab a').click(function (e) {
      e.preventDefault()
        $(this).tab('show');
        chart.invalidateSize();
        chart.write('chartdiv');
    })
0
PJunior

別の回避策は

_drawTransactionTypeChart();
setTimeout(function(){hidePieCharts();},1);
_

最初に_display:inline_をチャートコンテナーであるdivに設定すると、レンダリングされます。

次に、1ミリ秒後にsetTimeout()を使用して_display:none_を設定します。

お役に立てれば...

0
Chakradhar Vyza