Skip to content

Instantly share code, notes, and snippets.

@chriswmackey
Last active October 23, 2019 20:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save chriswmackey/1db0698c2807005ee17e03d57d85bd9b to your computer and use it in GitHub Desktop.
Save chriswmackey/1db0698c2807005ee17e03d57d85bd9b to your computer and use it in GitHub Desktop.
Design Explorer Lite Experiment
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
.metricdiv {background-color:#f2f2f2; width:210px;float:left;padding:10px;text-align:center;}
</style>
</head>
<body>
<div id="content">
</div>
<div id="metrics">
</div>
<script>
buildChart = function(dataList=[], dataNames=[], dataColors =[], stacked=true,
yAxisText=['Value','units'], maxVal=null, svgwidth=3,
svgheight=5, margin={top:20,right:40,bottom:30,left:70}) {
// convert twelfs to pixels
windowTwelf = window.innerWidth/12
svgwidth = windowTwelf * svgwidth
svgheight = windowTwelf * svgheight
// calculate chart properties
width = svgwidth - margin.left - margin.right
height = svgheight - margin.top - margin.bottom
barSpacer = svgwidth/10
topBarFactor = 1.25
if (stacked == true){
barWidth = svgwidth/3
} else {
barWidth = (svgwidth/2) / dataList.length
}
// auto-set the max val if it isn't set to anything
if (maxVal == null){
if (stacked == true){
maxVal = topBarFactor * dataList.reduce(function(a, b) { return a + b; }, 0);
} else {
maxVal = topBarFactor * Math.max(...dataList)
}
}
// auto-set the dataNames if they are empty.
if (dataNames.length == 0){
for (i = 0; i < dataList.length; i++) {
dataNames.push('Var ' + i.toString())
}
}
// auto-generate colors if they are empty.
if (dataColors.length == 0){
var f=d3.interpolateHsl("rgb(255,0,102)", "rgb(0,176,240)")
for (var i=0; i<dataList.length; i++) {
dataColors.push(f(i/(dataList.length-1)))
}
}
var x = d3.scaleBand()
.rangeRound([0, svgwidth])
.padding(0.1)
.align(0.1);
var yScale = d3.scaleLinear()
.domain([0, maxVal])
.rangeRound([height, 0]);
var svg = d3.select("#content").append("svg")
.attr("width", svgwidth)
.attr("height", svgheight)
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the y-axis labels
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(yScale).ticks(10, "s"))
if (yAxisText.length > 0) {
for (i = 0; i < yAxisText.length; i++) {
if (i == 0){
textHeight = '14px'
} else{
textHeight = '11px'
}
g.append("text")
.attr("x", 10)
.attr("y", yScale(yScale.ticks(10).pop()) + (i * 14))
.attr("dy", "0.35em")
.attr("text-anchor", "start")
.attr("fill", "#000")
.style('font-size', textHeight)
.style('font-family', 'sans-serif')
.text(yAxisText[i]);
}
}
// add the legend
spacerIncrement = 0
for (i = 0; i < dataList.length; i++) {
svg.append("rect")
.attr("x", svgwidth - 11)
.attr("y", margin.top + spacerIncrement)
.attr("width", 10)
.attr("height", 10)
.attr('fill', dataColors[i])
.style("stroke", "#000")
.style("stroke-width", "0.05em");
svg.append("text")
.attr("x",svgwidth - 15)
.attr("y", margin.top + spacerIncrement)
.attr("dy", "10px")
.attr("text-anchor", "end")
.attr("fill", "#000")
.style('font-family', 'sans-serif')
.style('font-size', '12px')
.text(dataNames[i]);
spacerIncrement += 20
}
// add the data
if (stacked == true){
stackIncrement = 0
svg.attr("class", "stacked")
for (i = 0; i < dataList.length; i++) {
svg.append("rect")
.attr("x", margin.left + barSpacer)
.attr("y", svgheight- margin.bottom - yScale(maxVal-dataList[i]) - yScale(maxVal - stackIncrement))
.attr("width", barWidth)
.attr("height", yScale(maxVal - dataList[i]))
.attr('fill', dataColors[i])
.attr("class", "dataBar")
.style("stroke", "#000")
.style("stroke-width", "0.05em");
stackIncrement += dataList[i]
}
} else{
svg.attr("class", "normal")
for (i = 0; i < dataList.length; i++) {
svg.append("rect")
.attr("x", margin.left + barSpacer + barWidth * i)
.attr("y", svgheight- margin.bottom - yScale(maxVal-dataList[i]))
.attr("width", barWidth)
.attr("height", yScale(maxVal - dataList[i]))
.attr('fill', dataColors[i])
.attr("class", "peakBar")
.style("stroke", "#000")
.style("stroke-width", "0.05em");
}
}
chartObj = {'svg': svg, 'stacked': stacked, 'margin': margin,
'svgheight': svgheight, 'barSpacer': barSpacer, 'yScale': yScale,
'maxVal': maxVal, 'barWidth': barWidth, 'dataColors': dataColors}
return chartObj
}
buildMetric = function(metricValue, propertiesDict) {
// set default values
width = '3'
decimals = 0
units = "meters"
longName = "testname"
id = (((1+Math.random())*0x10000)|0).toString(16).substring(1)
console.log(id)
// check the properties dictionary to see if any are overridden
if ("width" in propertiesDict){
width = propertiesDict["width"].toString()
}
if ("height" in propertiesDict){
height = propertiesDict["height"]
}
if ("decimals" in propertiesDict){
decimals = propertiesDict["decimals"]
}
if ("units" in propertiesDict){
units = propertiesDict["units"]
}
if ("longName" in propertiesDict){
longName = propertiesDict["longName"]
}
// convert svg width in 12/ths to pixels.
windowTwelf = parseInt(window.innerWidth/12)
width = (windowTwelf * width) - 5
styleString ='width:'+ width +'px;'
$('#metrics').append(
'<div class= "metricdiv" style= "'+ styleString +'">'+
'<div class= "metric" id="'+ id +'">' + metricValue.toString() +
'</div>' +
'<p>' + units + '<br>' + longName + '</p>'+
'</div>');
return id
}
updateMetric = function(id, num) {
d3.select("#"+id.toString()).append("text")
.attr("text-anchor", "start")
.attr("fill", "#000")
.style('font-size', '30px')
.style('font-family', 'sans-serif')
.text(num.toString());
}
id1 = buildMetric(5, {})
console.log(id1)
//updateMetric(id1, 7)
// Function to update the chart.
updateChart = function(chartObj, updatedData=[]){
// grab important paramters from the object
svg = chartObj['svg']
stacked = chartObj['stacked']
yScale = chartObj['yScale']
// delete old bars from the chart.
svg.selectAll('.dataBar').remove();
// add new bars to the chart.
stackIncrement = 0
if (stacked == true){
stackIncrement = 0
for (i = 0; i < updatedData.length; i++) {
svg.append("rect")
.attr("x", chartObj['margin'].left + chartObj['barSpacer'])
.attr("y", chartObj['svgheight']- chartObj['margin'].bottom - yScale(chartObj['maxVal']-updatedData[i]) - yScale(chartObj['maxVal'] - stackIncrement))
.attr("width", chartObj['barWidth'])
.attr("height", yScale(chartObj['maxVal'] - updatedData[i]))
.attr('fill', chartObj['dataColors'][i])
.attr("class", "dataBar")
.style("stroke", "#000")
.style("stroke-width", "0.05em");
stackIncrement += updatedData[i]
}
} else{
for (i = 0; i < updatedData.length; i++) {
svg.append("rect")
.attr("x", chartObj['margin'].left + chartObj['barSpacer'] + chartObj['barWidth'] * i)
.attr("y", chartObj['svgheight'] - chartObj['margin'].bottom - yScale(chartObj['maxVal']-updatedData[i]))
.attr("width", chartObj['barWidth'])
.attr("height", yScale(chartObj['maxVal'] - updatedData[i]))
.attr('fill', chartObj['dataColors'][i])
.attr("class", "dataBar")
.style("stroke", "#000")
.style("stroke-width", "0.05em");
}
}
}
var maxVal = 200
var data = [5, 20, 50, 20, 25, 10]
var colors = ["rgb(255,255,0)", "rgb(191,191,191)", "rgb(255,0,102)", "rgb(0,176,240)","rgb(166,216,110)","rgb(119,185,49)"]
var names = ["Lighting", "Equipment", "Heating", "Cooling","Fans","Pumps"]
var peakdata = [5, 20]
var names2 = ["Heating", "Cooling"]
var theSVG1 = buildChart(data, names, colors, true, ['EUI', 'kBTu/sf'])
var theSVG2 = buildChart(peakdata, names2, [], false, ['Peak Load'])
var newData = [5, 20, 10, 20, 25, 10]
updateChart(theSVG1, newData)
var newPeakdata = [15, 20]
updateChart(theSVG2, newPeakdata)
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment