2017-04-03 70 views
8

Używam wykresu morris.js wraz z suwakiem bootstrap.chart.redraw() nie działa po ustawieniu linii zdarzeń

Co chcę zrobić:
Jeśli suwak jest przesuwany, chcę wstawić wiersza zdarzenia do tabeli w pozycji wartości suwaków. Nic specjalnego.

Problem:
Wykres nie jest przerysowywany po ustawieniu zdarzenia. Podczas wstawiania nowych danych wykres zostanie automatycznie przerysowany. Spróbowałem więc orzeźwiający (w celu sprawdzenia poprawności składni) przekazując istniejące dane na wykresie ponownie tak:

chart.setData(chart.options.data); 

To działa! Nowe wydarzenie zostanie narysowane na wykresie. Niestety ma to złą wydajność, ponieważ wykres przerysowuje wszystkie dane.

Dokumentacja mówi, że istnieje chart.redraw(). To po prostu nie działa dla mnie. Może ktoś z was może dowiedzieć się dlaczego.

Po prostu uruchom fragment kodu i przełącz przyciski opcji, aby przetestować obie metody, a zobaczysz problem.

// Chart creation - not interesting 
 
var chart = new Morris.Line({ 
 
    element: 'chart', 
 
    ymin: 0, 
 
    ymax: 100, 
 
    gridIntegers: true, 
 
    parseTime:false, 
 
    // Will be set below 
 
    data: [ ], 
 
    xkey: 'position', 
 
    ykeys: ['value'], 
 
    labels: ['Value'], 
 
    hideHover: "always", 
 
    pointSize: 0, 
 
    continuousLine: false, 
 
    goalStrokeWidth: 3, 
 
    axes: true, 
 
    grid: true, 
 
    numLines: 6, 
 
    eventLineColors: [ "red" ], 
 
    smooth: true 
 
}); 
 

 
// Inserting some values 
 
var values = [101] 
 
for(i = 1; i <= 100; i += 1) { 
 
    var x = 100/(Math.pow((i-50), 2)+4); 
 
    values.push({ position: i, value: x }); 
 
} 
 
chart.setData(values); 
 

 
// Create slider 
 
$('#slider').slider({ 
 
    tooltip: 'never', 
 
    tooltip_position:'left', 
 
    height: 300, 
 
    length: 300, 
 
}); 
 

 
// If the slider moves, I want to set its value as an event-line 
 
$("#slider").on("slideStop", function(slideEvt) { 
 
    chart.options.events = [ slideEvt.value ]; 
 

 
    // Check inserting-data VS chart.redraw() 
 
    // Both should work... chart.redraw() isnt. 
 
    if(document.getElementById('insert').checked) 
 
     chart.setData(chart.options.data); 
 
    else if(document.getElementById('redraw').checked) 
 
     chart.redraw(); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script> 
 
<script src="http://cdn.oesmith.co.uk/morris-0.5.1.min.js"></script> 
 
<link href="http://cdn.oesmith.co.uk/morris-0.5.1.css" rel="stylesheet"/> 
 

 
<!-- Bootstrap slider --> 
 
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/bootstrap-slider.min.js"></script> 
 
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/css/bootstrap-slider.min.css"> 
 

 
<div id="chart" style="height: 150px;width:500px;"></div> 
 
<form action=""> 
 
    <input checked="true" id="insert" type="radio" name="refreshMethod"> Insert (working)<br> 
 
    <input id="redraw" type="radio" name="refreshMethod"> Redraw (not working)<br> 
 
</form> 
 
<input id="slider" type="text" data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="50"/>

Doceniam każdą pomoc tutaj. Dziękuję Ci bardzo!

Ważne edit:
Jak tylko mogę ustawić bounty (+1 godzina) będę robić. Bardzo istotną dodatkową częścią tego pytania jest powiązanie suwaka z pojedynczym zdarzeniem z planszami bez opóźnień. Obecnie wydajność jest bardzo niska w przypadku używania zdarzenia slide zamiast slideStop.

+0

"Dokumentacja mówi, że jest' chart.redraw() '." - można wskazać, gdzie/której dokument, który nawiązując do? Nie mogłem go znaleźć (zobacz linki w mojej odpowiedzi) – ochi

Odpowiedz

2

Nie działa, ponieważ wewnętrznie chart.events nie jest ustawiany, gdy zadzwonisz pod numer chart.redraw(). Ta właściwość jest ustawiona wewnątrz setData z linią this.events = this.options.events.

Aby skorygować to: W użyciu kodu chart.events = [val] zamiast chart.options.events = [val];

Osobiście bym ustawić je zarówno w przypadku setData nazywa się ponownie, ale to zależy od ciebie.

Więc w demo:

... 
else if(document.getElementById('redraw').checked) { 
    chart.events = [ slideEvt.value ]; 
    chart.redraw(); 
} 

EDIT:

dodał chart.quickRedraw funkcja. Spowoduje to usunięcie zbędnych przeliczeń z funkcji odświeżania (patrz kod zakomentowanym za to, co jest teraz wyłączone):

chart.quickRedraw = function() { 
     this.raphael.clear(); 
     //this._calc(); 
     this.drawGrid(); 
     //this.drawGoals(); 
     this.drawEvents(); 
     this.draw();  
}; 

Demo został zaktualizowany z trzeciej opcji.

// Chart creation - not interesting 
 
var chart = new Morris.Line({ 
 
    element: 'chart', 
 
    ymin: 0, 
 
    ymax: 100, 
 
    gridIntegers: true, 
 
    parseTime:false, 
 
    // Will be set below 
 
    data: [ ], 
 
    xkey: 'position', 
 
    ykeys: ['value'], 
 
    labels: ['Value'], 
 
    hideHover: "always", 
 
    pointSize: 0, 
 
    continuousLine: false, 
 
    goalStrokeWidth: 3, 
 
    axes: true, 
 
    grid: true, 
 
    numLines: 6, 
 
    eventLineColors: [ "red" ], 
 
    smooth: true 
 
}); 
 

 
// Inserting some values 
 
var values = [101] 
 
for(i = 1; i <= 100; i += 1) { 
 
    var x = 100/(Math.pow((i-50), 2)+4); 
 
    values.push({ position: i, value: x }); 
 
} 
 
chart.setData(values); 
 

 
// Create slider 
 
$('#slider').slider({ 
 
    tooltip: 'never', 
 
    tooltip_position:'left', 
 
    height: 300, 
 
    length: 300, 
 
}); 
 

 
// If the slider moves, I want to set its value as an event-line 
 
$("#slider").on("slideStop", function(slideEvt) { 
 
    chart.options.events = [ slideEvt.value ]; 
 

 
    // Check inserting-data VS chart.redraw() 
 
    // Both should work... chart.redraw() isnt. 
 
    if(document.getElementById('insert').checked) 
 
     chart.setData(chart.options.data); 
 
    else if(document.getElementById('redraw').checked) { 
 
     chart.events = [ slideEvt.value ]; 
 
     chart.redraw(); 
 
    } else if(document.getElementById('quickerRedraw').checked) { 
 
     chart.events = [ slideEvt.value ]; 
 
     chart.quickRedraw(); 
 
    } 
 
}); 
 

 
chart.quickRedraw = function() { 
 
     this.raphael.clear(); 
 
     //this._calc(); 
 
     this.drawGrid(); 
 
     //this.drawGoals(); 
 
     this.drawEvents(); 
 
     this.draw(); 
 
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script> 
 
<script src="http://cdn.oesmith.co.uk/morris-0.5.1.min.js"></script> 
 
<link href="http://cdn.oesmith.co.uk/morris-0.5.1.css" rel="stylesheet"/> 
 

 
<!-- Bootstrap slider --> 
 
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/bootstrap-slider.min.js"></script> 
 
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/css/bootstrap-slider.min.css"> 
 

 
<div id="chart" style="height: 150px;width:500px;"></div> 
 
<form action=""> 
 
    <input checked="true" id="insert" type="radio" name="refreshMethod"> Insert (working)<br> 
 
    <input id="redraw" type="radio" name="refreshMethod"> Redraw (working)<br> 
 
    <input id="quickerRedraw" type="radio" name="refreshMethod"> Quicker Redraw<br> 
 
</form> 
 
<input id="slider" type="text" data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="50"/>

+0

Zaktualizowałem odpowiedź, aby dodać alternatywną szybszą funkcję przerysowywania, usuwając część niepotrzebnego kodu 'przerysowywania'. Zobacz szczegóły w celu edycji –