charting plugin

So every business app created wants some sort of pie chart or bar chart or even points plotted on a map.  Now I know corona doesn’t have this built in and this question has been asked before, but let me ask another way.  

If I wanted to use an industry standard package like “highcharts” or google charts how might I do that?  I believe google returns some sort of html5/SVG.   

https://developers.google.com/chart/interactive/docs/

corona doesn’t support html5 right?  I thought I read that svg is now supported but I am not sure that will help because I would still need the html5 wrapper.  

I agree that corona making a plugin would probably be a bad idea since there are some really nice packages out there we could use that will always be way better.   But we at least need a way to take advantage of said packages.  

Laura

I dont use html much but does this help? :

https://docs.coronalabs.com/api/library/native/newWebView.html

Hi,

Are these charts to be displayed inside the app itself?

-dev

That almost helps.   Wouldn’t I need to send some kind of command to a web server and ask it to build a page dynamically based on the chart I would like to display.  Then have it pass me back a url I could call to then call the newWebView api and include such page in my app.  I rate that idea convoluted, error prone, and difficult and I would need to have a web server some where?  :(  

Keep those ideas coming tho.  

Ideally, yes

Just need to be able to run this:  

\<html\> \<head\> \<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"\>\</script\> \<script type="text/javascript"\> google.charts.load("current", {packages:["corechart"]}); google.charts.setOnLoadCallback(drawChart); function drawChart() { var data = google.visualization.arrayToDataTable([['Task', 'Hours per Day'], ['Work', 11], ['Eat', 2], ['Commute', 2], ['Watch TV', 2], ['Sleep', 7] ]); var options = { title: 'My Daily Activities', pieHole: 0.4, }; var chart = new google.visualization.PieChart(document.getElementById('donutchart')); chart.draw(data, options); } \</script\> \</head\> \<body\> \<div id="donutchart" style="width: 900px; height: 500px;"\>\</div\> \</body\> \</html\>

While I haven’t used google charts or any data analytic software, 

I suggest redirecting them to some dashboard online showing all the graphs.

Corona supports webView’s where you can include blocks on the page that contain the contents of a web page via a URL, or you can have local HTML in your project that you can show in your webView. The webView uses native webView controls. On iOS, macOS and Android this will include full HTML5 support. For Windows, I believe it’s using the Internet Explorer controls which depending on the version of Windows, the level of HTML5 support will vary.  

You can use the HTML locally inside a webView.

When we say we don’t support HTML5 (yet), we are talking about outputting your app as an web page were people can run your app from a web page. FYI, we are working on it!

We also have an SVG plugin that might work on your SVG files that produces a display object that you can include in your app like any other image. See the Nano SVG plugin:  https://marketplace.coronalabs.com/plugin/nano-svg

Rob

What Rob said.

So if I put this in my code: webView:request( “localfile.html”, system.ResourceDirectory )

and my localfile.html looked like:

\<html\> \<head\> \<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"\>\</script\> \<script type="text/javascript"\> google.charts.load("current", {packages:["corechart"]}); google.charts.setOnLoadCallback(drawChart); function drawChart() { var data = google.visualization.arrayToDataTable([['Task', 'Hours per Day'], ['Work', 11], ['Eat', 2], ['Commute', 2], ['Watch TV', 2], ['Sleep', 7] ]); var options = { title: 'My Daily Activities', pieHole: 0.4, }; var chart = new google.visualization.PieChart(document.getElementById('donutchart')); chart.draw(data, options); } \</script\> \</head\> \<body\> \<div id="donutchart" style="width: 900px; height: 500px;"\>\</div\> \</body\> \</html\>

It would render a pie chart in my app?  

I guess you would have to try it out  if it works.

I dont have some of the files you have so it would probably not work for me.

And thanks for the like :wink:

Hi,

In theory your code above “should” work depending on cross-origin policies.

This looks interesting as well https://github.com/GlitchGames/GGChart

While that specific Google API is depreciated, they state they have no plans on shutting it down (https://developers.google.com/chart/image/).

But the webView wrapper might be your best bet.

-dev

I have tried GGChart and it does still work.  But you of course couldn’t include that in any type of app you are building for someone.  If this wrapper works I might “upgrade”  GGChart to use the wrapper instead of the old google api.   Also, using a remove server to render stuff for you makes your app depend on the network.  I have seen GGChart fail a lot in spotty network situations.  But I guess that is the world we live in.  

I can confirm that loading this page using 

local webView = native.newWebView( display.contentCenterX, display.contentCenterY, 320, 480 )

webView:request( “localfile.html”, system.ResourceDirectory )

 

does work when the html in localfile.html is a request for a chart from google charts.

the only thing I don’t understand now is how to build the localfile.html dynamically based on user input.

 

The doc seems to indicate to me that it has to come out of a system file. Is there a system directory

I can write to?

You can write to system.TemporaryDirectory, system.CachesDirectory and system.DocumentsDirectory. I would probably recommend using the temporary directory for this usage.

This is what I did for a weather app I built for my wife. I need a Google Map with an overlay from Weather Underground. I need to provide several variables to the html.  

local header = [[\<!DOCTYPE html\> \<html\> \<head\> \<title\>Google Maps JavaScript API v3 Example: Map Simple\</title\> \<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"\> \<meta charset="utf-8"\> \<style\> html, body, #map\_canvas { margin: 0; padding: 0; height: 100%; } \</style\> \<script src="https://maps.googleapis.com/maps/api/js?key=mykeyhere"\>\</script\> \<script\> var map; var radarOverlay; var mapBounds; var API\_calls = 0; var rateLimitTimer;]] local body = [[function initialize() { var myLatLong = new google.maps.LatLng(latitude, longitude); var mapOptions = { zoom: 8, center: myLatLong, mapTypeId: google.maps.MapTypeId.ROADMAP, zoomControl: false, scaleControl: false, panControl: false, streetViewControl: false, overviewMapContro: false }; map = new google.maps.Map(document.getElementById('map\_canvas'), mapOptions); google.maps.event.addListener(map, 'idle', function() { API\_calls++; if (API\_calls \> 9) { // rate limit return(true); } var center = map.getCenter(); var bounds = map.getBounds(); var zoom = map.getZoom(); ne = bounds.getNorthEast(); sw = bounds.getSouthWest(); var URL = 'http://api.wunderground.com/api/mykeyhere/animatedradar/image.gif?num=5&delay=50&maxlat=' + ne.lat() + '&maxlon=' + sw.lng() + '&minlat=' + sw.lat() + '&minlon=' + ne.lng() + '&width=' + screenWidth + '&height=' + screenHeight + '&rainsnow=1&smooth=1&noclutter=1'; if (radarOverlay) { radarOverlay.setMap(null); } radarOverlay = new google.maps.GroundOverlay( URL, bounds ); radarOverlay.setMap(map); }); rateLimitTimer = setInterval(function () { API\_calls--; if (API\_calls \< 0) { API\_calls = 0; } }, 30000); } google.maps.event.addDomListener(window, 'load', initialize); \</script\> \</head\> \<body\> \<div id="map\_canvas"\>\</div\> \</body\> \</html\>]]

So there are two parts, some fixed HTML for the head and another part that represents a bulk of the body.  I then write some JS code in between the two:

 if event.phase == "will" then local path = system.pathForFile( "radar.html" , system.TemporaryDirectory ) local fp = io.open( path, "w" ) if fp then fp:write(header) fp:write("var latitude = " .. tostring(myData.latitude) .. ";\n") fp:write("var longitude = " .. tostring(myData.longitude) .. ";\n") fp:write("var screenWidth = " .. tostring( display.contentWidth) .. ";\n") fp:write("var screenHeight = " .. tostring( display.contentHeight - 50) .. ";\n") fp:write(body) fp:close() end else webView = native.newWebView( display.contentCenterX, display.contentCenterY - 25, display.contentWidth, display.contentHeight - 50 ) local path = system.pathForFile( "radar.html" , system.TemporaryDirectory ) local fp = io.open( path, "r" ) if fp then fp:close(); webView:request( "radar.html", system.TemporaryDirectory ) else webView:request( "radar.html", system.ResourceDirectory ) end end

In the scene:show’s will phase, I write out header, the JS to construct the var’s with my unique values for the user, then the body. Once I get to the “did” phase, I create the webView and if I can get a path to the HTML I just wrote out (should always unless there is some storage issue), I have the webView load the HTML I wrote out, if I can’t open that file for some reason, I fall back to a complete HTML file in the resource directory that won’t have customized location data.  This is a lot, but I wanted to include the pretty much complete example.

Hope this helps.

Rob

Hi,

I’ve put together a module that will return a PNG from the Google Charts API here https://github.com/develephant/google-charts-corona

Seems to work fine on Android, but I have not had a chance to test on an iOS device as I currently don’t have a developers account.

If someone can test the demo project on iOS and let me know if it works I can add in a way to create the pages dynamically.

-dev

Hi,

I optimized the module a little bit. Would still love to know if the demo project (in the demo directory) runs on iOS if anyone has a chance to test it out.

https://github.com/develephant/google-charts-corona

-dev

Jan 17 01:04:36.464 ERROR: build command failed: xcrun actool --output-format human-readable-text --warnings --notices --export-dependency-info "/var/folders/5d/wyygg2ls5vz1d40dw35gpc4c0000gn/T/CLtmpFu4oy7/assetcatalog\_dependencies" --output-partial-info-plist "/var/folders/5d/wyygg2ls5vz1d40dw35gpc4c0000gn/T/CLtmpFu4oy7/assetcatalog\_generated\_info.plist" --compress-pngs --enable-on-demand-resources YES --product-type com.apple.product-type.application --compile "/Volumes/Macintosh HD/Media/Projects/Omnigeek Media/AppBuilds/demo.app" --target-device iphone --target-device ipad --minimum-deployment-target 8.0 --platform iphoneos --app-icon AppIcon "Images.xcassets" Jan 17 01:04:36.465 ERROR: with exit code 1 and output:&nbsp; Jan 17 01:04:36.465 captureCommandOutput: cat /tmp/lua\_p3hKjl Jan 17 01:04:36.494 ERROR: while compiling icons:&nbsp; Jan 17 01:04:36.494 BUILD ERROR:&nbsp; Jan 17 01:04:36.495&nbsp; Jan 17 01:04:36.510 iOS build failed (12) after 11 seconds Jan 17 01:04:36.802 ERROR: Build Failed:&nbsp; Jan 17 01:04:36.803&nbsp;

Not happy building for iOS

@Rob - Ouch!

Well thank you very much for taking the time to do that. I really appreciate it.

Is it possible it’s because I removed all the icons and the image.xcassests stuff? Are those required for iOS build?

-dev

I don’t know why we would check for icons, but the error certainly looks like that’s the cause.

Rob