Подтвердить что ты не робот

AmCharts не отображает график для первоначально скрытых divs

Я использую amCharts (который использует Raphaël за кадром), чтобы отобразить некоторые диаграммы как SVG; и заметили, что если SVG отображается в первоначально невидимом div, браузер не сразу отображает изображение, когда div становится видимым. Однако, если я модифицирую дисплей, например, путем изменения размера браузера или масштабирования Ctrl-mousewheel, изображение SVG затем отображается как ожидалось, когда страница перерисовывается.

Точный метод переключения видимости div осуществляется через Bootstrap tabbed navbar.

Я признаю, что не очень разбираюсь в SVG - это проблема с рендерингом браузеров или разметкой SVG amCharts, или мне нужно явно называть какой-то метод перерисовки, когда я могу сказать о видимости SVG изменилось?

Здесь jsFiddle, который иллюстрирует проблему; если вы переключитесь на раздел 2 (в Chrome, Firefox), диаграмма не будет видна изначально. Изменение размера дисплея приведет к его появлению.

4b9b3361

Ответ 1

Я нашел причину как для начального поведения, так и для обходного пути - и все это специфично для amCharts (ничего общего с SVG как таковой), поэтому я перефразирую заголовок соответственно.

Что происходит, когда amCharts создает SVG, он должен (или, по крайней мере, решает) определять ширину и высоту в абсолютных выражениях. Они основаны на размере целевого div, полученного с помощью свойств offsetWidth и offsetHeight.

Неактивная вкладка имеет набор свойств display: none, и в результате эта часть DOM даже не отображается, поэтому возвращает ноль для обоих свойств размера. Это в конечном итоге приводит к тому, что amCharts создает диаграмму SVG 0x0, когда chart.write вызывается для скрытого div.

Изменение размера фиксирует все, потому что каждая диаграмма регистрирует слушателя в событии окна onresize, которое вызывает метод диаграммы handleResize. Это заставляет пересчитать ширину и высоту на основе новых (текущих) размеров div.


Итак, в заключение я думаю, что есть два альтернативных способа справиться с этим:

  • Вызов chart.write для диаграммы тогда и только тогда, когда ее вкладка становится видимой.
  • Вызов каждого метода диаграммы handleResize при изменении вкладок.

(Первый вариант позволяет избежать первоначального попадания в визуализацию невидимой диаграммы, но затем выполняет полное перерисовку при каждом изменении вкладок. Последний имеет преимущество, но, скорее всего, быстрее после этого. решение будет состоять в том, чтобы отображать каждый график ровно один раз между каждым изменением размера, в первый раз, когда он становится видимым, но это намного сложнее, поскольку это могло бы включать в себя, в частности, прослушиватели событий по умолчанию).

Обновление. Дальнейшие осложнения с отображением невидимой диаграммы; в частности, я нашел проблемы с расчетами высоты, не принимая во внимание пространство, требуемое доменной осью, и поэтому растягивая диаграмму из своего div. Это не было исправлено, вызвав handleResize - вызов measureMargins заранее выглядел так, как будто он должен работать, но не сделал этого. (Вероятно, есть еще один метод, который можно было бы вызвать после этого, чтобы он работал, например, resetMargins, но на данный момент он начал чувствовать себя очень неустойчивым...)

Как таковой, я не считаю целесообразным визуализировать диаграмму в первый раз на невидимом div, поэтому я пошел с некоторой комбинацией отмеченных выше маркеров. Я слушаю, когда вкладка диаграммы становится видимой в первый раз, а затем вызывает chart.write для соответствующего объекта диаграммы - и всякий раз, когда вкладки меняются, всем ранее отображенным диаграммам предлагается обрабатывать размер.

Ответ 2

* Отредактировано *

Вот обновленный fiddle. Canvas будет отображаться только после отображения вкладки. Я храню идентификаторы chartdiv в массиве и проверяю, есть ли в нем или нет.

* Отредактировано *

Единственное решение, которое я нашел, это показать График после отображения конкретной вкладки.

Как вы видите в этом 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);
});

Я думаю, это не совсем то, что вы ищете, но я надеюсь, что это поможет на данный момент.

Ответ 3

У меня была такая же проблема, но мое решение было альтернативой отображению: none, вы можете использовать этот класс в css

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

это исчезает на экране, но видимо для amchart, поэтому разрешение диаграммы никогда не теряет размер!!!!

Ответ 4

Я полностью согласен с Анджей Дойлем.

Выдача handleresize на диаграмме при нажатии на выбранную div (вкладку) работает для меня на cs-cart с пользовательскими вкладками (не jquery -ами).

Следующие действия выполняются во время определения корзины во всем мире.

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

Ответ 5

Это поможет вам решить проблему. У меня есть мой амхарт, показанный в разных вкладках. Компонент SVG не позволяет им показывать этот div из-за проблемы с изменением размера.

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

измените размер своего окна во время создания диаграмм.

Ответ 6

Я также столкнулся с проблемой и исправил ее, сделав инициализатор функцией. Рабочая скрипка.

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

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

Ответ 7

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>

Ответ 8

Другая работа вокруг была бы

drawTransactionTypeChart();
setTimeout(function(){hidePieCharts();},1);

Изначально устанавливаем display:inline в div, который является контейнером диаграммы, он получает визуализацию.

Затем установите display:none с помощью setTimeout() после 1 мс.

Надеюсь, что это поможет...

Ответ 9

У меня есть два amcharts на разных вкладках. Фондовая диаграмма будет размещена на #chartdiv и круговая диаграмма, которая будет помещена на #chartdivpie. Вот как я решил свою проблему.

Мой пользовательский css - перезаписать загрузочный файл -

#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');
    })

Ответ 10

<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>