Rysowanie wykresów w ASP.NET Core, Visual Studio

0

Witam,

Trochę się gubię w możliwościach rysowania grafów w aplikacji MVC ASP.NET Core. Wiem, ze jest sporo darmowych bibliotek. Instalowałem NuGety dla Chart.js i d3.js. Jednak nie dodają mi się pliki js w katalogu wwwroot/js, nie wiem jak mam skorzystać z tych paczek skoro nie mogę się do nich odnieść w sekcji head pliku cshtml. W przypadku Chart.js udało mi się to obejść wprost wgrywając plik Chart.Bundle.min. Jednak problem jest z biblioteką c3.js która oparta jest o d3, instaluje je do katalogu bower (bo tak mi podpowiada VS), czy też można wgrać jeden plik zamiast ściągać całą paczkę Nuget?. Czy ktoś mógłby wytłumaczyć dlaczego istnieje i d3 i c3 (łatwo się w tym pogubić), do czego potrzebuje tego bowera i w końcu jak odnieść się w pliku cshtml do odpowiedniej biblioteki js do rysowania grafów. Siedzę w temacie (samych wykresów) drugi dzień i widzę, że bardzo ciężko mi to zrozumieć, mam niezły bałagan w głowie :/

Wszelkie informacje wyjaśniające wskazane :)

Pozdrawiam,

0

Robiłem kiedyś w Chart.js i wtedy zrobiłem to tak (użyłem ~), bower instalował paczkę Chart.js 2.0.2 do wwwroot/lib.

<script src="~/lib/Chart.js/dist/Chart.js"></script>

https://github.com/pollubnet/Ifrit/blob/master/Ifrit.Web/Views/Shared/_Layout.cshtml#L18

Oczywiście możesz całkowicie pominąć bowera i ręcznie wrzucać pliki do wwwroot, nikt cię nie przymusza. Bower po prostu automatyzuje proces i zamiast samemu dbać o kopiowanie plików robi to za ciebie.

0

O dzięki, to może być to o co mi chodzi :) Czyli, gdybym to robił sam to muszę się odwołać do ~/js.... a jak z bowerem to do ~/lib .... ?

0

Witam,

Podpiąłem sobie bibliotekę Plotly.js. Rysowanie działa, jednak chciałbym obecnie pociągnąć dane z backendu w C#. Próbuje to zrobić tak, by w kontrolerze Home w metodzie GwtJson wysyłać JSON'a z danymi dla osi X i Y. Kod w pliku js, wygląda następująco

Plotly.d3.json("GetJson", function (err, response) {
    var trace1 = {
        x: [response.XAxis],
        y: [response.YAxis],
        type: 'scatter',
        line: { color: '#17BECF' }
    }
    Plotly.newPlot('chart', trace1)
});

Jako wynik pokazują się same osi bez danych. Ktoś wie co robię nie tak?

screenshot-20180320154141.png

0

Pokaż jak generujesz response w tym zapytaniu - jeżeli on już jest listą, to chyba nie powinien być zawarty w [ ].

0

To jest klasa danych na poszczególne osie :

public class ChartRecords
    {
        public List<int> XAxis = new List<int>();
        public List<int> YAxis = new List<int>();
    }

Generacja losowych danych:

 public static class Trace
    {
        static Random random = new Random();

        public static ChartRecords GetRecords()
        {
            ChartRecords chartRecords = new ChartRecords();

            for (int i = 0; i < 1000; i++)
            {
                chartRecords.XAxis.Add(i);
                chartRecords.YAxis.Add(random.Next(0, 100));
            }

            return chartRecords;
        }
    }

Zwracanie JSON'a przez kontroler:

 public JsonResult GetJson()
        {
            ChartRecords chartRecords = Models.Trace.GetRecords();
            var settings = new JsonSerializerSettings();
            return Json(chartRecords, settings);
        }

PS:
Po odpaleniu w konsoli "zbadaj" wszystko skutkuje takim błędem:
"Calling Plotly.plot as if redrawing but this container doesn't yet have a plot"

0

Zreplikowałem twój problem i go rozwiązałem:

Plotly.d3.json("/Home/GetJson", function (err, response) {
    var trace1 = {
        x: response.XAxis,
        y: response.YAxis,
        type: 'scatter',
        line: { color: '#17BECF' }
    }

    Plotly.newPlot('chart', [trace1]); // drugi parametr newPlot musi być tablicą: https://community.plot.ly/t/load-data-from-external-rest-service/348/4
});
0

Witam,

Faktycznie działa, dzięki. Najlepsze jest to, że oglądałem tę stronę, ale widocznie zbyt powierzchownie, nie wyłapałem tej ważnej informacji, że drugi argument w funkcji rysującej musi być tablicą.

Jedna ściana pokonana, ale są kolejne.

Ile można rzeczy można zmieniać w runtimie? Udało mi się:

Chciałbym też, aby po kliknięciu w przycisk pojawiał się i znikał rangeselector. Jak przypisać zdarzenie do kliknięcia przycisku?:

$('.SliderOn button').click(function () {
    rangeselector: {
        buttons: [
            {
                count: 1,
                label: '1m',
                step: 'month',
                stepmode: 'backward'
            },
            { step: 'all' }
        ]
    }
    rangeslider: { range: ['2017-12-01', '2018-01-05'] }
    Plotly.relayout('chart')
})
  • czy jako "modeBarButtons" . Poniżej kod który wklejony w okno JS ( https://codepen.io/etpinard/pen/PzWYgj ) umożliwia włączenie rangeselectora (niestety w moim kodzie taki sposób nie działa)
var update = {
	title: 'New Title',
	xaxis: {
        range: ['0', '2'],
        rangeselector: {
            buttons: [
                {
                    count: 1,
                    label: '1m',
                    step: 'month',
                    stepmode: 'backward'
                },
                { step: 'all' }
            ]
        },
        rangeslider: { range: ['0', '2'] }
    },
}
Plotly.plot('graph', [{
  y: [2, 1, 2]
}], {
  xaxis: {
  }
}, {
  modeBarButtons: [[{
    name: 'Show slidebar',
    click: function(gd) {
      Plotly.relayout(gd, update);
    }
  }]]
});

U mnie to wygląda tak (rozumiem, że muszę dodać czwarty argument Plotly.plot):

var buttons = {
    modeBarButtons: [[{
        name: 'SlideBar',
        click: function (b) {
            Plotly.relayout(b, Enable);
        }

    }]]
}
    Plotly.newPlot(chart, data, layout, buttons);
var Enable = {
    xaxis: {
        type: 'date',
        range: ['2017-12-01', '2018-02-01'],
        rangeselector: {
            buttons: [
                {
                    count: 1,
                    label: '1m',
                    step: 'month',
                    stepmode: 'backward'
                },
                { step: 'all' }
            ]
        },
        rangeslider: { range: ['2017-12-01', '2018-01-05'] }
    }
}

Poszukując rozwiązania, trafiłem na pewien trop, ale nie potrafię znaleźć odpowiedzi na mój problem, może znów czegoś nie widzę: https://github.com/plotly/plotly.js/issues/686

Oczywiście rangeselector to tylko jedna z kilku rzeczy do zmiany w runtime, inne to np zmiana tła wykresu (którego swoją drogą jeszcze nie udało mi się zmienić statycznie). Jednak jeśli załapię metodę to potem będzie łatwiej. Generalnie wiem, że należy używać Plotly.relayout i Plotly.restyle, zamiast Plotly.newPlot :)

Pozdrawiam,

0

Działa modeBarButtons. Tylko trzeba było go wprost wkleić w Plotly.newPlot jako 4 argument:

Plotly.newPlot(chart, data, layout, {
    modeBarButtons: [[{
        name: 'SlideBar',
        click: function (b) {
            Plotly.relayout(b, Enable);
        }

    }]]
});

To nad czym się teraz głowie to jak umieścić taką funkcjonalność w sekcji updatemenus. Skoro można tam dać jako metodę method: 'relayout' to pewnie się da też włączać i wyłączać rangeselectora. Pytanie jest takie co wpisać w pole args ? :)

Po drugie czy wiecie jak można zmieniać kilka styli za jednym zamachem w jednym buttonie updatamenus? Żeby nie robić czegoś takiego:

updatemenus: [{
        y: 0.7,
        yanchor: 'top',
        buttons: [{
            method: 'relayout',
            args: ['paper_bgcolor', 'white'],
            label: 'light'
        }, {
            method: 'relayout',
            args: ['paper_bgcolor', 'darkgrey'],
            label: 'dark'
        }]
    },
    {
        y: 0.5,
        yanchor: 'top',
        buttons: [{
            method: 'relayout',
            args: ['plot_bgcolor', 'white'],
            label: 'light'
        }, {
            method: 'relayout',
            args: ['plot_bgcolor', 'darkgrey'],
            label: 'dark'
        }]
    },
    ]

Gdzie dla paper_bgcolor i plot_bgcolor, mam dwa osobne przyciski

1 użytkowników online, w tym zalogowanych: 0, gości: 1