Created
October 31, 2017 20:14
-
-
Save GeorgDangl/4402f32b0dc0844f8d8c0f98fe072b7f to your computer and use it in GitHub Desktop.
Displaying graphs and charts in a Xamarin WebView with Chart.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" | |
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms" | |
prism:ViewModelLocator.AutowireViewModel="True" | |
x:Class="App.Mobile.Views.HackyReportPage" | |
Title="Hacky Chart.js Report"> | |
<WebView VerticalOptions="FillAndExpand"> | |
<WebView.Source> | |
<HtmlWebViewSource Html="{Binding ReportHtml}" /> | |
</WebView.Source> | |
</WebView> | |
</ContentPage> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Newtonsoft.Json; | |
using Prism.AppModel; | |
using Prism.Navigation; | |
using Prism.Services; | |
namespace App.Mobile.ViewModels | |
{ | |
public class HackyReportPageViewModel : ViewModelBase | |
{ | |
public HackyReportPageViewModel(INavigationService navigationService, | |
IApplicationStore applicationStore, | |
IDeviceService deviceService) | |
: base(navigationService, applicationStore, deviceService) | |
{ | |
BuildReportHtml(); | |
} | |
public string ReportHtml { get; set; } | |
private void BuildReportHtml() | |
{ | |
var chartConfigScript = GetChartScript(); | |
var html = GetHtmlWithChartConfig(chartConfigScript); | |
ReportHtml = html; | |
} | |
private string GetHtmlWithChartConfig(string chartConfig) | |
{ | |
var inlineStyle = "style=\"width:100%;height:100%;\""; | |
var chartJsScript = "<script src=\"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.min.js\"></script>"; | |
var chartConfigJsScript = $"<script>{chartConfig}</script>"; | |
var chartContent = $@"<div id=""chart-container"" {inlineStyle}> | |
<canvas id=""chart"" /> | |
</div>"; | |
var document = $@"<html style=""width:97%;height:100%;""> | |
<head>{chartJsScript}</head> | |
<body {inlineStyle}> | |
{chartContent} | |
{chartConfigJsScript} | |
</body> | |
</html>"; | |
return document; | |
} | |
private string GetChartScript() | |
{ | |
var chartConfig = GetSpendingChartConfig(); | |
var script = $@"var config = {chartConfig}; | |
window.onload = function() {{ | |
var canvasContext = document.getElementById(""chart"").getContext(""2d""); | |
new Chart(canvasContext, config); | |
}};"; | |
return script; | |
} | |
private string GetSpendingChartConfig() | |
{ | |
var config = new | |
{ | |
type = "pie", | |
data = GetPieChartData(), | |
options = new | |
{ | |
responsive = true, | |
maintainAspectRatio = false, | |
legend = new | |
{ | |
position = "top" | |
}, | |
animation = new | |
{ | |
animateScale = true | |
} | |
} | |
}; | |
var jsonConfig = JsonConvert.SerializeObject(config); | |
return jsonConfig; | |
} | |
private object GetPieChartData() | |
{ | |
var colors = GetDefaultColors(); | |
var labels = new[] {"Groceries", "Car", "Flat", "Electronics", "Entertainment", "Insurance"}; | |
var randomGen = new Random(); | |
var dataPoints = Enumerable.Range(0, labels.Length) | |
.Select(i => randomGen.Next(5, 25)) | |
.ToList(); | |
var data = new | |
{ | |
datasets = new[] | |
{ | |
new | |
{ | |
label = "Spending", | |
data = dataPoints, | |
backgroundColor = dataPoints.Select((d, i) => | |
{ | |
var color = colors[i % colors.Count]; | |
return $"rgb({color.Item1},{color.Item2},{color.Item3})"; | |
}) | |
} | |
}, | |
labels | |
}; | |
return data; | |
} | |
private List<Tuple<int, int, int>> GetDefaultColors() | |
{ | |
return new List<Tuple<int, int, int>> | |
{ | |
new Tuple<int, int, int>(255, 99, 132), | |
new Tuple<int, int, int>(255, 159, 64), | |
new Tuple<int, int, int>(255, 205, 86), | |
new Tuple<int, int, int>(75, 192, 192), | |
new Tuple<int, int, int>(54, 162, 235), | |
new Tuple<int, int, int>(153, 102, 255), | |
new Tuple<int, int, int>(201, 203, 207) | |
}; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for writing this! I took your idea and expanded it into a Nuget package since I have several projects that could use this functionality. https://github.com/ChristopherMWood/XamarinChartJSPlugin