-
vizulySeptember 9, 2020 at 11:38 am #12007
Below is a more basic file for the Ring Chart. What is tricky about the ring chart is that each data series has its own objects you need to create – as seen in the
createSeries()
functions. This is demonstrated in the RingChart docs as well – but it doesn’t go too in depth. Anyway – here is the code for the basic example. It still relies on an external data file because there are so many time series data points. If you put this in the directory as the RingChart test container it should work just fine.<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vizuly 2.0 - RingChart</title> <!-- vizuly2.specific style sheets --> <link rel="stylesheet" href="lib/styles/vizuly.css"> <script src="lib/d3_v5.7.min.js"></script> <script src="lib/vizuly2_core.min.js"></script> <script src="src/RingChart.js"></script> <script src="data/ringchart_data.js"></script> </head> <body> <!-- Our main content container--> <div id="myDiv" style="width:600px; height:600px; border-radius:10px; margin: 0px auto; margin-top:100px; overflow:hidden;"> </div> <script id="testscript"> var viz = vizuly2.viz.RingChart("#myDiv"); function createSeries(data) { var laTemps = []; var pollution = data.pollution; var calfire = data.calfire; var drought = data.drought; data.temps.forEach(function (d, i) { if (i % 7 == 0) { d.Date = new Date(d.Date); laTemps.push(d); } }) pollution.forEach(function (d) { d.Date = new Date(d.Date); }) calfire.forEach(function (d) { d.StartDate = new Date(d.StartDate); d.EndDate = new Date(d.EndDate); }) drought.forEach(function (d) { d.Date = new Date(d.ValidEnd); }) var tempSeries = { 'data' : laTemps, 'label' : 'Temps', 'x' : function (d, i) { return d.Date; }, 'y' : function (d) { return [d.TempMax] }, 'plotType' : 'BAR_STACKED', 'valueRange' : function (series) { return [d3.min(series.data, function (d, i) { return d3.sum(series.y(d, i))}),d3.max(series.data, function (d, i) { return d3.sum(series.y(d, i))})] }, 'plotRatio' : .35, 'dataTipLabels' : function (d, datum, index) { return [ 'Low: ' + d3.format(',')(Math.round(datum.TempMin)) + '°F', 'High: ' + d3.format(',')(Math.round(datum.TempMax)) + '°F', d3.timeFormat('%b %d, %Y')(datum.Date) ] } }; var pollutionSeries = { 'data' : pollution, 'label' : 'Pollution', 'x' : function (d, i) { return d.Date; }, 'y' : function (d) { return d.AQI; }, 'plotType' : 'LINE_AREA', 'plotRatio' : .2, 'dataTipLabels' : function (d, datum, i) { return ['Particulate: ' + d3.format(',.2f')(datum.PM2_5), 'Air Quality Index: ' + d3.format(',.2f')(datum.AQI), d3.timeFormat('%b %Y')(datum.Date)] } }; var droughtSeries = { 'data' : drought, 'label' : 'Drought', 'x' : function (d, i) { return d.Date; }, 'y' : function (d) { return [d.D0, d.D1, d.D2, d.D3, d.D4]; }, 'plotType' : 'BAR_STACKED', 'valueRange' : function (series) { return [0, d3.max(series.data, function (d, i) { return d3.sum(series.y(d, i)) })] }, 'plotRatio' : .25, 'dataTipLabels' : function (d, datum, index) { return ['No Drought: ' + d3.format(',')(Math.round(datum.None)) + ' Acres', '<div style="text-align:left, width:120px, margin:0px auto">' + 'L0: ' + d3.format(',')(Math.round(datum.D0)) + ' Acres <br>' + 'L1: ' + d3.format(',')(Math.round(datum.D1)) + ' Acres <br>' + 'L2: ' + d3.format(',')(Math.round(datum.D2)) + ' Acres <br>' + 'L3: ' + d3.format(',')(Math.round(datum.D3)) + ' Acres <br>' + 'L4: ' + d3.format(',')(Math.round(datum.D4)) + ' Acres <br>' + '</div>', d3.timeFormat('%b %Y')(datum.Date)] } }; var fireSeries = { 'data' : calfire.filter(function (d) { return d.Acres > 1000 }), 'label' : 'Fires', 'x' : function (d, i) { return d.StartDate; }, 'y' : function (d) { return d.Acres; }, 'valueRange' : function (series) { return [0, d3.max(series.data, function (d, i) { return d.Acres })] }, 'plotType' : 'SCATTER', 'plotRatio' : .21, 'scale' : d3.scalePow().exponent(.5), 'dataTipLabels' : function (d, datum, index) { return [datum.Name + ' Fire', d3.format(',')(datum.Acres) + ' Acres Burned', d3.timeFormat('%b %Y')(datum.StartDate)] } } return [tempSeries, pollutionSeries, droughtSeries, fireSeries]; } var series = createSeries(data); viz.series(series) .margin({top: '10%', left: "10%", right: "10%", bottom: "10%"}) .width('100%') .height('100%') .outerRadius('48%') .innerRadius('25%') .xTickCount(24) .gutterAngle(28) .dateRange(function () { return [new Date("01/01/2000" + ""), new Date("09/01/2018")] }) .style('gutter-fill','#AAA') .style('gutter-fill-opacity',.15) .style('series-label-color','#000') .on('styled',function (d) { viz.selection().selectAll('.x-axis-label').style('font-family','Roboto') }) viz.update(); </script> </body> </html>
DeasusSeptember 9, 2020 at 5:48 pm #12008-thank you! So awesome! -I noticed that the example HTML page defaulted to the ‘Climate’ theme. Do you happen to have the same HTML example with the “Ghost” theme? If not, I could try to target each and every part of the ghost theme and update it under .style… but I’m super hopeful you have something consolidated!
Thanks so so so much!
vizulySeptember 9, 2020 at 6:51 pm #12009Hello Deasus,
So the themes are a bit more involved, they are combination of styles and functions. I encourage you to take a deeper look at the
demo/RingChartDemo.js
file. But I have put them all together in a single file here. Vizuly is designed to be a highly customizable visualization library – but it does come with a certain level of complexity for these more advanced techniques.The Ring Chart is by far the most complex Vizuly component – most component themes are just a collection of style settings, but here you go with all the code in one file.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vizuly 2.0 - RingChart</title> <!-- vizuly2.specific style sheets --> <link rel="stylesheet" href="lib/styles/vizuly.css"> <script src="lib/d3_v5.7.min.js"></script> <script src="lib/vizuly2_core.min.js"></script> <script src="src/RingChart.js"></script> <script src="data/ringchart_data.js"></script> </head> <body> <!-- Our main content container--> <div id="myDiv" style="width:600px; height:600px; border-radius:10px; margin: 0px auto; margin-top:100px; overflow:hidden;"> </div> <script id="testscript"> var viz = vizuly2.viz.RingChart("#myDiv"); function createSeries(data) { var laTemps = []; var pollution = data.pollution; var calfire = data.calfire; var drought = data.drought; data.temps.forEach(function (d, i) { if (i % 7 == 0) { d.Date = new Date(d.Date); laTemps.push(d); } }) pollution.forEach(function (d) { d.Date = new Date(d.Date); }) calfire.forEach(function (d) { d.StartDate = new Date(d.StartDate); d.EndDate = new Date(d.EndDate); }) drought.forEach(function (d) { d.Date = new Date(d.ValidEnd); }) var tempSeries = { 'data' : laTemps, 'label' : 'Temps', 'x' : function (d, i) { return d.Date; }, 'y' : function (d) { return [d.TempMax] }, 'plotType' : 'BAR_STACKED', 'valueRange' : function (series) { return [d3.min(series.data, function (d, i) { return d3.sum(series.y(d, i))}),d3.max(series.data, function (d, i) { return d3.sum(series.y(d, i))})] }, 'plotRatio' : .35, 'dataTipLabels' : function (d, datum, index) { return [ 'Low: ' + d3.format(',')(Math.round(datum.TempMin)) + '°F', 'High: ' + d3.format(',')(Math.round(datum.TempMax)) + '°F', d3.timeFormat('%b %d, %Y')(datum.Date) ] } }; var pollutionSeries = { 'data' : pollution, 'label' : 'Pollution', 'x' : function (d, i) { return d.Date; }, 'y' : function (d) { return d.AQI; }, 'plotType' : 'LINE_AREA', 'plotRatio' : .2, 'dataTipLabels' : function (d, datum, i) { return ['Particulate: ' + d3.format(',.2f')(datum.PM2_5), 'Air Quality Index: ' + d3.format(',.2f')(datum.AQI), d3.timeFormat('%b %Y')(datum.Date)] } }; var droughtSeries = { 'data' : drought, 'label' : 'Drought', 'x' : function (d, i) { return d.Date; }, 'y' : function (d) { return [d.D0, d.D1, d.D2, d.D3, d.D4]; }, 'plotType' : 'BAR_STACKED', 'valueRange' : function (series) { return [0, d3.max(series.data, function (d, i) { return d3.sum(series.y(d, i)) })] }, 'plotRatio' : .25, 'dataTipLabels' : function (d, datum, index) { return ['No Drought: ' + d3.format(',')(Math.round(datum.None)) + ' Acres', '<div style="text-align:left, width:120px, margin:0px auto">' + 'L0: ' + d3.format(',')(Math.round(datum.D0)) + ' Acres <br>' + 'L1: ' + d3.format(',')(Math.round(datum.D1)) + ' Acres <br>' + 'L2: ' + d3.format(',')(Math.round(datum.D2)) + ' Acres <br>' + 'L3: ' + d3.format(',')(Math.round(datum.D3)) + ' Acres <br>' + 'L4: ' + d3.format(',')(Math.round(datum.D4)) + ' Acres <br>' + '</div>', d3.timeFormat('%b %Y')(datum.Date)] } }; var fireSeries = { 'data' : calfire.filter(function (d) { return d.Acres > 1000 }), 'label' : 'Fires', 'x' : function (d, i) { return d.StartDate; }, 'y' : function (d) { return d.Acres; }, 'valueRange' : function (series) { return [0, d3.max(series.data, function (d, i) { return d.Acres })] }, 'plotType' : 'SCATTER', 'plotRatio' : .21, 'scale' : d3.scalePow().exponent(.5), 'dataTipLabels' : function (d, datum, index) { return [datum.Name + ' Fire', d3.format(',')(datum.Acres) + ' Acres Burned', d3.timeFormat('%b %Y')(datum.StartDate)] } } return [tempSeries, pollutionSeries, droughtSeries, fireSeries]; } var series = createSeries(data); viz.series(series) .margin({top: '10%', left: "10%", right: "10%", bottom: "10%"}) .width('100%') .height('100%') .outerRadius('48%') .innerRadius('25%') .xTickCount(24) .gutterAngle(28) .dateRange(function () { return [new Date("01/01/2000" + ""), new Date("09/01/2018")] }) .style('gutter-fill','#AAA') .style('gutter-fill-opacity',.15) .style('series-label-color','#000') .on('styled',function (d) { viz.selection().selectAll('.x-axis-label').style('font-family','Roboto') }) viz.update(); function clearViz() { viz.clearStyles(); viz.series().forEach(function (series) { series.styles = {}; }) viz .xTickLengthMajor(function (d) { return (viz.size().outerRadius - viz.size().innerRadius) * .04; }) .xTickLengthMinor(function (d) { return (viz.size().outerRadius - viz.size().innerRadius) * .02; }) .expandTicksOnHover(true); } var ghostTheme = { styles: { 'background-color-top': '#555', 'background-color-bottom': '#000', 'tick-stroke': '#FFF', 'tick-stroke-opacity': 0.2, 'ring-background-fill': '#000', 'axis-stroke': '#FFF', 'axis-label-color': '#FFF', 'series-label-color': '#FFF', 'x-label-tip-color': '#000', 'x-label-tip-fill': '#FFF', 'value-line-stroke': '#FFF', 'value-line-opacity': 0.8, 'value-circle-fill': '#E64A19', 'value-circle-stroke': '#FAD2C5' }, props: { 'xTickLengthMajor' : function (d) { return (viz.size().outerRadius - viz.size().innerRadius) }, 'xTickLengthMinor' : function (d) { return (viz.size().outerRadius - viz.size().innerRadius) }, 'expandTicksOnHover': false }, series: [ { index: 0, styles: { 'series-bar-stroke': 'none', 'series-bar-fill': function (d, i, index) { return tempScaleColorGhost(d.TempMax) }, 'series-bar-fill-opacity': 0.5 } }, { index: 1, styles: { 'series-area-fill': function (d, i, index) { return "url(#" + vizuly2.svg.gradient.radialFade(viz, '#FFF', [1, .25], [.8, 1]).attr("id") + ")"; }, 'series-area-fill-opacity': .7, 'series-line-stroke-over': '#390ed5', 'series-area-fill-over': '#E64A19' } }, { index: 2, styles: { 'series-bar-fill': function (d, i, index) { return '#FFF' }, 'series-bar-fill-opacity': function (d, i, index) { return [0.1, 0.2, 0.4, 0.6, 0.8][index] }, 'series-bar-fill-over': '#E64A19', 'series-bar-stroke-over': '#E64A19', 'series-bar-stroke-over-opacity': .8 } }, { index: 3, styles: { 'series-scatter-fill': function (d, i, index) { return '#FFF' }, 'series-scatter-fill-over': '#E64A19', 'series-scatter-fill-opacity': function (d) { return fireOpacity(d.Acres) }, 'series-scatter-fill-opacity-over': 1, 'series-scatter-stroke': function (d, i, index) { return '#FFF' }, 'series-scatter-stroke-over': '#FFF' } } ] } function changeTheme(val) { clearViz(); var props = this[val].props; Object.keys(props).forEach(function (key) { viz[key](props[key]); }) var series = this[val].series; viz.series().forEach(function (vizSeries, i) { vizSeries.styles = series[i].styles; }) var styles = this[val].styles; viz.applyStyles(styles); viz.update(); } var tempScaleColorGhost=d3.scaleLinear().range(['#333', '#333', '#AAA', '#FFF']).domain([0, 60, 80, 100]) var fireOpacity=d3.scaleLinear().range([.2, .8]).domain([d3.min(data.calfire,fireFunction), d3.max(data.calfire, fireFunction)]) var fireFunction = function (d) { return d.Acres }; changeTheme('ghostTheme'); </script> </body> </html>
-
|
You must be logged in to reply to this topic.