Skip to content

Instantly share code, notes, and snippets.

@joshbirk
Last active March 29, 2019 20:04
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save joshbirk/08be97d92b91c3bdc9e1 to your computer and use it in GitHub Desktop.
Save joshbirk/08be97d92b91c3bdc9e1 to your computer and use it in GitHub Desktop.
Lightning Chart Component w/ D3.js
function plumb(raw_data,data) {
this.raw_data = raw_data;
this.data = data;
return this;
}
plumb.prototype.keyPlumber = function() {}
plumb.prototype.generateKey = function(plumber) {
this.keyPlumber = plumber;
this.data = [];
var data_plumb = this;
this.raw_data.forEach(function(record) {
data_plumb.data[data_plumb.keyPlumber(record)] = {};
});
return this;
}
plumb.prototype.meanField = function(field,label) {
var data_plumb = this;
this.raw_data.forEach(function(record) {
if(data_plumb.data[data_plumb.keyPlumber(record)][label] === undefined) { //this assumes first run
data_plumb.data[data_plumb.keyPlumber(record)][label] = 0;
data_plumb.data[data_plumb.keyPlumber(record)]["keyCount"] = 0;
}
data_plumb.data[data_plumb.keyPlumber(record)][label] += record[field];
data_plumb.data[data_plumb.keyPlumber(record)]["keyCount"]++;
});
this.data.forEach(function(record) {
// fieldCount = data_plumb.raw_data.length / data_plumb.data.length;
record[label] /= record["keyCount"];
console.log(record[label]);
});
return this;
}
plumb.prototype.maxField = function(field,label) {
var data_plumb = this;
this.raw_data.forEach(function(record) {
if(data_plumb.data[data_plumb.keyPlumber(record)][label] === undefined || record[field] > data_plumb.data[data_plumb.keyPlumber(record)][label]) {
data_plumb.data[data_plumb.keyPlumber(record)][label] = record[field];
}
});
return this;
}
plumb.prototype.minField = function(field,label) {
var data_plumb = this;
this.raw_data.forEach(function(record) {
if(data_plumb.data[data_plumb.keyPlumber(record)][label] === undefined || record[field] < data_plumb.data[data_plumb.keyPlumber(record)][label]) {
data_plumb.data[data_plumb.keyPlumber(record)][label] = record[field];
}
});
return this;
}
public with sharing class SpeedTestController {
@AuraEnabled
public static List< SpeedTest__c > getData() {
List<SpeedTest__c> speeds = [SELECT ID, TimeString__c,Download__c,Upload__c from SpeedTest__c LIMIT 1000];
return speeds;
}
}
<aura:component controller="SpeedTestController" >
<ltng:require scripts="/resource/jquery,/resource/d3,/resource/plumb"
afterScriptsLoaded="{!c.getSpeeds}"/>
<div id="chart"></div>
</aura:component>
({
getSpeeds : function(component, event, helper) {
var speeds = new Array();
var current_offset = 100;
var done = false;
var transformed_speeds = [];
var speed_plumb = {};
var action = component.get("c.getData");
action.setCallback(this, function(a) {
speeds = a.getReturnValue();
speed_plumb = new plumb(speeds);
helper.plumbData(speed_plumb);
helper.drawData(speed_plumb);
});
$A.enqueueAction(action);
}
})
({
plumbData : function(speed_plumb) {
speed_plumb.generateKey(function(speed) {
var hour = speed.TimeString__c.split(" ")[1];
hour = hour.split(":")[0];
hour = parseInt(hour);
return hour;
}).meanField("Download__c","DownloadSpeed")
.maxField("Download__c","MaxDownload")
.minField("Download__c","MinDownload")
.meanField("Download__c","MeanDownload");
},
createArc : function(time,speed, svg) {
if(!speed || !speed.DownloadSpeed) {return;}
var gradient = ["#F50D00","#D91319","#BE1A32","#A3214C","#882865","#6C2E7F","#513598","#363CB2","#1B43CB","#004AE5","#004AE5","#004AE5","#004AE5"];
var peak_color = "#FFDF99";
var startAngle = time * 15;
var endAngle = startAngle + 15;
var arc = d3.svg.arc()
.innerRadius(40)
.outerRadius(150)
.startAngle(startAngle * (Math.PI/180)) //converting from degs to radians
.endAngle(endAngle * (Math.PI/180)) //just radians
svg.append("path")
.attr("d", arc)
.attr("class", "hour-arc")
.attr("id", "hour"+String(time))
.attr("fill", function (d, i) { return gradient[Math.round(speed.DownloadSpeed)]; })
.attr("stroke", peak_color)
.attr("transform", "translate(175,175)");
var text = svg.append("text")
.attr("x", 5)
.attr("dy", 24);
text.append("textPath")
.attr("class", "hour-arc")
.attr("stroke","white")
.style("fill","white")
.attr("font-family","Verdana")
.attr("font-size","24")
.attr("xlink:href","#hour"+String(time))
.text(String(Math.round(speed.MeanDownload)));
var text_speed = svg.append("text")
.attr("x", 10)
.attr("dy", 80);
text_speed.append("textPath")
.attr("class", "hour-arc")
.attr("stroke",peak_color)
.attr("font-family","Verdana")
.attr("font-size","12")
.attr("xlink:href","#hour"+String(time))
.text(String(time));
},
drawData : function(speed_plumb) {
var svg = d3.select("#chart").append("svg")
.attr("preserveAspectRatio", "xMidYMid")
.attr("viewBox", "-50 -50 1200 1200")
.attr("width", 1200)
.attr("height", 1200);
var peak_color = "#FFDF99";
//Play Time
var startAngle = 20 * 15;
var endAngle = startAngle + 75;
var arc = d3.svg.arc()
.innerRadius(20)
.outerRadius(200)
.startAngle(startAngle * (Math.PI/180)) //converting from degs to radians
.endAngle(endAngle * (Math.PI/180)) //just radians
svg.append("path")
.attr("d", arc)
.attr("stroke","black")
.attr("id", "peaktime")
.attr("fill", function (d, i) { return peak_color; })
.attr("transform", "translate(175,175)");
var text = svg.append("text")
.attr("x", 14)
.attr("dy", 14);
text.append("textPath")
.attr("stroke","black")
.attr("font-family","Verdana")
.attr("font-size","12")
.attr("xlink:href","#peaktime")
.text("Online Gaming");
//Sleep Time
startAngle = 24 * 15;
endAngle = startAngle + 135;
arc = d3.svg.arc()
.innerRadius(20)
.outerRadius(200)
.startAngle(startAngle * (Math.PI/180)) //converting from degs to radians
.endAngle(endAngle * (Math.PI/180)) //just radians
svg.append("path")
.attr("d", arc)
.attr("stroke","black")
.attr("id", "sleeptime")
.attr("fill", function (d, i) { return peak_color; })
.attr("transform", "translate(175,175)");
text = svg.append("text")
.attr("x", 14)
.attr("dy", 14);
text.append("textPath")
.attr("stroke","black")
.attr("font-family","Verdana")
.attr("font-size","12")
.attr("xlink:href","#sleeptime")
.text("Sleeping");
//Work Time
startAngle = 9 * 15;
endAngle = startAngle + 135;
arc = d3.svg.arc()
.innerRadius(20)
.outerRadius(200)
.startAngle(startAngle * (Math.PI/180)) //converting from degs to radians
.endAngle(endAngle * (Math.PI/180)) //just radians
svg.append("path")
.attr("d", arc)
.attr("stroke","black")
.attr("id", "worktime")
.attr("fill", function (d, i) { return peak_color; })
.attr("transform", "translate(175,175)");
text = svg.append("text")
.attr("x", 14)
.attr("dy", 14);
text.append("textPath")
.attr("stroke","black")
.attr("font-family","Verdana")
.attr("font-size","12")
.attr("xlink:href","#worktime")
.text("Working");
//Netflix Time
startAngle = 18 * 15;
endAngle = startAngle + 30;
arc = d3.svg.arc()
.innerRadius(20)
.outerRadius(200)
.startAngle(startAngle * (Math.PI/180)) //converting from degs to radians
.endAngle(endAngle * (Math.PI/180)) //just radians
svg.append("path")
.attr("d", arc)
.attr("stroke","black")
.attr("id", "netflix")
.attr("fill", function (d, i) { return peak_color; })
.attr("transform", "translate(175,175)");
text = svg.append("text")
.attr("x", 14)
.attr("dy", 14);
text.append("textPath")
.attr("stroke","black")
.attr("font-family","Verdana")
.attr("font-size","12")
.attr("xlink:href","#netflix")
.text("Netflix");
//refresh
d3.selectAll(".hour-arc").remove()
for(var i = 0; i < speed_plumb.data.length; i++) {
this.createArc(i,speed_plumb.data[i],svg);
}
}
})
@piyushchandani
Copy link

Hi,

I am new to D3 and want to learn it. I started by implementing your code but getting the below error. Also, I created a custom object named SpeedTest__c.

Error in $A.getCallback() [plumb is not defined]
Callback failed: apex://SpeedTestController/ACTION$getData

Could you please help me to resolve it?

Thanks in advance !

Piyush

@davidrobertslogicom
Copy link

Thanks joshbirk for the method os tagging the svg to a

!

@bradclemons3
Copy link

davidrobertslogicom - Did you get an answer on this issue with the Callback()? Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment