@@ -39,6 +39,10 @@ hr { | |||||
margin-bottom: 2rem; | margin-bottom: 2rem; | ||||
} | } | ||||
.step-explain { | |||||
margin-top: 30px; | |||||
} | |||||
pre.highlight { | pre.highlight { | ||||
background: #f7f7f7; | background: #f7f7f7; | ||||
border-radius: 3px; | border-radius: 3px; | ||||
@@ -8,7 +8,7 @@ let bar_composite_data = { | |||||
"2013", "2014", "2015", "2016", "2017"], | "2013", "2014", "2015", "2016", "2017"], | ||||
"datasets": [{ | "datasets": [{ | ||||
"title": "Reports", | |||||
"title": "Events", | |||||
"color": "orange", | "color": "orange", | ||||
"values": report_count_list, | "values": report_count_list, | ||||
// "formatted": report_count_list.map(d => d + " reports") | // "formatted": report_count_list.map(d => d + " reports") | ||||
@@ -40,7 +40,7 @@ let more_line_data = { | |||||
let bar_composite_chart = new Chart ({ | let bar_composite_chart = new Chart ({ | ||||
parent: "#chart-composite-1", | parent: "#chart-composite-1", | ||||
title: "Reposrts", | |||||
title: "Fireball/Bolide Events - Yearly (more than 5 reports)", | |||||
data: bar_composite_data, | data: bar_composite_data, | ||||
type: 'bar', | type: 'bar', | ||||
height: 180, | height: 180, | ||||
@@ -63,23 +63,79 @@ bar_composite_chart.parent.addEventListener('data-select', (e) => { | |||||
// Demo Chart (bar, linepts, scatter(blobs), percentage) | // Demo Chart (bar, linepts, scatter(blobs), percentage) | ||||
// ================================================================================ | // ================================================================================ | ||||
let type_data = { | let type_data = { | ||||
"labels": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], | |||||
"datasets": [{ | |||||
"color": "light-blue", | |||||
"values": [25, 40, 30, 35, 8, 52, 17] | |||||
"labels": ["12am-3am", "3am-6am", "6am-9am", "9am-12pm", | |||||
"12pm-3pm", "3pm-6pm", "6pm-9pm", "9pm-12am"], | |||||
"datasets": [ | |||||
{ | |||||
title: "Some Data", color: "light-blue", | |||||
values: [25, 40, 30, 35, 8, 52, 17, -4] | |||||
}, | }, | ||||
{ | { | ||||
"color": "violet", | |||||
"values": [25, 50, -10, 15, 18, 32, 27] | |||||
title: "Another Set", color: "violet", | |||||
values: [25, 50, -10, 15, 18, 32, 27, 14] | |||||
}, | }, | ||||
{ | |||||
title: "Yet Another", color: "blue", | |||||
values: [15, 20, -3, -15, 58, 12, -17, 37] | |||||
} | |||||
] | |||||
}; | |||||
let type_chart = new Chart({ | |||||
parent: "#chart-types", | |||||
title: "My Awesome Chart", | |||||
data: type_data, | |||||
type: 'bar', | |||||
height: 250 | |||||
}); | |||||
Array.prototype.slice.call( | |||||
document.querySelectorAll('.chart-type-buttons button') | |||||
).map(el => { | |||||
el.addEventListener('click', (e) => { | |||||
let btn = e.target; | |||||
let type = btn.getAttribute('data-type'); | |||||
type_chart = type_chart.get_different_chart(type); | |||||
Array.prototype.slice.call( | |||||
btn.parentNode.querySelectorAll('button')).map(el => { | |||||
el.classList.remove('active'); | |||||
}); | |||||
btn.classList.add('active'); | |||||
}); | |||||
}); | |||||
// Trends Chart | |||||
// ================================================================================ | |||||
let trends_data = { | |||||
"labels": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", | |||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed", | |||||
"Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed"], | |||||
"datasets": [ | |||||
{ | { | ||||
"color": "blue", | "color": "blue", | ||||
"values": [15, 20, -3, -15, 58, 12, -17] | |||||
"values": [25, 40, 30, 35, 48, 52, 17, 15, 20, -3, -15, 58, | |||||
12, -17, 35, 48, 40, 30, 52, 17, 25, 5, 48, 52, 17] | |||||
} | } | ||||
] | ] | ||||
}; | }; | ||||
let plot_chart = new Chart({ | |||||
parent: "#chart-trends", | |||||
data: trends_data, | |||||
type: 'line', | |||||
height: 250, | |||||
show_dots: 0, | |||||
// region_fill: 1, | |||||
heatline: 1, | |||||
x_axis_mode: 'tick', | |||||
y_axis_mode: 'tick' | |||||
}); | |||||
// Update values chart | |||||
// ================================================================================ | |||||
let update_data_all_labels = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", | let update_data_all_labels = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", | ||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed", | "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed", | ||||
"Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed"]; | "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed"]; | ||||
@@ -103,7 +159,7 @@ let update_data = { | |||||
"specific_values": [ | "specific_values": [ | ||||
{ | { | ||||
title: "Altitude", | title: "Altitude", | ||||
// title: "Altiteragrwst ude", | |||||
// title: "A very long text", | |||||
line_type: "dashed", | line_type: "dashed", | ||||
value: 38 | value: 38 | ||||
}, | }, | ||||
@@ -152,14 +208,7 @@ let heatmap_data = { | |||||
// ================================================================================ | // ================================================================================ | ||||
let type_chart = new Chart({ | |||||
parent: "#chart-types", | |||||
data: type_data, | |||||
type: 'bar', | |||||
height: 250, | |||||
// region_fill: 1, | |||||
// y_axis_mode: 'tick' | |||||
}); | |||||
let update_chart = new Chart({ | let update_chart = new Chart({ | ||||
parent: "#chart-update", | parent: "#chart-update", | ||||
@@ -195,24 +244,6 @@ let heatmap = new Chart({ | |||||
// Events | // Events | ||||
// ================================================================================ | // ================================================================================ | ||||
Array.prototype.slice.call( | |||||
document.querySelectorAll('.chart-type-buttons button') | |||||
).map(el => { | |||||
el.addEventListener('click', (e) => { | |||||
btn = e.target; | |||||
let type = btn.getAttribute('data-type'); | |||||
type_chart = type_chart.get_different_chart(type); | |||||
Array.prototype.slice.call( | |||||
btn.parentNode.querySelectorAll('button')).map(el => { | |||||
el.classList.remove('active'); | |||||
}); | |||||
btn.classList.add('active'); | |||||
}); | |||||
}); | |||||
let chart_update_buttons = document.querySelector('.chart-update-buttons'); | let chart_update_buttons = document.querySelector('.chart-update-buttons'); | ||||
@@ -32,7 +32,7 @@ | |||||
<div class="col-sm-10 push-sm-1 later" style="font-size: 14px;"> | <div class="col-sm-10 push-sm-1 later" style="font-size: 14px;"> | ||||
<div id="chart-composite-1" class="border"><svg height=225></svg></div> | <div id="chart-composite-1" class="border"><svg height=225></svg></div> | ||||
<p class="mt-1">Use arrow keys to navigate data points</p> | |||||
<p class="mt-1">Click or use arrow keys to navigate data points</p> | |||||
</div> | </div> | ||||
<div class="col-sm-10 push-sm-1 later" style="font-size: 14px;"> | <div class="col-sm-10 push-sm-1 later" style="font-size: 14px;"> | ||||
<div id="chart-composite-2" class="border"><svg height=225></svg></div> | <div id="chart-composite-2" class="border"><svg height=225></svg></div> | ||||
@@ -46,15 +46,51 @@ | |||||
<div class="dashboard-section"> | <div class="dashboard-section"> | ||||
<h6 class="margin-vertical-rem"> | <h6 class="margin-vertical-rem"> | ||||
<!--Bars, Lines or <a href="http://www.storytellingwithdata.com/blog/2011/07/death-to-pie-charts" target="_blank">Percentages</a>--> | <!--Bars, Lines or <a href="http://www.storytellingwithdata.com/blog/2011/07/death-to-pie-charts" target="_blank">Percentages</a>--> | ||||
Create a new chart | |||||
Create a chart | |||||
</h6> | </h6> | ||||
<pre><code class="hljs html"><div id="chart"></div></code></pre> | |||||
<p class="step-explain">Include it in your HTML</p> | |||||
<pre><code class="hljs html"> <script src="frappe-charts.min.js" /></code></pre> | |||||
<p class="step-explain">Make a new Chart</p> | |||||
<pre><code class="hljs html"> <!--HTML--> | |||||
<div id="chart"></div></code></pre> | |||||
<pre><code class="hljs javascript"> // Javascript | |||||
let data = { | |||||
labels: ["12am-3am", "3am-6am", "6am-9am", "9am-12pm", | |||||
"12pm-3pm", "3pm-6pm", "6pm-9pm", "9pm-12am"], | |||||
datasets: [ | |||||
{ | |||||
title: "Some Data", color: "light-blue", | |||||
values: [25, 40, 30, 35, 8, 52, 17, -4] | |||||
}, | |||||
{ | |||||
title: "Another Set", color: "violet", | |||||
values: [25, 50, -10, 15, 18, 32, 27, 14] | |||||
}, | |||||
{ | |||||
title: "Yet Another", color: "blue", | |||||
values: [15, 20, -3, -15, 58, 12, -17, 37] | |||||
} | |||||
] | |||||
}; | |||||
let chart = new Chart({ | |||||
parent: "#chart", | |||||
title: "My Awesome Chart", | |||||
data: data, | |||||
type: 'bar', // or 'line', 'scatter', 'percentage' | |||||
height: 250 | |||||
});</code></pre> | |||||
<div id="chart-types" class="border"></div> | <div id="chart-types" class="border"></div> | ||||
<div class="btn-group chart-type-buttons margin-vertical-px mx-auto" role="group"> | <div class="btn-group chart-type-buttons margin-vertical-px mx-auto" role="group"> | ||||
<button type="button" class="btn btn-sm btn-secondary active" data-type='bar'>Bar Chart</button> | <button type="button" class="btn btn-sm btn-secondary active" data-type='bar'>Bar Chart</button> | ||||
<button type="button" class="btn btn-sm btn-secondary" data-type='line'>Line Chart</button> | <button type="button" class="btn btn-sm btn-secondary" data-type='line'>Line Chart</button> | ||||
<button type="button" class="btn btn-sm btn-secondary" data-type='scatter'>Scatter Chart</button> | |||||
<button type="button" class="btn btn-sm btn-secondary" data-type='percentage'>Percentage Chart</button> | <button type="button" class="btn btn-sm btn-secondary" data-type='percentage'>Percentage Chart</button> | ||||
</div> | </div> | ||||
<p class="text-muted"> | |||||
<a target="_blank" href="http://www.storytellingwithdata.com/blog/2011/07/death-to-pie-charts">Why Percentage?</a> | |||||
</p> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -74,6 +110,32 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="col-sm-10 push-sm-1"> | |||||
<div class="dashboard-section"> | |||||
<h6 class="margin-vertical-rem"> | |||||
Plot Trends | |||||
</h6> | |||||
<pre><code class="hljs javascript"> ... | |||||
x_axis_mode: 'tick', // for short label ticks | |||||
// or 'span' for long spanning vertical axis lines | |||||
y_axis_mode: 'tick', | |||||
...</code></pre> | |||||
<div id="chart-trends" class="border"></div> | |||||
<div class="btn-group chart-plot-buttons mt-1 mx-auto" role="group"> | |||||
<button type="button" class="btn btn-sm btn-secondary" data-update="line">Line</button> | |||||
<button type="button" class="btn btn-sm btn-secondary" data-update="heatline">HeatLine</button> | |||||
<button type="button" class="btn btn-sm btn-secondary" data-update="region">Region</button> | |||||
</div> | |||||
<pre><code class="hljs javascript margin-vertical-px"> ... | |||||
type: 'line', // Line chart specific properties: | |||||
show_dots: 0, // Show data points on the line; default 1 | |||||
heatline: 1, // Show a value-wise line gradient; default 0 | |||||
region_fill: 1, // Fill the area under the graph; default 0 | |||||
...</code></pre> | |||||
</div> | |||||
</div> | |||||
<div class="col-sm-10 push-sm-1"> | <div class="col-sm-10 push-sm-1"> | ||||
<div class="dashboard-section"> | <div class="dashboard-section"> | ||||
<h6 class="margin-vertical-rem"> | <h6 class="margin-vertical-rem"> | ||||
@@ -102,7 +164,7 @@ | |||||
<div id="chart-aggr" class="border"></div> | <div id="chart-aggr" class="border"></div> | ||||
<div class="chart-aggr-buttons mt-1 mx-auto" role="group"> | <div class="chart-aggr-buttons mt-1 mx-auto" role="group"> | ||||
<button type="button" class="btn btn-sm btn-secondary" data-aggregation="sums">Show Sums</button> | <button type="button" class="btn btn-sm btn-secondary" data-aggregation="sums">Show Sums</button> | ||||
<button type="button" class="btn btn-sm btn-secondary" data-aggregation="average">Show Average</button> | |||||
<button type="button" class="btn btn-sm btn-secondary" data-aggregation="average">Show Averages</button> | |||||
</div> | </div> | ||||
<pre><code class="hljs html margin-vertical-px"><div id="chart"></div></code></pre> | <pre><code class="hljs html margin-vertical-px"><div id="chart"></div></code></pre> | ||||
</div> | </div> | ||||
@@ -2,6 +2,7 @@ import '../styles/charts.less'; | |||||
import BarChart from './charts/BarChart'; | import BarChart from './charts/BarChart'; | ||||
import LineChart from './charts/LineChart'; | import LineChart from './charts/LineChart'; | ||||
import ScatterChart from './charts/ScatterChart'; | |||||
import PercentageChart from './charts/PercentageChart'; | import PercentageChart from './charts/PercentageChart'; | ||||
import Heatmap from './charts/Heatmap'; | import Heatmap from './charts/Heatmap'; | ||||
@@ -19,6 +20,8 @@ export default class Chart { | |||||
return new LineChart(arguments[0]); | return new LineChart(arguments[0]); | ||||
} else if(args.type === 'bar') { | } else if(args.type === 'bar') { | ||||
return new BarChart(arguments[0]); | return new BarChart(arguments[0]); | ||||
} else if(args.type === 'scatter') { | |||||
return new ScatterChart(arguments[0]); | |||||
} else if(args.type === 'percentage') { | } else if(args.type === 'percentage') { | ||||
return new PercentageChart(arguments[0]); | return new PercentageChart(arguments[0]); | ||||
} else if(args.type === 'heatmap') { | } else if(args.type === 'heatmap') { | ||||
@@ -234,13 +234,15 @@ export default class AxisChart extends BaseChart { | |||||
); | ); | ||||
} | } | ||||
make_new_units_for_dataset(x_values, y_values, color, dataset_index, no_of_datasets, group, array, unit) { | |||||
if(!group) group = this.svg_units_groups[dataset_index]; | |||||
if(!array) array = this.y[dataset_index].svg_units; | |||||
make_new_units_for_dataset(x_values, y_values, color, dataset_index, | |||||
no_of_datasets, units_group, units_array, unit) { | |||||
if(!units_group) units_group = this.svg_units_groups[dataset_index]; | |||||
if(!units_array) units_array = this.y[dataset_index].svg_units; | |||||
if(!unit) unit = this.unit_args; | if(!unit) unit = this.unit_args; | ||||
group.textContent = ''; | |||||
array.length = 0; | |||||
units_group.textContent = ''; | |||||
units_array.length = 0; | |||||
y_values.map((y, i) => { | y_values.map((y, i) => { | ||||
let data_unit = this.draw[unit.type]( | let data_unit = this.draw[unit.type]( | ||||
@@ -248,12 +250,17 @@ export default class AxisChart extends BaseChart { | |||||
y, | y, | ||||
unit.args, | unit.args, | ||||
color, | color, | ||||
i, | |||||
dataset_index, | dataset_index, | ||||
no_of_datasets | no_of_datasets | ||||
); | ); | ||||
group.appendChild(data_unit); | |||||
array.push(data_unit); | |||||
units_group.appendChild(data_unit); | |||||
units_array.push(data_unit); | |||||
}); | }); | ||||
if(this.is_navigable) { | |||||
this.bind_units(units_array); | |||||
} | |||||
} | } | ||||
make_y_specifics() { | make_y_specifics() { | ||||
@@ -952,17 +959,18 @@ export default class AxisChart extends BaseChart { | |||||
setup_utils() { | setup_utils() { | ||||
this.draw = { | this.draw = { | ||||
'bar': (x, y_top, args, color, index, no_of_datasets) => { | |||||
'bar': (x, y_top, args, color, index, dataset_index, no_of_datasets) => { | |||||
let total_width = this.avg_unit_width - args.space_width; | let total_width = this.avg_unit_width - args.space_width; | ||||
let start_x = x - total_width/2; | let start_x = x - total_width/2; | ||||
let width = total_width / no_of_datasets; | let width = total_width / no_of_datasets; | ||||
let current_x = start_x + width * index; | |||||
let current_x = start_x + width * dataset_index; | |||||
let [height, y] = this.get_bar_height_and_y_attr(y_top); | let [height, y] = this.get_bar_height_and_y_attr(y_top); | ||||
return $.createSVG('rect', { | return $.createSVG('rect', { | ||||
className: `bar mini fill ${color}`, | className: `bar mini fill ${color}`, | ||||
'data-point-index': index, | |||||
x: current_x, | x: current_x, | ||||
y: y, | y: y, | ||||
width: width, | width: width, | ||||
@@ -970,9 +978,10 @@ export default class AxisChart extends BaseChart { | |||||
}); | }); | ||||
}, | }, | ||||
'dot': (x, y, args, color) => { | |||||
'dot': (x, y, args, color, index) => { | |||||
return $.createSVG('circle', { | return $.createSVG('circle', { | ||||
className: `fill ${color}`, | className: `fill ${color}`, | ||||
'data-point-index': index, | |||||
cx: x, | cx: x, | ||||
cy: y, | cy: y, | ||||
r: args.radius | r: args.radius | ||||
@@ -44,6 +44,15 @@ export default class BarChart extends AxisChart { | |||||
}); | }); | ||||
} | } | ||||
bind_units(units_array) { | |||||
units_array.map(unit => { | |||||
unit.addEventListener('click', () => { | |||||
let index = unit.getAttribute('data-point-index'); | |||||
this.update_current_data_point(index); | |||||
}); | |||||
}); | |||||
} | |||||
update_overlay(unit) { | update_overlay(unit) { | ||||
let attributes = []; | let attributes = []; | ||||
Object.keys(unit.attributes).map(index => { | Object.keys(unit.attributes).map(index => { | ||||
@@ -1,5 +1,6 @@ | |||||
import SvgTip from '../objects/SvgTip'; | import SvgTip from '../objects/SvgTip'; | ||||
import $ from '../helpers/dom'; | import $ from '../helpers/dom'; | ||||
import Chart from '../charts'; | |||||
export default class BaseChart { | export default class BaseChart { | ||||
constructor({ | constructor({ | ||||
@@ -36,7 +37,7 @@ export default class BaseChart { | |||||
} | } | ||||
this.has_legend = has_legend; | this.has_legend = has_legend; | ||||
this.chart_types = ['line', 'bar', 'percentage', 'heatmap']; | |||||
this.chart_types = ['line', 'scatter', 'bar', 'percentage', 'heatmap']; | |||||
this.set_margins(height); | this.set_margins(height); | ||||
} | } | ||||
@@ -49,9 +50,10 @@ export default class BaseChart { | |||||
// Only across compatible types | // Only across compatible types | ||||
let compatible_types = { | let compatible_types = { | ||||
bar: ['line', 'percentage'], | |||||
line: ['bar', 'percentage'], | |||||
percentage: ['bar', 'line'], | |||||
bar: ['line', 'scatter', 'percentage'], | |||||
line: ['scatter', 'bar', 'percentage'], | |||||
scatter: ['line', 'bar', 'percentage'], | |||||
percentage: ['bar', 'line', 'scatter'], | |||||
heatmap: [] | heatmap: [] | ||||
}; | }; | ||||
@@ -62,8 +64,9 @@ export default class BaseChart { | |||||
// Okay, this is anticlimactic | // Okay, this is anticlimactic | ||||
// this function will need to actually be 'change_chart_type(type)' | // this function will need to actually be 'change_chart_type(type)' | ||||
// that will update only the required elements, but for now ... | // that will update only the required elements, but for now ... | ||||
return new BaseChart({ | |||||
return new Chart({ | |||||
parent: this.raw_chart_args.parent, | parent: this.raw_chart_args.parent, | ||||
title: this.title, | |||||
data: this.raw_chart_args.data, | data: this.raw_chart_args.data, | ||||
type: type, | type: type, | ||||
height: this.raw_chart_args.height | height: this.raw_chart_args.height | ||||
@@ -127,7 +130,7 @@ export default class BaseChart { | |||||
setup_container() { | setup_container() { | ||||
this.container = $.create('div', { | this.container = $.create('div', { | ||||
className: 'chart-container', | className: 'chart-container', | ||||
innerHTML: `<h6 class="title" style="margin-top: 15px;">${this.title}</h6> | |||||
innerHTML: `<h6 class="title">${this.title}</h6> | |||||
<h6 class="sub-title uppercase">${this.subtitle}</h6> | <h6 class="sub-title uppercase">${this.subtitle}</h6> | ||||
<div class="frappe-chart graphics"></div> | <div class="frappe-chart graphics"></div> | ||||
<div class="graph-stats-container"></div>` | <div class="graph-stats-container"></div>` | ||||
@@ -216,6 +219,7 @@ export default class BaseChart { | |||||
make_overlay() {} | make_overlay() {} | ||||
bind_overlay() {} | bind_overlay() {} | ||||
bind_units() {} | |||||
on_left_arrow() {} | on_left_arrow() {} | ||||
on_right_arrow() {} | on_right_arrow() {} | ||||
@@ -238,6 +242,7 @@ export default class BaseChart { | |||||
} | } | ||||
update_current_data_point(index) { | update_current_data_point(index) { | ||||
index = parseInt(index); | |||||
if(index < 0) index = 0; | if(index < 0) index = 0; | ||||
if(index >= this.x.length) index = this.x.length - 1; | if(index >= this.x.length) index = this.x.length - 1; | ||||
if(index === this.current_index) return; | if(index === this.current_index) return; | ||||
@@ -4,14 +4,23 @@ import $ from '../helpers/dom'; | |||||
export default class LineChart extends AxisChart { | export default class LineChart extends AxisChart { | ||||
constructor(args) { | constructor(args) { | ||||
super(args); | super(args); | ||||
this.x_axis_mode = args.x_axis_mode || 'span'; | |||||
this.y_axis_mode = args.y_axis_mode || 'span'; | |||||
if(args.hasOwnProperty('show_dots')) { | |||||
this.show_dots = args.show_dots; | |||||
} else { | |||||
this.show_dots = 1; | |||||
} | |||||
this.region_fill = args.region_fill; | |||||
if(Object.getPrototypeOf(this) !== LineChart.prototype) { | if(Object.getPrototypeOf(this) !== LineChart.prototype) { | ||||
return; | return; | ||||
} | } | ||||
this.dot_radius = args.dot_radius || 4; | |||||
this.heatline = args.heatline; | |||||
this.type = 'line'; | this.type = 'line'; | ||||
this.region_fill = args.region_fill; | |||||
this.x_axis_mode = args.x_axis_mode || 'span'; | |||||
this.y_axis_mode = args.y_axis_mode || 'span'; | |||||
this.setup(); | this.setup(); | ||||
} | } | ||||
@@ -35,10 +44,18 @@ export default class LineChart extends AxisChart { | |||||
super.setup_values(); | super.setup_values(); | ||||
this.unit_args = { | this.unit_args = { | ||||
type: 'dot', | type: 'dot', | ||||
args: { radius: 8 } | |||||
args: { radius: this.dot_radius } | |||||
}; | }; | ||||
} | } | ||||
make_new_units_for_dataset(x_values, y_values, color, dataset_index, | |||||
no_of_datasets, units_group, units_array, unit) { | |||||
if(this.show_dots) { | |||||
super.make_new_units_for_dataset(x_values, y_values, color, dataset_index, | |||||
no_of_datasets, units_group, units_array, unit); | |||||
} | |||||
} | |||||
make_paths() { | make_paths() { | ||||
this.y.map((d, i) => { | this.y.map((d, i) => { | ||||
this.make_path(d, i, this.x_axis_positions, d.y_tops, d.color || this.colors[i]); | this.make_path(d, i, this.x_axis_positions, d.y_tops, d.color || this.colors[i]); | ||||
@@ -57,39 +74,60 @@ export default class LineChart extends AxisChart { | |||||
d: "M"+points_str | d: "M"+points_str | ||||
}); | }); | ||||
if(this.heatline) { | |||||
let gradient_id = this.make_gradient(color); | |||||
d.path.style.stroke = `url(#${gradient_id})`; | |||||
} | |||||
if(this.region_fill) { | if(this.region_fill) { | ||||
let gradient_id ='path-fill-gradient' + '-' + color; | |||||
this.gradient_def = $.createSVG('linearGradient', { | |||||
inside: this.svg_defs, | |||||
id: gradient_id, | |||||
x1: 0, | |||||
x2: 0, | |||||
y1: 0, | |||||
y2: 1 | |||||
}); | |||||
this.fill_region_for_dataset(d, i, color, points_str); | |||||
} | |||||
} | |||||
fill_region_for_dataset(d, i, color, points_str) { | |||||
let gradient_id = this.make_gradient(color, true); | |||||
d.region_path = $.createSVG('path', { | |||||
inside: this.paths_groups[i], | |||||
className: `region-fill`, | |||||
d: "M" + `0,${this.zero_line}L` + points_str + `L${this.width},${this.zero_line}`, | |||||
}); | |||||
d.region_path.style.stroke = "none"; | |||||
d.region_path.style.fill = `url(#${gradient_id})`; | |||||
} | |||||
make_gradient(color, lighter = false) { | |||||
let gradient_id ='path-fill-gradient' + '-' + color; | |||||
let gradient_def = $.createSVG('linearGradient', { | |||||
inside: this.svg_defs, | |||||
id: gradient_id, | |||||
x1: 0, | |||||
x2: 0, | |||||
y1: 0, | |||||
y2: 1 | |||||
}); | |||||
let set_gradient_stop = (grad_elem, offset, color, opacity) => { | |||||
$.createSVG('stop', { | |||||
'className': 'stop-color ' + color, | |||||
'inside': grad_elem, | |||||
'offset': offset, | |||||
'stop-opacity': opacity | |||||
}); | |||||
}; | |||||
set_gradient_stop(this.gradient_def, "0%", color, 0.4); | |||||
set_gradient_stop(this.gradient_def, "50%", color, 0.2); | |||||
set_gradient_stop(this.gradient_def, "100%", color, 0); | |||||
d.region_path = $.createSVG('path', { | |||||
inside: this.paths_groups[i], | |||||
className: `region-fill`, | |||||
d: "M" + `0,${this.zero_line}L` + points_str + `L${this.width},${this.zero_line}`, | |||||
let set_gradient_stop = (grad_elem, offset, color, opacity) => { | |||||
$.createSVG('stop', { | |||||
'className': 'stop-color ' + color, | |||||
'inside': grad_elem, | |||||
'offset': offset, | |||||
'stop-opacity': opacity | |||||
}); | }); | ||||
}; | |||||
let opacities = [1, 0.6, 0.2]; | |||||
d.region_path.style.stroke = "none"; | |||||
d.region_path.style.fill = `url(#${gradient_id})`; | |||||
if(lighter) { | |||||
opacities = [0.4, 0.2, 0]; | |||||
} | } | ||||
set_gradient_stop(gradient_def, "0%", color, opacities[0]); | |||||
set_gradient_stop(gradient_def, "50%", color, opacities[1]); | |||||
set_gradient_stop(gradient_def, "100%", color, opacities[2]); | |||||
return gradient_id; | |||||
} | } | ||||
} | } |
@@ -0,0 +1,35 @@ | |||||
import LineChart from './LineChart'; | |||||
export default class ScatterChart extends LineChart { | |||||
constructor(args) { | |||||
super(args); | |||||
this.type = 'scatter'; | |||||
if(!args.dot_radius) { | |||||
this.dot_radius = 8; | |||||
} else { | |||||
this.dot_radius = args.dot_radius; | |||||
} | |||||
this.setup(); | |||||
} | |||||
setup_graph_components() { | |||||
this.setup_path_groups(); | |||||
super.setup_graph_components(); | |||||
} | |||||
setup_path_groups() {} | |||||
setup_values() { | |||||
super.setup_values(); | |||||
this.unit_args = { | |||||
type: 'dot', | |||||
args: { radius: this.dot_radius } | |||||
}; | |||||
} | |||||
make_paths() {} | |||||
make_path() {} | |||||
} |
@@ -3,6 +3,15 @@ | |||||
.graph-focus-margin { | .graph-focus-margin { | ||||
margin: 0px 5%; | margin: 0px 5%; | ||||
} | } | ||||
&>.title { | |||||
margin-top: 25px; | |||||
margin-left: 25px; | |||||
text-align: left; | |||||
text-transform: uppercase; | |||||
font-weight: normal; | |||||
font-size: 12px; | |||||
color: #6c7680; | |||||
} | |||||
.graphics { | .graphics { | ||||
margin-top: 10px; | margin-top: 10px; | ||||
padding-top: 10px; | padding-top: 10px; | ||||
@@ -39,7 +48,7 @@ | |||||
} | } | ||||
} | } | ||||
.axis, .chart-label { | .axis, .chart-label { | ||||
font-size: 10px; | |||||
font-size: 11px; | |||||
fill: #555b51; | fill: #555b51; | ||||
line { | line { | ||||
stroke: #dadada; | stroke: #dadada; | ||||
@@ -127,10 +136,12 @@ | |||||
li { | li { | ||||
min-width: 90px; | min-width: 90px; | ||||
flex: 1; | flex: 1; | ||||
font-weight: 600; | |||||
} | } | ||||
} | } | ||||
strong { | strong { | ||||
color: #dfe2e5; | color: #dfe2e5; | ||||
font-weight: 600; | |||||
} | } | ||||
.svg-pointer { | .svg-pointer { | ||||
position: absolute; | position: absolute; | ||||