/* ------------------------------------------------------------------------------
*
* # Statistics widgets
*
* Demo JS code for widgets_stats.html page
*
* ---------------------------------------------------------------------------- */
// Setup module
// ------------------------------
var StatisticWidgets = function() {
//
// Setup module components
//
// Messages area chart
var _areaChartWidget = function(element, chartHeight, color) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Basic setup
// ------------------------------
// Define main variables
var d3Container = d3.select(element),
margin = {top: 0, right: 0, bottom: 0, left: 0},
width = d3Container.node().getBoundingClientRect().width - margin.left - margin.right,
height = chartHeight - margin.top - margin.bottom;
// Date and time format
var parseDate = d3.time.format('%Y-%m-%d').parse;
// Create SVG
// ------------------------------
// Container
var container = d3Container.append('svg');
// SVG element
var svg = container
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Construct chart layout
// ------------------------------
// Area
var area = d3.svg.area()
.x(function(d) { return x(d.date); })
.y0(height)
.y1(function(d) { return y(d.value); })
.interpolate('monotone');
// Construct scales
// ------------------------------
// Horizontal
var x = d3.time.scale().range([0, width ]);
// Vertical
var y = d3.scale.linear().range([height, 0]);
// Load data
// ------------------------------
d3.json("../../../../global_assets/demo_data/dashboard/monthly_sales.json", function (error, data) {
// Show what's wrong if error
if (error) return console.error(error);
// Pull out values
data.forEach(function (d) {
d.date = parseDate(d.date);
d.value = +d.value;
});
// Get the maximum value in the given array
var maxY = d3.max(data, function(d) { return d.value; });
// Reset start data for animation
var startData = data.map(function(datum) {
return {
date: datum.date,
value: 0
};
});
// Set input domains
// ------------------------------
// Horizontal
x.domain(d3.extent(data, function(d, i) { return d.date; }));
// Vertical
y.domain([0, d3.max( data, function(d) { return d.value; })]);
//
// Append chart elements
//
// Add area path
svg.append("path")
.datum(data)
.attr("class", "d3-area")
.style('fill', color)
.attr("d", area)
.transition() // begin animation
.duration(1000)
.attrTween('d', function() {
var interpolator = d3.interpolateArray(startData, data);
return function (t) {
return area(interpolator (t));
};
});
// Resize chart
// ------------------------------
// Call function on window resize
$(window).on('resize', messagesAreaResize);
// Call function on sidebar width change
$(document).on('click', '.sidebar-control', messagesAreaResize);
// Resize function
//
// Since D3 doesn't support SVG resize by default,
// we need to manually specify parts of the graph that need to
// be updated on window resize
function messagesAreaResize() {
// Layout variables
width = d3Container.node().getBoundingClientRect().width - margin.left - margin.right;
// Layout
// -------------------------
// Main svg width
container.attr("width", width + margin.left + margin.right);
// Width of appended group
svg.attr("width", width + margin.left + margin.right);
// Horizontal range
x.range([0, width]);
// Chart elements
// -------------------------
// Area path
svg.selectAll('.d3-area').datum( data ).attr("d", area);
}
});
}
};
// Simple bar charts
var _barChartWidget = function(element, barQty, height, animate, easing, duration, delay, color, tooltip) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Basic setup
// ------------------------------
// Add data set
var bardata = [];
for (var i=0; i < barQty; i++) {
bardata.push(Math.round(Math.random() * 10) + 10);
}
// Main variables
var d3Container = d3.select(element),
width = d3Container.node().getBoundingClientRect().width;
// Construct scales
// ------------------------------
// Horizontal
var x = d3.scale.ordinal()
.rangeBands([0, width], 0.3);
// Vertical
var y = d3.scale.linear()
.range([0, height]);
// Set input domains
// ------------------------------
// Horizontal
x.domain(d3.range(0, bardata.length));
// Vertical
y.domain([0, d3.max(bardata)]);
// Create chart
// ------------------------------
// Add svg element
var container = d3Container.append('svg');
// Add SVG group
var svg = container
.attr('width', width)
.attr('height', height)
.append('g');
//
// Append chart elements
//
// Bars
var bars = svg.selectAll('rect')
.data(bardata)
.enter()
.append('rect')
.attr('class', 'd3-random-bars')
.attr('width', x.rangeBand())
.attr('x', function(d,i) {
return x(i);
})
.style('fill', color);
// Tooltip
// ------------------------------
// Initiate
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0]);
// Show and hide
if(tooltip == "hours" || tooltip == "goal" || tooltip == "members") {
bars.call(tip)
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
}
// Daily meetings tooltip content
if(tooltip == "hours") {
tip.html(function (d, i) {
return "
" +
"
" + d + "
" +
"
meetings" +
"
" + i + ":00" + "
" +
"
";
});
}
// Statements tooltip content
if(tooltip == "goal") {
tip.html(function (d, i) {
return "" +
"
" + d + "
" +
"
statements" +
"
" + i + ":00" + "
" +
"
";
});
}
// Online members tooltip content
if(tooltip == "members") {
tip.html(function (d, i) {
return "" +
"
" + d + "0" + "
" +
"
members" +
"
" + i + ":00" + "
" +
"
";
});
}
// Bar loading animation
// ------------------------------
// Choose between animated or static
if(animate) {
withAnimation();
} else {
withoutAnimation();
}
// Animate on load
function withAnimation() {
bars
.attr('height', 0)
.attr('y', height)
.transition()
.attr('height', function(d) {
return y(d);
})
.attr('y', function(d) {
return height - y(d);
})
.delay(function(d, i) {
return i * delay;
})
.duration(duration)
.ease(easing);
}
// Load without animateion
function withoutAnimation() {
bars
.attr('height', function(d) {
return y(d);
})
.attr('y', function(d) {
return height - y(d);
});
}
// Resize chart
// ------------------------------
// Call function on window resize
$(window).on('resize', barsResize);
// Call function on sidebar width change
$(document).on('click', '.sidebar-control', barsResize);
// Resize function
//
// Since D3 doesn't support SVG resize by default,
// we need to manually specify parts of the graph that need to
// be updated on window resize
function barsResize() {
// Layout variables
width = d3Container.node().getBoundingClientRect().width;
// Layout
// -------------------------
// Main svg width
container.attr("width", width);
// Width of appended group
svg.attr("width", width);
// Horizontal range
x.rangeBands([0, width], 0.3);
// Chart elements
// -------------------------
// Bars
svg.selectAll('.d3-random-bars')
.attr('width', x.rangeBand())
.attr('x', function(d,i) {
return x(i);
});
}
}
};
// Simple line chart
var _lineChartWidget = function(element, chartHeight, lineColor, pathColor, pointerLineColor, pointerBgColor) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Basic setup
// ------------------------------
// Add data set
var dataset = [
{
"date": "04/13/14",
"alpha": "60"
}, {
"date": "04/14/14",
"alpha": "35"
}, {
"date": "04/15/14",
"alpha": "65"
}, {
"date": "04/16/14",
"alpha": "50"
}, {
"date": "04/17/14",
"alpha": "65"
}, {
"date": "04/18/14",
"alpha": "20"
}, {
"date": "04/19/14",
"alpha": "60"
}
];
// Main variables
var d3Container = d3.select(element),
margin = {top: 0, right: 0, bottom: 0, left: 0},
width = d3Container.node().getBoundingClientRect().width - margin.left - margin.right,
height = chartHeight - margin.top - margin.bottom,
padding = 20;
// Format date
var parseDate = d3.time.format("%m/%d/%y").parse,
formatDate = d3.time.format("%a, %B %e");
// Add tooltip
// ------------------------------
var tooltip = d3.tip()
.attr('class', 'd3-tip')
.html(function (d) {
return "";
});
// Create chart
// ------------------------------
// Add svg element
var container = d3Container.append('svg');
// Add SVG group
var svg = container
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(tooltip);
// Load data
// ------------------------------
dataset.forEach(function (d) {
d.date = parseDate(d.date);
d.alpha = +d.alpha;
});
// Construct scales
// ------------------------------
// Horizontal
var x = d3.time.scale()
.range([padding, width - padding]);
// Vertical
var y = d3.scale.linear()
.range([height, 5]);
// Set input domains
// ------------------------------
// Horizontal
x.domain(d3.extent(dataset, function (d) {
return d.date;
}));
// Vertical
y.domain([0, d3.max(dataset, function (d) {
return Math.max(d.alpha);
})]);
// Construct chart layout
// ------------------------------
// Line
var line = d3.svg.line()
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.alpha);
});
//
// Append chart elements
//
// Add mask for animation
// ------------------------------
// Add clip path
var clip = svg.append("defs")
.append("clipPath")
.attr("id", "clip-line-small");
// Add clip shape
var clipRect = clip.append("rect")
.attr('class', 'clip')
.attr("width", 0)
.attr("height", height);
// Animate mask
clipRect
.transition()
.duration(1000)
.ease('linear')
.attr("width", width);
// Line
// ------------------------------
// Path
var path = svg.append('path')
.attr({
'd': line(dataset),
"clip-path": "url(#clip-line-small)",
'class': 'd3-line d3-line-medium'
})
.style('stroke', lineColor);
// Animate path
svg.select('.line-tickets')
.transition()
.duration(1000)
.ease('linear');
// Add vertical guide lines
// ------------------------------
// Bind data
var guide = svg.append('g')
.selectAll('.d3-line-guides-group')
.data(dataset);
// Append lines
guide
.enter()
.append('line')
.attr('class', 'd3-line-guides')
.attr('x1', function (d, i) {
return x(d.date);
})
.attr('y1', function (d, i) {
return height;
})
.attr('x2', function (d, i) {
return x(d.date);
})
.attr('y2', function (d, i) {
return height;
})
.style('stroke', pathColor)
.style('stroke-dasharray', '4,2')
.style('shape-rendering', 'crispEdges');
// Animate guide lines
guide
.transition()
.duration(1000)
.delay(function(d, i) { return i * 150; })
.attr('y2', function (d, i) {
return y(d.alpha);
});
// Alpha app points
// ------------------------------
// Add points
var points = svg.insert('g')
.selectAll('.d3-line-circle')
.data(dataset)
.enter()
.append('circle')
.attr('class', 'd3-line-circle d3-line-circle-medium')
.attr("cx", line.x())
.attr("cy", line.y())
.attr("r", 3)
.style({
'stroke': pointerLineColor,
'fill': pointerBgColor
});
// Animate points on page load
points
.style('opacity', 0)
.transition()
.duration(250)
.ease('linear')
.delay(1000)
.style('opacity', 1);
// Add user interaction
points
.on("mouseover", function (d) {
tooltip.offset([-10, 0]).show(d);
// Animate circle radius
d3.select(this).transition().duration(250).attr('r', 4);
})
// Hide tooltip
.on("mouseout", function (d) {
tooltip.hide(d);
// Animate circle radius
d3.select(this).transition().duration(250).attr('r', 3);
});
// Change tooltip direction of first point
d3.select(points[0][0])
.on("mouseover", function (d) {
tooltip.offset([0, 10]).direction('e').show(d);
// Animate circle radius
d3.select(this).transition().duration(250).attr('r', 4);
})
.on("mouseout", function (d) {
tooltip.direction('n').hide(d);
// Animate circle radius
d3.select(this).transition().duration(250).attr('r', 3);
});
// Change tooltip direction of last point
d3.select(points[0][points.size() - 1])
.on("mouseover", function (d) {
tooltip.offset([0, -10]).direction('w').show(d);
// Animate circle radius
d3.select(this).transition().duration(250).attr('r', 4);
})
.on("mouseout", function (d) {
tooltip.direction('n').hide(d);
// Animate circle radius
d3.select(this).transition().duration(250).attr('r', 3);
});
// Resize chart
// ------------------------------
// Call function on window resize
$(window).on('resize', lineChartResize);
// Call function on sidebar width change
$(document).on('click', '.sidebar-control', lineChartResize);
// Resize function
//
// Since D3 doesn't support SVG resize by default,
// we need to manually specify parts of the graph that need to
// be updated on window resize
function lineChartResize() {
// Layout variables
width = d3Container.node().getBoundingClientRect().width - margin.left - margin.right;
// Layout
// -------------------------
// Main svg width
container.attr("width", width + margin.left + margin.right);
// Width of appended group
svg.attr("width", width + margin.left + margin.right);
// Horizontal range
x.range([padding, width - padding]);
// Chart elements
// -------------------------
// Mask
clipRect.attr("width", width);
// Line path
svg.selectAll('.d3-line').attr("d", line(dataset));
// Circles
svg.selectAll('.d3-line-circle').attr("cx", line.x());
// Guide lines
svg.selectAll('.d3-line-guides')
.attr('x1', function (d, i) {
return x(d.date);
})
.attr('x2', function (d, i) {
return x(d.date);
});
}
}
};
// Simple sparklines
var _sparklinesWidget = function(element, chartType, qty, chartHeight, interpolation, duration, interval, color) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Basic setup
// ------------------------------
// Define main variables
var d3Container = d3.select(element),
margin = {top: 0, right: 0, bottom: 0, left: 0},
width = d3Container.node().getBoundingClientRect().width - margin.left - margin.right,
height = chartHeight - margin.top - margin.bottom;
// Generate random data (for demo only)
var data = [];
for (var i=0; i < qty; i++) {
data.push(Math.floor(Math.random() * qty) + 5);
}
// Construct scales
// ------------------------------
// Horizontal
var x = d3.scale.linear().range([0, width]);
// Vertical
var y = d3.scale.linear().range([height - 5, 5]);
// Set input domains
// ------------------------------
// Horizontal
x.domain([1, qty - 3]);
// Vertical
y.domain([0, qty]);
// Construct chart layout
// ------------------------------
// Line
var line = d3.svg.line()
.interpolate(interpolation)
.x(function(d, i) { return x(i); })
.y(function(d, i) { return y(d); });
// Area
var area = d3.svg.area()
.interpolate(interpolation)
.x(function(d,i) {
return x(i);
})
.y0(height)
.y1(function(d) {
return y(d);
});
// Create SVG
// ------------------------------
// Container
var container = d3Container.append('svg');
// SVG element
var svg = container
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Add mask for animation
// ------------------------------
// Add clip path
var clip = svg.append("defs")
.append("clipPath")
.attr('id', function(d, i) { return "load-clip-" + element.substring(1); });
// Add clip shape
var clips = clip.append("rect")
.attr('class', 'load-clip')
.attr("width", 0)
.attr("height", height);
// Animate mask
clips
.transition()
.duration(1000)
.ease('linear')
.attr("width", width);
//
// Append chart elements
//
// Main path
var path = svg.append("g")
.attr("clip-path", function(d, i) { return "url(#load-clip-" + element.substring(1) + ")"; })
.append("path")
.datum(data)
.attr("transform", "translate(" + x(0) + ",0)");
// Add path based on chart type
if(chartType == "area") {
path.attr("d", area).attr('class', 'd3-area').style("fill", color); // area
}
else {
path.attr("d", line).attr("class", "d3-line d3-line-medium").style('stroke', color); // line
}
// Animate path
path
.style('opacity', 0)
.transition()
.duration(500)
.style('opacity', 1);
// Set update interval. For demo only
// ------------------------------
setInterval(function() {
// push a new data point onto the back
data.push(Math.floor(Math.random() * qty) + 5);
// pop the old data point off the front
data.shift();
update();
}, interval);
// Update random data. For demo only
// ------------------------------
function update() {
// Redraw the path and slide it to the left
path
.attr("transform", null)
.transition()
.duration(duration)
.ease("linear")
.attr("transform", "translate(" + x(0) + ",0)");
// Update path type
if(chartType == "area") {
path.attr("d", area).attr('class', 'd3-area').style("fill", color);
}
else {
path.attr("d", line).attr("class", "d3-line d3-line-medium").style('stroke', color);
}
}
// Resize chart
// ------------------------------
// Call function on window resize
$(window).on('resize', resizeSparklines);
// Call function on sidebar width change
$(document).on('click', '.sidebar-control', resizeSparklines);
// Resize function
//
// Since D3 doesn't support SVG resize by default,
// we need to manually specify parts of the graph that need to
// be updated on window resize
function resizeSparklines() {
// Layout variables
width = d3Container.node().getBoundingClientRect().width - margin.left - margin.right;
// Layout
// -------------------------
// Main svg width
container.attr("width", width + margin.left + margin.right);
// Width of appended group
svg.attr("width", width + margin.left + margin.right);
// Horizontal range
x.range([0, width]);
// Chart elements
// -------------------------
// Clip mask
clips.attr("width", width);
// Line
svg.select(".d3-line").attr("d", line);
// Area
svg.select(".d3-area").attr("d", area);
}
}
};
// Animated progress with icon
var _progressIcon = function(element, radius, border, backgroundColor, foregroundColor, end, iconClass) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Basic setup
// ------------------------------
// Main variables
var d3Container = d3.select(element),
startPercent = 0,
iconSize = 32,
endPercent = end,
twoPi = Math.PI * 2,
formatPercent = d3.format('.0%'),
boxSize = radius * 2;
// Values count
var count = Math.abs((endPercent - startPercent) / 0.01);
// Values step
var step = endPercent < startPercent ? -0.01 : 0.01;
// Create chart
// ------------------------------
// Add SVG element
var container = d3Container.append('svg');
// Add SVG group
var svg = container
.attr('width', boxSize)
.attr('height', boxSize)
.append('g')
.attr('transform', 'translate(' + (boxSize / 2) + ',' + (boxSize / 2) + ')');
// Construct chart layout
// ------------------------------
// Arc
var arc = d3.svg.arc()
.startAngle(0)
.innerRadius(radius)
.outerRadius(radius - border)
.cornerRadius(20);
//
// Append chart elements
//
// Paths
// ------------------------------
// Background path
svg.append('path')
.attr('class', 'd3-progress-background')
.attr('d', arc.endAngle(twoPi))
.style('fill', backgroundColor);
// Foreground path
var foreground = svg.append('path')
.attr('class', 'd3-progress-foreground')
.attr('filter', 'url(#blur)')
.style({
'fill': foregroundColor,
'stroke': foregroundColor
});
// Front path
var front = svg.append('path')
.attr('class', 'd3-progress-front')
.style({
'fill': foregroundColor,
'fill-opacity': 1
});
// Text
// ------------------------------
// Percentage text value
var numberText = d3.select('.progress-percentage')
.attr('class', 'pt-1 mt-2 mb-1');
// Icon
d3.select(element)
.append("i")
.attr("class", iconClass + " counter-icon")
.style({
'color': foregroundColor,
'top': ((boxSize - iconSize) / 2) + 'px'
});
// Animation
// ------------------------------
// Animate path
function updateProgress(progress) {
foreground.attr('d', arc.endAngle(twoPi * progress));
front.attr('d', arc.endAngle(twoPi * progress));
numberText.text(formatPercent(progress));
}
// Animate text
var progress = startPercent;
(function loops() {
updateProgress(progress);
if (count > 0) {
count--;
progress += step;
setTimeout(loops, 10);
}
})();
}
};
// Animated progress with percentage count
var _progressPercentage = function(element, radius, border, backgroundColor, foregroundColor, end) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Basic setup
// ------------------------------
// Main variables
var d3Container = d3.select(element),
startPercent = 0,
fontSize = 22,
endPercent = end,
twoPi = Math.PI * 2,
formatPercent = d3.format('.0%'),
boxSize = radius * 2;
// Values count
var count = Math.abs((endPercent - startPercent) / 0.01);
// Values step
var step = endPercent < startPercent ? -0.01 : 0.01;
// Create chart
// ------------------------------
// Add SVG element
var container = d3Container.append('svg');
// Add SVG group
var svg = container
.attr('width', boxSize)
.attr('height', boxSize)
.append('g')
.attr('transform', 'translate(' + radius + ',' + radius + ')');
// Construct chart layout
// ------------------------------
// Arc
var arc = d3.svg.arc()
.startAngle(0)
.innerRadius(radius)
.outerRadius(radius - border)
.cornerRadius(20);
//
// Append chart elements
//
// Paths
// ------------------------------
// Background path
svg.append('path')
.attr('class', 'd3-progress-background')
.attr('d', arc.endAngle(twoPi))
.style('fill', backgroundColor);
// Foreground path
var foreground = svg.append('path')
.attr('class', 'd3-progress-foreground')
.attr('filter', 'url(#blur)')
.style({
'fill': foregroundColor,
'stroke': foregroundColor
});
// Front path
var front = svg.append('path')
.attr('class', 'd3-progress-front')
.style({
'fill': foregroundColor,
'fill-opacity': 1
});
// Text
// ------------------------------
// Percentage text value
var numberText = svg
.append('text')
.attr('dx', 0)
.attr('dy', (fontSize / 2) - border)
.style({
'font-size': fontSize + 'px',
'line-height': 1,
'fill': foregroundColor,
'text-anchor': 'middle'
});
// Animation
// ------------------------------
// Animate path
function updateProgress(progress) {
foreground.attr('d', arc.endAngle(twoPi * progress));
front.attr('d', arc.endAngle(twoPi * progress));
numberText.text(formatPercent(progress));
}
// Animate text
var progress = startPercent;
(function loops() {
updateProgress(progress);
if (count > 0) {
count--;
progress += step;
setTimeout(loops, 10);
}
})();
}
};
// Simple pie
var _animatedPie = function(element, size) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Add data set
var data = [
{
"status": "Pending tickets",
"icon": "",
"value": 938,
"color": "#29B6F6"
}, {
"status": "Resolved tickets",
"icon": "",
"value": 490,
"color": "#66BB6A"
}, {
"status": "Closed tickets",
"icon": "",
"value": 789,
"color": "#EF5350"
}
];
// Main variables
var d3Container = d3.select(element),
distance = 2, // reserve 2px space for mouseover arc moving
radius = (size/2) - distance,
sum = d3.sum(data, function(d) { return d.value; });
// Tooltip
// ------------------------------
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.direction('e')
.html(function (d) {
return "";
});
// Create chart
// ------------------------------
// Add svg element
var container = d3Container.append("svg").call(tip);
// Add SVG group
var svg = container
.attr("width", size)
.attr("height", size)
.append("g")
.attr("transform", "translate(" + (size / 2) + "," + (size / 2) + ")");
// Construct chart layout
// ------------------------------
// Pie
var pie = d3.layout.pie()
.sort(null)
.startAngle(Math.PI)
.endAngle(3 * Math.PI)
.value(function (d) {
return d.value;
});
// Arc
var arc = d3.svg.arc()
.outerRadius(radius);
//
// Append chart elements
//
// Group chart elements
var arcGroup = svg.selectAll(".d3-arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "d3-arc")
.style({
'stroke': '#fff',
'stroke-width': 2,
'cursor': 'pointer'
});
// Append path
var arcPath = arcGroup
.append("path")
.style("fill", function (d) {
return d.data.color;
});
// Add tooltip
arcPath
.on('mouseover', function (d, i) {
// Transition on mouseover
d3.select(this)
.transition()
.duration(500)
.ease('elastic')
.attr('transform', function (d) {
d.midAngle = ((d.endAngle - d.startAngle) / 2) + d.startAngle;
var x = Math.sin(d.midAngle) * distance;
var y = -Math.cos(d.midAngle) * distance;
return 'translate(' + x + ',' + y + ')';
});
})
.on("mousemove", function (d) {
// Show tooltip on mousemove
tip.show(d)
.style("top", (d3.event.pageY - 40) + "px")
.style("left", (d3.event.pageX + 30) + "px");
})
.on('mouseout', function (d, i) {
// Mouseout transition
d3.select(this)
.transition()
.duration(500)
.ease('bounce')
.attr('transform', 'translate(0,0)');
// Hide tooltip
tip.hide(d);
});
// Animate chart on load
arcPath
.transition()
.delay(function(d, i) { return i * 500; })
.duration(500)
.attrTween("d", function(d) {
var interpolate = d3.interpolate(d.startAngle,d.endAngle);
return function(t) {
d.endAngle = interpolate(t);
return arc(d);
};
});
//
// Append counter
//
// Append element
d3Container
.append('h2')
.attr('class', 'pt-1 mt-2 mb-1 font-weight-semibold');
// Animate counter
d3Container.select('h2')
.transition()
.duration(1500)
.tween("text", function(d) {
var i = d3.interpolate(this.textContent, sum);
return function(t) {
this.textContent = d3.format(",d")(Math.round(i(t)));
};
});
}
};
// Pie with legend
var _animatedPieWithLegend = function(element, size) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Add data set
var data = [
{
"status": "New",
"value": 578,
"color": "#29B6F6"
}, {
"status": "Pending",
"value": 983,
"color": "#66BB6A"
}, {
"status": "Shipped",
"value": 459,
"color": "#EF5350"
}
];
// Main variables
var d3Container = d3.select(element),
distance = 2, // reserve 2px space for mouseover arc moving
radius = (size/2) - distance,
sum = d3.sum(data, function(d) { return d.value; });
// Create chart
// ------------------------------
// Add svg element
var container = d3Container.append("svg");
// Add SVG group
var svg = container
.attr("width", size)
.attr("height", size)
.append("g")
.attr("transform", "translate(" + (size / 2) + "," + (size / 2) + ")");
// Construct chart layout
// ------------------------------
// Pie
var pie = d3.layout.pie()
.sort(null)
.startAngle(Math.PI)
.endAngle(3 * Math.PI)
.value(function (d) {
return d.value;
});
// Arc
var arc = d3.svg.arc()
.outerRadius(radius);
//
// Append chart elements
//
// Group chart elements
var arcGroup = svg.selectAll(".d3-arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "d3-arc")
.style({
'stroke': '#fff',
'stroke-width': 2,
'cursor': 'pointer'
});
// Append path
var arcPath = arcGroup
.append("path")
.style("fill", function (d) {
return d.data.color;
});
// Add interactions
arcPath
.on('mouseover', function (d, i) {
// Transition on mouseover
d3.select(this)
.transition()
.duration(500)
.ease('elastic')
.attr('transform', function (d) {
d.midAngle = ((d.endAngle - d.startAngle) / 2) + d.startAngle;
var x = Math.sin(d.midAngle) * distance;
var y = -Math.cos(d.midAngle) * distance;
return 'translate(' + x + ',' + y + ')';
});
// Animate legend
$(element + ' [data-slice]').css({
'opacity': 0.3,
'transition': 'all ease-in-out 0.15s'
});
$(element + ' [data-slice=' + i + ']').css({'opacity': 1});
})
.on('mouseout', function (d, i) {
// Mouseout transition
d3.select(this)
.transition()
.duration(500)
.ease('bounce')
.attr('transform', 'translate(0,0)');
// Revert legend animation
$(element + ' [data-slice]').css('opacity', 1);
});
// Animate chart on load
arcPath
.transition()
.delay(function(d, i) { return i * 500; })
.duration(500)
.attrTween("d", function(d) {
var interpolate = d3.interpolate(d.startAngle,d.endAngle);
return function(t) {
d.endAngle = interpolate(t);
return arc(d);
};
});
//
// Append counter
//
// Append element
d3Container
.append('h2')
.attr('class', 'pt-1 mt-2 mb-1 font-weight-semibold');
// Animate counter
d3Container.select('h2')
.transition()
.duration(1500)
.tween("text", function(d) {
var i = d3.interpolate(this.textContent, sum);
return function(t) {
this.textContent = d3.format(",d")(Math.round(i(t)));
};
});
//
// Append legend
//
// Add element
var legend = d3.select(element)
.append('ul')
.attr('class', 'chart-widget-legend')
.selectAll('li').data(pie(data))
.enter().append('li')
.attr('data-slice', function(d, i) {
return i;
})
.attr('style', function(d, i) {
return 'border-bottom: 2px solid ' + d.data.color;
})
.text(function(d, i) {
return d.data.status + ': ';
});
// Add value
legend.append('span')
.text(function(d, i) {
return d.data.value;
});
}
};
// Pie arc with legend
var _pieArcWithLegend = function(element, size) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Basic setup
// ------------------------------
// Add data set
var data = [
{
"status": "Pending",
"icon": "",
"value": 720,
"color": "#29B6F6"
}, {
"status": "Resolved",
"icon": "",
"value": 990,
"color": "#66BB6A"
}, {
"status": "Closed",
"icon": "",
"value": 720,
"color": "#EF5350"
}
];
// Main variables
var d3Container = d3.select(element),
distance = 2, // reserve 2px space for mouseover arc moving
radius = (size/2) - distance,
sum = d3.sum(data, function(d) { return d.value; });
// Tooltip
// ------------------------------
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.direction('e')
.html(function (d) {
return "";
});
// Create chart
// ------------------------------
// Add svg element
var container = d3Container.append("svg").call(tip);
// Add SVG group
var svg = container
.attr("width", size)
.attr("height", size / 2)
.append("g")
.attr("transform", "translate(" + (size / 2) + "," + (size / 2) + ")");
// Construct chart layout
// ------------------------------
// Pie
var pie = d3.layout.pie()
.sort(null)
.startAngle(-Math.PI / 2)
.endAngle(Math.PI / 2)
.value(function (d) {
return d.value;
});
// Arc
var arc = d3.svg.arc()
.outerRadius(radius)
.innerRadius(radius / 1.3);
//
// Append chart elements
//
// Group chart elements
var arcGroup = svg.selectAll(".d3-arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "d3-arc")
.style({
'stroke': '#fff',
'stroke-width': 2,
'cursor': 'pointer'
});
// Append path
var arcPath = arcGroup
.append("path")
.style("fill", function (d) {
return d.data.color;
});
//
// Interactions
//
// Mouse
arcPath
.on('mouseover', function(d, i) {
// Transition on mouseover
d3.select(this)
.transition()
.duration(500)
.ease('elastic')
.attr('transform', function (d) {
d.midAngle = ((d.endAngle - d.startAngle) / 2) + d.startAngle;
var x = Math.sin(d.midAngle) * distance;
var y = -Math.cos(d.midAngle) * distance;
return 'translate(' + x + ',' + y + ')';
});
$(element + ' [data-slice]').css({
'opacity': 0.3,
'transition': 'all ease-in-out 0.15s'
});
$(element + ' [data-slice=' + i + ']').css({'opacity': 1});
})
.on('mouseout', function(d, i) {
// Mouseout transition
d3.select(this)
.transition()
.duration(500)
.ease('bounce')
.attr('transform', 'translate(0,0)');
$(element + ' [data-slice]').css('opacity', 1);
});
// Animate chart on load
arcPath
.transition()
.delay(function(d, i) {
return i * 500;
})
.duration(500)
.attrTween("d", function(d) {
var interpolate = d3.interpolate(d.startAngle,d.endAngle);
return function(t) {
d.endAngle = interpolate(t);
return arc(d);
};
});
//
// Append total text
//
svg.append('text')
.attr('class', 'text-muted')
.attr({
'class': 'half-donut-total',
'text-anchor': 'middle',
'dy': -33
})
.style({
'font-size': '12px',
'fill': '#999'
})
.text('Total');
//
// Append count
//
// Text
svg
.append('text')
.attr('class', 'half-conut-count')
.attr('text-anchor', 'middle')
.attr('dy', -5)
.style({
'font-size': '21px',
'font-weight': 500
});
// Animation
svg.select('.half-conut-count')
.transition()
.duration(1500)
.ease('linear')
.tween("text", function(d) {
var i = d3.interpolate(this.textContent, sum);
return function(t) {
this.textContent = d3.format(",d")(Math.round(i(t)));
};
});
//
// Legend
//
// Add legend list
var legend = d3.select(element)
.append('ul')
.attr('class', 'chart-widget-legend')
.selectAll('li')
.data(pie(data))
.enter()
.append('li')
.attr('data-slice', function(d, i) {
return i;
})
.attr('style', function(d, i) {
return 'border-bottom: solid 2px ' + d.data.color;
})
.text(function(d, i) {
return d.data.status + ': ';
});
// Legend text
legend.append('span')
.text(function(d, i) {
return d.data.value;
});
}
};
// Simple donut
var _animatedDonut = function(element, size) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Add data set
var data = [
{
"status": "Pending tickets",
"icon": "",
"value": 567,
"color": "#29B6F6"
}, {
"status": "Resolved tickets",
"icon": "",
"value": 234,
"color": "#66BB6A"
}, {
"status": "Closed tickets",
"icon": "",
"value": 642,
"color": "#EF5350"
}
];
// Main variables
var d3Container = d3.select(element),
distance = 2, // reserve 2px space for mouseover arc moving
radius = (size/2) - distance,
sum = d3.sum(data, function(d) { return d.value; });
// Tooltip
// ------------------------------
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.direction('e')
.html(function (d) {
return "";
});
// Create chart
// ------------------------------
// Add svg element
var container = d3Container.append("svg").call(tip);
// Add SVG group
var svg = container
.attr("width", size)
.attr("height", size)
.append("g")
.attr("transform", "translate(" + (size / 2) + "," + (size / 2) + ")");
// Construct chart layout
// ------------------------------
// Pie
var pie = d3.layout.pie()
.sort(null)
.startAngle(Math.PI)
.endAngle(3 * Math.PI)
.value(function (d) {
return d.value;
});
// Arc
var arc = d3.svg.arc()
.outerRadius(radius)
.innerRadius(radius / 1.5);
//
// Append chart elements
//
// Group chart elements
var arcGroup = svg.selectAll(".d3-arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "d3-arc")
.style({
'stroke': '#fff',
'stroke-width': 2,
'cursor': 'pointer'
});
// Append path
var arcPath = arcGroup
.append("path")
.style("fill", function (d) {
return d.data.color;
});
// Add tooltip
arcPath
.on('mouseover', function (d, i) {
// Transition on mouseover
d3.select(this)
.transition()
.duration(500)
.ease('elastic')
.attr('transform', function (d) {
d.midAngle = ((d.endAngle - d.startAngle) / 2) + d.startAngle;
var x = Math.sin(d.midAngle) * distance;
var y = -Math.cos(d.midAngle) * distance;
return 'translate(' + x + ',' + y + ')';
});
})
.on("mousemove", function (d) {
// Show tooltip on mousemove
tip.show(d)
.style("top", (d3.event.pageY - 40) + "px")
.style("left", (d3.event.pageX + 30) + "px");
})
.on('mouseout', function (d, i) {
// Mouseout transition
d3.select(this)
.transition()
.duration(500)
.ease('bounce')
.attr('transform', 'translate(0,0)');
// Hide tooltip
tip.hide(d);
});
// Animate chart on load
arcPath
.transition()
.delay(function(d, i) { return i * 500; })
.duration(500)
.attrTween("d", function(d) {
var interpolate = d3.interpolate(d.startAngle,d.endAngle);
return function(t) {
d.endAngle = interpolate(t);
return arc(d);
};
});
//
// Append counter
//
// Append text
svg
.append('text')
.attr('text-anchor', 'middle')
.attr('dy', 6)
.style({
'font-size': '17px',
'font-weight': 500
});
// Animate text
svg.select('text')
.transition()
.duration(1500)
.tween("text", function(d) {
var i = d3.interpolate(this.textContent, sum);
return function(t) {
this.textContent = d3.format(",d")(Math.round(i(t)));
};
});
}
};
// Donut with legend
var _animatedDonutWithLegend = function(element, size) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Add data set
var data = [
{
"status": "New",
"value": 790,
"color": "#29B6F6"
}, {
"status": "Pending",
"value": 850,
"color": "#66BB6A"
}, {
"status": "Shipped",
"value": 760,
"color": "#EF5350"
}
];
// Main variables
var d3Container = d3.select(element),
distance = 2, // reserve 2px space for mouseover arc moving
radius = (size/2) - distance,
sum = d3.sum(data, function(d) { return d.value; });
// Create chart
// ------------------------------
// Add svg element
var container = d3Container.append("svg");
// Add SVG group
var svg = container
.attr("width", size)
.attr("height", size)
.append("g")
.attr("transform", "translate(" + (size / 2) + "," + (size / 2) + ")");
// Construct chart layout
// ------------------------------
// Pie
var pie = d3.layout.pie()
.sort(null)
.startAngle(Math.PI)
.endAngle(3 * Math.PI)
.value(function (d) {
return d.value;
});
// Arc
var arc = d3.svg.arc()
.outerRadius(radius)
.innerRadius(radius / 1.5);
//
// Append chart elements
//
// Group chart elements
var arcGroup = svg.selectAll(".d3-arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "d3-arc")
.style({
'stroke': '#fff',
'stroke-width': 2,
'cursor': 'pointer'
});
// Append path
var arcPath = arcGroup
.append("path")
.style("fill", function (d) {
return d.data.color;
});
// Add interactions
arcPath
.on('mouseover', function (d, i) {
// Transition on mouseover
d3.select(this)
.transition()
.duration(500)
.ease('elastic')
.attr('transform', function (d) {
d.midAngle = ((d.endAngle - d.startAngle) / 2) + d.startAngle;
var x = Math.sin(d.midAngle) * distance;
var y = -Math.cos(d.midAngle) * distance;
return 'translate(' + x + ',' + y + ')';
});
// Animate legend
$(element + ' [data-slice]').css({
'opacity': 0.3,
'transition': 'all ease-in-out 0.15s'
});
$(element + ' [data-slice=' + i + ']').css({'opacity': 1});
})
.on('mouseout', function (d, i) {
// Mouseout transition
d3.select(this)
.transition()
.duration(500)
.ease('bounce')
.attr('transform', 'translate(0,0)');
// Revert legend animation
$(element + ' [data-slice]').css('opacity', 1);
});
// Animate chart on load
arcPath
.transition()
.delay(function(d, i) {
return i * 500;
})
.duration(500)
.attrTween("d", function(d) {
var interpolate = d3.interpolate(d.startAngle,d.endAngle);
return function(t) {
d.endAngle = interpolate(t);
return arc(d);
};
});
//
// Append counter
//
// Append text
svg
.append('text')
.attr('text-anchor', 'middle')
.attr('dy', 6)
.style({
'font-size': '17px',
'font-weight': 500
});
// Animate text
svg.select('text')
.transition()
.duration(1500)
.tween("text", function(d) {
var i = d3.interpolate(this.textContent, sum);
return function(t) {
this.textContent = d3.format(",d")(Math.round(i(t)));
};
});
//
// Append legend
//
// Add element
var legend = d3.select(element)
.append('ul')
.attr('class', 'chart-widget-legend')
.selectAll('li').data(pie(data))
.enter().append('li')
.attr('data-slice', function(d, i) {
return i;
})
.attr('style', function(d, i) {
return 'border-bottom: 2px solid ' + d.data.color;
})
.text(function(d, i) {
return d.data.status + ': ';
});
// Add value
legend.append('span')
.text(function(d, i) {
return d.data.value;
});
}
};
// Donut with details
var _donutWithDetails = function(element, size) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Basic setup
// ------------------------------
// Add data set
var data = [
{
"status": "Pending",
"icon": "",
"value": 720,
"color": "#29B6F6"
}, {
"status": "Resolved",
"icon": "",
"value": 990,
"color": "#66BB6A"
}, {
"status": "Closed",
"icon": "",
"value": 720,
"color": "#EF5350"
}
];
// Main variables
var d3Container = d3.select(element),
distance = 2, // reserve 2px space for mouseover arc moving
radius = (size/2) - distance,
sum = d3.sum(data, function(d) { return d.value; });
// Tooltip
// ------------------------------
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.direction('e')
.html(function (d) {
return "";
});
// Create chart
// ------------------------------
// Add svg element
var container = d3Container.append("svg").call(tip);
// Add SVG group
var svg = container
.attr("width", size)
.attr("height", size)
.append("g")
.attr("transform", "translate(" + (size / 2) + "," + (size / 2) + ")");
// Construct chart layout
// ------------------------------
// Pie
var pie = d3.layout.pie()
.sort(null)
.startAngle(Math.PI)
.endAngle(3 * Math.PI)
.value(function (d) {
return d.value;
});
// Arc
var arc = d3.svg.arc()
.outerRadius(radius)
.innerRadius(radius / 1.35);
//
// Append chart elements
//
// Group chart elements
var arcGroup = svg.selectAll(".d3-arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "d3-arc")
.style({
'stroke': '#fff',
'stroke-width': 2,
'cursor': 'pointer'
});
// Append path
var arcPath = arcGroup
.append("path")
.style("fill", function (d) {
return d.data.color;
});
//
// Add interactions
//
// Mouse
arcPath
.on('mouseover', function(d, i) {
// Transition on mouseover
d3.select(this)
.transition()
.duration(500)
.ease('elastic')
.attr('transform', function (d) {
d.midAngle = ((d.endAngle - d.startAngle) / 2) + d.startAngle;
var x = Math.sin(d.midAngle) * distance;
var y = -Math.cos(d.midAngle) * distance;
return 'translate(' + x + ',' + y + ')';
});
$(element + ' [data-slice]').css({
'opacity': 0.3,
'transition': 'all ease-in-out 0.15s'
});
$(element + ' [data-slice=' + i + ']').css({'opacity': 1});
})
.on('mouseout', function(d, i) {
// Mouseout transition
d3.select(this)
.transition()
.duration(500)
.ease('bounce')
.attr('transform', 'translate(0,0)');
$(element + ' [data-slice]').css('opacity', 1);
});
// Animate chart on load
arcPath
.transition()
.delay(function(d, i) {
return i * 500;
})
.duration(500)
.attrTween("d", function(d) {
var interpolate = d3.interpolate(d.startAngle,d.endAngle);
return function(t) {
d.endAngle = interpolate(t);
return arc(d);
};
});
//
// Add text
//
// Total
svg.append('text')
.attr('class', 'text-muted')
.attr({
'class': 'half-donut-total',
'text-anchor': 'middle',
'dy': -13
})
.style({
'font-size': '12px',
'fill': '#999'
})
.text('Total');
// Count
svg
.append('text')
.attr('class', 'half-donut-count')
.attr('text-anchor', 'middle')
.attr('dy', 14)
.style({
'font-size': '21px',
'font-weight': 500
});
// Animate count
svg.select('.half-donut-count')
.transition()
.duration(1500)
.ease('linear')
.tween("text", function(d) {
var i = d3.interpolate(this.textContent, sum);
return function(t) {
this.textContent = d3.format(",d")(Math.round(i(t)));
};
});
//
// Add legend
//
// Append list
var legend = d3.select(element)
.append('ul')
.attr('class', 'chart-widget-legend')
.selectAll('li')
.data(pie(data))
.enter()
.append('li')
.attr('data-slice', function(d, i) {
return i;
})
.attr('style', function(d, i) {
return 'border-bottom: solid 2px ' + d.data.color;
})
.text(function(d, i) {
return d.data.status + ': ';
});
// Append text
legend.append('span')
.text(function(d, i) {
return d.data.value;
});
}
};
// Progress arc - single color
var _progressArcSingle = function(element, size) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Main variables
var d3Container = d3.select(element),
radius = size,
thickness = 20,
color = '#29B6F6';
// Create chart
// ------------------------------
// Add svg element
var container = d3Container.append("svg");
// Add SVG group
var svg = container
.attr('width', radius * 2)
.attr('height', radius + 20)
.attr('class', 'gauge');
// Construct chart layout
// ------------------------------
// Pie
var arc = d3.svg.arc()
.innerRadius(radius - thickness)
.outerRadius(radius)
.startAngle(-Math.PI / 2);
// Append chart elements
// ------------------------------
//
// Group arc elements
//
// Group
var chart = svg.append('g')
.attr('transform', 'translate(' + radius + ',' + radius + ')');
// Background
var background = chart.append('path')
.datum({
endAngle: Math.PI / 2
})
.attr({
'd': arc,
'fill': '#eee'
});
// Foreground
var foreground = chart.append('path')
.datum({
endAngle: -Math.PI / 2
})
.style('fill', color)
.attr('d', arc);
// Counter value
var value = svg.append('g')
.attr('transform', 'translate(' + radius + ',' + (radius * 0.9) + ')')
.append('text')
.text(0 + '%')
.attr({
'text-anchor': 'middle',
'fill': '#555'
})
.style({
'font-size': 19,
'font-weight': 400
});
//
// Min and max text
//
// Group
var scale = svg.append('g')
.attr('transform', 'translate(' + radius + ',' + (radius + 15) + ')')
.style({
'font-size': 12,
'fill': '#999'
});
// Max
scale.append('text')
.text(100)
.attr({
'text-anchor': 'middle',
'x': (radius - thickness / 2)
});
// Min
scale.append('text')
.text(0)
.attr({
'text-anchor': 'middle',
'x': -(radius - thickness / 2)
});
//
// Animation
//
// Interval
setInterval(function() {
update(Math.random() * 100);
}, 1500);
// Update
function update(v) {
v = d3.format('.0f')(v);
foreground.transition()
.duration(750)
.call(arcTween, v);
value.transition()
.duration(750)
.call(textTween, v);
}
// Arc
function arcTween(transition, v) {
var newAngle = v / 100 * Math.PI - Math.PI / 2;
transition.attrTween('d', function(d) {
var interpolate = d3.interpolate(d.endAngle, newAngle);
return function(t) {
d.endAngle = interpolate(t);
return arc(d);
};
});
}
// Text
function textTween(transition, v) {
transition.tween('text', function() {
var interpolate = d3.interpolate(this.innerHTML, v),
split = (v + '').split('.'),
round = (split.length > 1) ? Math.pow(10, split[1].length) : 1;
return function(t) {
this.innerHTML = d3.format('.0f')(Math.round(interpolate(t) * round) / round) + '%';
};
});
}
}
};
// Progress arc - multiple colors
var _progressArcMulti = function(element, size, goal) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Main variables
var d3Container = d3.select(element),
radius = size,
thickness = 20,
startColor = '#66BB6A',
midColor = '#FFA726',
endColor = '#EF5350';
// Colors
var color = d3.scale.linear()
.domain([0, 70, 100])
.range([startColor, midColor, endColor]);
// Create chart
// ------------------------------
// Add svg element
var container = d3Container.append("svg");
// Add SVG group
var svg = container
.attr('width', radius * 2)
.attr('height', radius + 20);
// Construct chart layout
// ------------------------------
// Pie
var arc = d3.svg.arc()
.innerRadius(radius - thickness)
.outerRadius(radius)
.startAngle(-Math.PI / 2);
// Append chart elements
// ------------------------------
//
// Group arc elements
//
// Group
var chart = svg.append('g')
.attr('transform', 'translate(' + radius + ',' + radius + ')');
// Background
var background = chart.append('path')
.datum({
endAngle: Math.PI / 2
})
.attr({
'd': arc,
'fill': '#eee'
});
// Foreground
var foreground = chart.append('path')
.datum({
endAngle: -Math.PI / 2
})
.style('fill', startColor)
.attr('d', arc);
// Counter value
var value = svg.append('g')
.attr('transform', 'translate(' + radius + ',' + (radius * 0.9) + ')')
.append('text')
.text(0 + '%')
.attr({
'text-anchor': 'middle',
'fill': '#555'
})
.style({
'font-size': 19,
'font-weight': 400
});
//
// Min and max text
//
// Group
var scale = svg.append('g')
.attr('transform', 'translate(' + radius + ',' + (radius + 15) + ')')
.style({
'font-size': 12,
'fill': '#999'
});
// Max
scale.append('text')
.text(100)
.attr({
'text-anchor': 'middle',
'x': (radius - thickness / 2)
});
// Min
scale.append('text')
.text(0)
.attr({
'text-anchor': 'middle',
'x': -(radius - thickness / 2)
});
//
// Animation
//
// Interval
setInterval(function() {
update(Math.random() * 100);
}, 1500);
// Update
function update(v) {
v = d3.format('.0f')(v);
foreground.transition()
.duration(750)
.style('fill', function() {
return color(v);
})
.call(arcTween, v);
value.transition()
.duration(750)
.call(textTween, v);
}
// Arc
function arcTween(transition, v) {
var newAngle = v / 100 * Math.PI - Math.PI / 2;
transition.attrTween('d', function(d) {
var interpolate = d3.interpolate(d.endAngle, newAngle);
return function(t) {
d.endAngle = interpolate(t);
return arc(d);
};
});
}
// Text
function textTween(transition, v) {
transition.tween('text', function() {
var interpolate = d3.interpolate(this.innerHTML, v),
split = (v + '').split('.'),
round = (split.length > 1) ? Math.pow(10, split[1].length) : 1;
return function(t) {
this.innerHTML = d3.format('.0f')(Math.round(interpolate(t) * round) / round) + '%';
};
});
}
}
};
// Rounded progress - single arc
var _roundedProgressSingle = function(element, size, goal, color) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Add random data
var dataset = function () {
return [
{percentage: Math.random() * 100}
];
};
// Main variables
var d3Container = d3.select(element),
padding = 2,
strokeWidth = 16,
width = size,
height = size,
τ = 2 * Math.PI;
// Create chart
// ------------------------------
// Add svg element
var container = d3Container.append("svg");
// Add SVG group
var svg = container
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
// Construct chart layout
// ------------------------------
// Foreground arc
var arc = d3.svg.arc()
.startAngle(0)
.endAngle(function (d) {
return d.percentage / 100 * τ;
})
.innerRadius((size / 2) - strokeWidth)
.outerRadius((size / 2) - padding)
.cornerRadius(20);
// Background arc
var background = d3.svg.arc()
.startAngle(0)
.endAngle(τ)
.innerRadius((size / 2) - strokeWidth)
.outerRadius((size / 2) - padding);
// Append chart elements
// ------------------------------
//
// Group arc elements
//
// Group
var field = svg.selectAll("g")
.data(dataset)
.enter().append("g");
// Foreground arc
field
.append("path")
.attr("class", "arc-foreground")
.attr('fill', color);
// Background arc
field
.append("path")
.attr("d", background)
.style({
"fill": color,
"opacity": 0.2
});
//
// Text
//
// Goal
field
.append("text")
.text("Out of " + goal)
.attr("transform", "translate(0,20)")
.style({
'font-size': 11,
'fill': '#999',
'font-weight': 500,
'text-transform': 'uppercase',
'text-anchor': 'middle'
});
// Count
field
.append("text")
.attr('class', 'arc-goal-completed')
.attr("transform", "translate(0,0)")
.style({
'font-size': 23,
'font-weight': 500,
'text-anchor': 'middle'
});
//
// Animate elements
//
// Add transition
d3.transition().duration(2500).each(update);
// Animation
function update() {
field = field
.each(function (d) {
this._value = d.percentage;
})
.data(dataset)
.each(function (d) {
d.previousValue = this._value;
});
// Foreground arc
field
.select(".arc-foreground")
.transition()
.duration(600)
.ease("easeInOut")
.attrTween("d", arcTween);
// Update count text
field
.select(".arc-goal-completed")
.text(function (d) {
return Math.round(d.percentage /100 * goal);
});
// Animate count text
svg.select('.arc-goal-completed')
.transition()
.duration(600)
.tween("text", function(d) {
var i = d3.interpolate(this.textContent, d.percentage);
return function(t) {
this.textContent = Math.floor(d.percentage/100 * goal);
};
});
// Update every 4 seconds (for demo)
setTimeout(update, 4000);
}
// Arc animation
function arcTween(d) {
var i = d3.interpolateNumber(d.previousValue, d.percentage);
return function (t) {
d.percentage = i(t);
return arc(d);
};
}
}
};
// Rounded progress - multiple arcs
var _roundedProgressMultiple = function(element, size) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Add random data
var data = [
{index: 0, name: 'Memory', percentage: 0},
{index: 1, name: 'CPU', percentage: 0},
{index: 2, name: 'Sessions', percentage: 0}
];
// Main variables
var d3Container = d3.select(element),
padding = 2,
strokeWidth = 8,
width = size,
height = size,
τ = 2 * Math.PI;
// Colors
var colors = ['#78909C', '#F06292', '#4DB6AC'];
// Create chart
// ------------------------------
// Add svg element
var container = d3Container.append("svg");
// Add SVG group
var svg = container
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
// Construct chart layout
// ------------------------------
// Foreground arc
var arc = d3.svg.arc()
.startAngle(0)
.endAngle(function (d) {
return d.percentage / 100 * τ;
})
.innerRadius(function (d) {
return (size / 2) - d.index * (strokeWidth + padding);
})
.outerRadius(function (d) {
return ((size / 2) - d.index * (strokeWidth + padding)) - strokeWidth;
})
.cornerRadius(20);
// Background arc
var background = d3.svg.arc()
.startAngle(0)
.endAngle(τ)
.innerRadius(function (d) {
return (size / 2) - d.index * (strokeWidth + padding);
})
.outerRadius(function (d) {
return ((size / 2) - d.index * (strokeWidth + padding)) - strokeWidth;
});
// Append chart elements
// ------------------------------
//
// Group arc elements
//
// Group
var field = svg.selectAll("g")
.data(data)
.enter().append("g");
// Foreground arcs
field
.append("path")
.attr("class", "arc-foreground")
.style("fill", function (d, i) {
return colors[i];
});
// Background arcs
field
.append("path")
.style("fill", function (d, i) {
return colors[i];
})
.style("opacity", 0.1)
.attr("d", background);
//
// Add legend
//
// Append list
var legend = d3.select(element)
.append('ul')
.attr('class', 'chart-widget-legend text-muted')
.selectAll('li')
.data(data)
.enter()
.append('li')
.attr('data-slice', function(d, i) {
return i;
})
.attr('style', function(d, i) {
return 'border-bottom: solid 2px ' + colors[i];
})
.text(function(d, i) {
return d.name;
});
//
// Animate elements
//
// Add transition
d3.transition().each(update);
// Animation
function update() {
field = field
.each(function (d) {
this._value = d.percentage;
})
.data(data)
.each(function (d) {
d.previousValue = this._value;
d.percentage = Math.round(Math.random() * 100) + 1;
});
// Foreground arcs
field
.select("path.arc-foreground")
.transition()
.duration(750)
.ease("easeInOut")
.attrTween("d", arcTween);
// Update every 4 seconds
setTimeout(update, 4000);
}
// Arc animation
function arcTween(d) {
var i = d3.interpolateNumber(d.previousValue, d.percentage);
return function (t) {
d.percentage = i(t);
return arc(d);
};
}
}
};
// Pie with progress bar
var _pieWithProgress = function(element, size) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Demo dataset
var dataset = [
{ name: 'New', count: 639 },
{ name: 'Pending', count: 255 },
{ name: 'Shipped', count: 215 }
];
// Main variables
var d3Container = d3.select(element),
total = 0,
width = size,
height = size,
progressSpacing = 6,
progressSize = (progressSpacing + 2),
arcSize = 20,
outerRadius = (width / 2),
innerRadius = (outerRadius - arcSize);
// Colors
var color = d3.scale.ordinal()
.range(['#EF5350', '#29b6f6', '#66BB6A']);
// Create chart
// ------------------------------
// Add svg element
var container = d3Container.append("svg");
// Add SVG group
var svg = container
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
// Construct chart layout
// ------------------------------
// Add dataset
dataset.forEach(function(d){
total+= d.count;
});
// Pie layout
var pie = d3.layout.pie()
.value(function(d){ return d.count; })
.sort(null);
// Inner arc
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
// Line arc
var arcLine = d3.svg.arc()
.innerRadius(innerRadius - progressSize)
.outerRadius(innerRadius - progressSpacing)
.startAngle(0);
// Append chart elements
// ------------------------------
//
// Animations
//
var arcTween = function(transition, newAngle) {
transition.attrTween("d", function (d) {
var interpolate = d3.interpolate(d.endAngle, newAngle);
var interpolateCount = d3.interpolate(0, dataset[0].count);
return function (t) {
d.endAngle = interpolate(t);
middleCount.text(d3.format(",d")(Math.floor(interpolateCount(t))));
return arcLine(d);
};
});
};
//
// Donut paths
//
// Donut
var path = svg.selectAll('path')
.data(pie(dataset))
.enter()
.append('path')
.attr('d', arc)
.attr('fill', function(d, i) {
return color(d.data.name);
})
.style({
'stroke': '#fff',
'stroke-width': 2,
'cursor': 'pointer'
});
// Animate donut
path
.transition()
.delay(function(d, i) { return i; })
.duration(600)
.attrTween("d", function(d) {
var interpolate = d3.interpolate(d.startAngle, d.endAngle);
return function(t) {
d.endAngle = interpolate(t);
return arc(d);
};
});
//
// Line path
//
// Line
var pathLine = svg.append('path')
.datum({endAngle: 0})
.attr('d', arcLine)
.style({
fill: color('New')
});
// Line animation
pathLine.transition()
.duration(600)
.delay(300)
.call(arcTween, (2 * Math.PI) * (dataset[0].count / total));
//
// Add count text
//
var middleCount = svg.append('text')
.datum(0)
.attr('dy', 6)
.style({
'font-size': '21px',
'font-weight': 500,
'text-anchor': 'middle'
})
.text(function(d){
return d;
});
//
// Add interactions
//
// Mouse
path
.on('mouseover', function(d, i) {
$(element + ' [data-slice]').css({
'opacity': 0.3,
'transition': 'all ease-in-out 0.15s'
});
$(element + ' [data-slice=' + i + ']').css({'opacity': 1});
})
.on('mouseout', function(d, i) {
$(element + ' [data-slice]').css('opacity', 1);
});
//
// Add legend
//
// Append list
var legend = d3.select(element)
.append('ul')
.attr('class', 'chart-widget-legend')
.selectAll('li')
.data(pie(dataset))
.enter()
.append('li')
.attr('data-slice', function(d, i) {
return i;
})
.attr('style', function(d, i) {
return 'border-bottom: solid 2px ' + color(d.data.name);
})
.text(function(d, i) {
return d.data.name + ': ';
});
// Append legend text
legend.append('span')
.text(function(d, i) {
return d.data.count;
});
}
};
// Segmented gauge
var _segmentedGauge = function(element, size, min, max, sliceQty) {
if (typeof d3 == 'undefined') {
console.warn('Warning - d3.min.js is not loaded.');
return;
}
// Initialize chart only if element exsists in the DOM
if(element) {
// Main variables
var d3Container = d3.select(element),
width = size,
height = (size / 2) + 20,
radius = (size / 2),
ringInset = 15,
ringWidth = 20,
pointerWidth = 10,
pointerTailLength = 5,
pointerHeadLengthPercent = 0.75,
minValue = min,
maxValue = max,
minAngle = -90,
maxAngle = 90,
slices = sliceQty,
range = maxAngle - minAngle,
pointerHeadLength = Math.round(radius * pointerHeadLengthPercent);
// Colors
var colors = d3.scale.linear()
.domain([0, slices - 1])
.interpolate(d3.interpolateHsl)
.range(['#66BB6A', '#EF5350']);
// Create chart
// ------------------------------
// Add SVG element
var container = d3Container.append('svg');
// Add SVG group
var svg = container
.attr('width', width)
.attr('height', height);
// Construct chart layout
// ------------------------------
// Donut
var arc = d3.svg.arc()
.innerRadius(radius - ringWidth - ringInset)
.outerRadius(radius - ringInset)
.startAngle(function(d, i) {
var ratio = d * i;
return deg2rad(minAngle + (ratio * range));
})
.endAngle(function(d, i) {
var ratio = d * (i + 1);
return deg2rad(minAngle + (ratio * range));
});
// Linear scale that maps domain values to a percent from 0..1
var scale = d3.scale.linear()
.range([0, 1])
.domain([minValue, maxValue]);
// Ticks
var ticks = scale.ticks(slices);
var tickData = d3.range(slices)
.map(function() {
return 1 / slices;
});
// Calculate angles
function deg2rad(deg) {
return deg * Math.PI / 180;
}
// Calculate rotation angle
function newAngle(d) {
var ratio = scale(d);
var newAngle = minAngle + (ratio * range);
return newAngle;
}
// Append chart elements
// ------------------------------
//
// Append arc
//
// Wrap paths in separate group
var arcs = svg.append('g')
.attr('transform', "translate(" + radius + "," + radius + ")")
.style({
'stroke': '#fff',
'stroke-width': 2,
'shape-rendering': 'crispEdges'
});
// Add paths
arcs.selectAll('path')
.data(tickData)
.enter()
.append('path')
.attr('fill', function(d, i) {
return colors(i);
})
.attr('d', arc);
//
// Text labels
//
// Wrap text in separate group
var arcLabels = svg.append('g')
.attr('transform', "translate(" + radius + "," + radius + ")");
// Add text
arcLabels.selectAll('text')
.data(ticks)
.enter()
.append('text')
.attr('transform', function(d) {
var ratio = scale(d);
var newAngle = minAngle + (ratio * range);
return 'rotate(' + newAngle + ') translate(0,' + (10 - radius) + ')';
})
.style({
'text-anchor': 'middle',
'font-size': 11,
'fill': '#999'
})
.text(function(d) { return d + "%"; });
//
// Pointer
//
// Line data
var lineData = [
[pointerWidth / 2, 0],
[0, -pointerHeadLength],
[-(pointerWidth / 2), 0],
[0, pointerTailLength],
[pointerWidth / 2, 0]
];
// Create line
var pointerLine = d3.svg.line()
.interpolate('monotone');
// Wrap all lines in separate group
var pointerGroup = svg
.append('g')
.data([lineData])
.attr('transform', "translate(" + radius + "," + radius + ")");
// Paths
pointer = pointerGroup
.append('path')
.attr('d', pointerLine)
.attr('transform', 'rotate(' + minAngle + ')');
// Random update
// ------------------------------
// Update values
function update() {
var ratio = scale(Math.random() * max);
var newAngle = minAngle + (ratio * range);
pointer.transition()
.duration(2500)
.ease('elastic')
.attr('transform', 'rotate(' + newAngle + ')');
}
update();
// Update values every 5 seconds
setInterval(function() {
update();
}, 5000);
}
};
//
// Return objects assigned to module
//
return {
init: function() {
_areaChartWidget("#chart_area_basic", 50, '#5C6BC0');
_areaChartWidget("#chart_area_color", 50, 'rgba(255,255,255,0.75)');
_barChartWidget("#chart_bar_basic", 24, 50, true, "elastic", 1200, 50, "#EF5350", "members");
_barChartWidget("#chart_bar_color", 24, 50, true, "elastic", 1200, 50, "rgba(255,255,255,0.75)", "members");
_lineChartWidget('#line_chart_simple', 50, '#2196F3', 'rgba(33,150,243,0.5)', '#2196F3', '#fff');
_lineChartWidget('#line_chart_color', 50, '#fff', 'rgba(255,255,255,0.5)', '#fff', '#29B6F6');
_sparklinesWidget("#sparklines_basic", "area", 30, 50, "basis", 750, 2000, "#66BB6A");
_sparklinesWidget("#sparklines_color", "area", 30, 50, "basis", 750, 2000, "rgba(255,255,255,0.75)");
_progressIcon('#progress_icon_one', 42, 2.5, "#eee", "#EF5350", 0.68, "icon-heart6");
_progressIcon('#progress_icon_two', 42, 2.5, "#eee", "#5C6BC0", 0.82, "icon-trophy3");
_progressIcon('#progress_icon_three', 42, 2.5, "#00897B", "#fff", 0.73, "icon-bag");
_progressIcon('#progress_icon_four', 42, 2.5, "#673AB7", "#fff", 0.49, "icon-truck");
_progressPercentage('#progress_percentage_one', 46, 3, "#eee", "#2196F3", 0.79);
_progressPercentage('#progress_percentage_two', 46, 3, "#eee", "#EF5350", 0.62);
_progressPercentage('#progress_percentage_three', 46, 3, "#039BE5", "#fff", 0.69);
_progressPercentage('#progress_percentage_four', 46, 3, "#E53935", "#fff", 0.43);
_animatedPie("#pie_basic", 120);
_animatedPieWithLegend("#pie_basic_legend", 120);
_pieArcWithLegend("#pie_arc_legend", 170);
_animatedDonut("#donut_basic_stats", 120);
_animatedDonutWithLegend("#donut_basic_legend", 120);
_donutWithDetails("#donut_basic_details", 146);
_progressArcSingle("#arc_single", 78);
_progressArcMulti("#arc_multi", 78, 700);
_roundedProgressSingle("#rounded_progress_single", 150, 700, '#EC407A');
_roundedProgressMultiple("#rounded_progress_multiple", 140);
_pieWithProgress("#pie_progress_bar", 146);
_segmentedGauge("#segmented_gauge", 200, 0, 100, 5);
}
}
}();
// Initialize module
// ------------------------------
// When content loaded
document.addEventListener('DOMContentLoaded', function() {
StatisticWidgets.init();
});