Created
October 21, 2020 11:22
-
-
Save valex/f88bc8bd5d478788ad3ab3b5ee236fcf to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<meta charset="utf-8"> | |
<link rel="stylesheet" href="styles.css"> | |
</head> | |
<body> | |
<div style="display: flex; | |
flex-direction: row; justify-content: space-between;"> | |
<div id="chart"></div> | |
<div id="chart_right"></div> | |
</div> | |
</body> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js" ></script> | |
<script src="scripts.js"></script> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function CHART_1_class(id, selector){ | |
this.options = { | |
selector: selector, | |
viewBox: [400, 300], | |
bands: { | |
left: ["pinky", "ring", "middle", "pointing"], | |
right: ["pointing", "middle", "ring", "pinky"] | |
}, | |
colors: { | |
background: '#d7e5ec', | |
better: '#4bc774', | |
better_hover: '#76e582', | |
worse: '#d63a31', | |
worse_hover: '#eb4a41', | |
}, | |
groups: ['onPeriodStart', 'onPeriodEnd'], | |
yScaleDomain: [0, 160], | |
barStrokeWidth: 2, | |
paddings: { | |
main: { | |
left: 0.2, | |
bottom: 0.3 | |
} | |
}, | |
headerHeight: 0.18 | |
} | |
this.id = id, | |
this.el = null, | |
this.aspect = null, | |
this.originalData = null, | |
this.data = null, | |
this.vis = { | |
svg: null, | |
defs: null, | |
background:null, | |
legends: null, | |
hand_legends: null, | |
yAxis: null, | |
markers:null, | |
bars: null, | |
mainRect: { // init values | |
x: 0, | |
y: 0, | |
width: this.options.viewBox[0], | |
height: this.options.viewBox[1] | |
}, | |
headerRect: { | |
x: null, | |
y: null, | |
width: null, | |
height: null, | |
center: { | |
x: null, | |
y: null | |
} | |
}, | |
xScale: null, | |
yScale: null | |
} | |
this.el = d3.select(this.options.selector); | |
this.aspect = this.options.viewBox[0] / this.options.viewBox[1]; | |
window.addEventListener("resize", this.onResize.bind(this), false); | |
}; | |
CHART_1_class.prototype = { | |
setData: function(data){ | |
this.originalData = Object.assign({}, data); | |
this.data = null; | |
this.prepareData(); | |
}, | |
prepareData: function(){ | |
var that = this; | |
this.data = Object.assign({}, this.originalData); | |
// build diff | |
this.data['diff'] = {}; | |
for (var prop in this.data[this.options.groups[1]]) { | |
if( ! this.data[this.options.groups[1]].hasOwnProperty( prop ) ) | |
continue; | |
if( typeof this.data[this.options.groups[0]][prop] === 'undefined' ) | |
continue; | |
this.data['diff'][prop] = this.data[this.options.groups[1]][prop] - this.data[this.options.groups[0]][prop]; | |
} | |
var diff_entries = Object.entries(this.data['diff']); | |
this.data['diff_max_key'] = diff_entries[ | |
d3.maxIndex(diff_entries, function(d){ | |
return d[1]; | |
}) | |
][0]; | |
this.data['diff_min_key'] = diff_entries[ | |
d3.minIndex(diff_entries, function(d){ | |
return d[1]; | |
}) | |
][0]; | |
for(var i=0; i < this.options.groups.length; i++){ | |
var group = this.options.groups[i]; | |
// calculate min and max | |
for (var prop in this.data[group]) { | |
if( this.data[group].hasOwnProperty( prop ) ) { | |
if(typeof this.data['maxValue'] === 'undefined'){ | |
this.data['maxValue'] = +this.data[group][prop]; | |
}else{ | |
if(+this.data[group][prop] > this.data['maxValue']) | |
this.data['maxValue'] = +this.data[group][prop]; | |
} | |
if(typeof this.data['minValue'] === 'undefined'){ | |
this.data['minValue'] = +this.data[group][prop]; | |
}else{ | |
if(+this.data[group][prop] < this.data['minValue']) | |
this.data['minValue'] = +this.data[group][prop]; | |
} | |
} | |
} | |
// build entries | |
this.data[group]['entries'] = Object.entries(this.data[group]) | |
} | |
}, | |
buildVis: function(){ | |
if( ! this.vis.svg ) this.buildUnchanged(); | |
this.makeCalculations(); | |
this.buildDefs(); | |
this.buildSkeleton(); | |
this.buildLegends(); | |
this.buildAxes(); | |
this.buildMarkers(); | |
this.buildBars(); | |
}, | |
makeCalculations: function(){ | |
var headerPlusMainHeigh = Math.ceil(this.options.viewBox[1] - (this.options.paddings.main.bottom * this.options.viewBox[1])); | |
this.vis.headerRect.x = 1 + Math.round(this.options.paddings.main.left * this.options.viewBox[0]); | |
this.vis.headerRect.y = 1; | |
this.vis.headerRect.width = this.options.viewBox[0] - this.vis.headerRect.x -1; | |
this.vis.headerRect.height = Math.floor( this.options.headerHeight * headerPlusMainHeigh); | |
this.vis.headerRect.center.x = this.vis.headerRect.x + this.vis.headerRect.width / 2; | |
this.vis.headerRect.center.y = this.vis.headerRect.y + this.vis.headerRect.height / 2; | |
this.vis.mainRect.x = this.vis.headerRect.x; | |
this.vis.mainRect.y = this.vis.headerRect.y + this.vis.headerRect.height; | |
this.vis.mainRect.width = this.vis.headerRect.width; | |
this.vis.mainRect.height = Math.floor(headerPlusMainHeigh - this.vis.headerRect.height); | |
this.vis.xScale = d3.scaleBand() | |
.domain(this.options.bands[this.data['hand']]) | |
.rangeRound([this.vis.mainRect.x, this.vis.mainRect.x+this.vis.mainRect.width]) | |
.paddingInner(0.25) | |
.paddingOuter(0.5); | |
this.vis.yScale = d3.scaleLinear() | |
.domain(this.options.yScaleDomain) | |
.range([ | |
this.vis.mainRect.y + this.vis.mainRect.height, | |
this.vis.mainRect.y | |
]); | |
}, | |
buildMarkers:function(){ | |
var that = this; | |
this.vis['markers'] | |
.selectAll("g.end") | |
.data(this.options.bands[this.data['hand']]) | |
.join('g') | |
.attr('class', function(fingerKey){ return fingerKey; }) | |
.classed('end', true) | |
.style('opacity', '0') | |
.each(function(fingerKey){ | |
// text | |
var text_bounding; | |
var text = d3.select(this) | |
.selectAll("text") | |
.data([ that.data[that.options.groups[1]][fingerKey] ]) | |
.join("text") | |
.attr("x", function(){return 10}) | |
.attr("y", function(value){return that.vis.yScale( value )}) | |
.attr("dx", 10) | |
.attr("dy", 1) | |
.attr("font-size", "1rem") | |
.attr("fill", "black") | |
.attr("text-anchor", "start") | |
.style("alignment-baseline", "middle") | |
.style("font-weight", "normal") | |
.attr("class", "noselect") | |
.text(function(value, i) { | |
return value+"\u00B0"; | |
}) | |
.each(function(){ | |
text_bounding = d3.select(this).node().getBBox(); | |
}) | |
//rect | |
var rect_padding = 4; | |
var rect_bounding; | |
d3.select(this) | |
.selectAll("rect") | |
.data( [ text_bounding ] ) | |
.join("rect") | |
.attr('rx', 6) | |
.attr('ry', 6) | |
.attr('x', function(d){ return d.x - rect_padding }) | |
.attr('y', function(d){ return d.y -rect_padding }) | |
.attr('width', function(d){ return d.width + 2*rect_padding }) | |
.attr('height', function(d){ return d.height +2*rect_padding }) | |
.attr('fill', 'white') | |
.style('fill-opacity', "1") | |
.style('stroke-width', '1px') | |
.style('stroke', function(d, i){ | |
if( that.data.diff[fingerKey] > 0) | |
return that.options.colors.better; | |
return that.options.colors.worse; | |
}) | |
.each(function(){ | |
rect_bounding = d3.select(this).node().getBBox(); | |
}) | |
text.raise(); | |
//line | |
d3.select(this) | |
.selectAll('line') | |
.data([ that.data[that.options.groups[1]][fingerKey] ]) | |
.join("line") | |
.attr('x1', function(d, i){ | |
return that.vis.xScale(fingerKey) + that.vis.xScale.bandwidth() /2; | |
}) | |
.attr('y1', function(d, i){ | |
return that.vis.yScale( d ) | |
}) | |
.attr('x2', function(d, i){ return rect_bounding.x + rect_bounding.width }) | |
.attr('y2', function(d, i){ | |
return that.vis.yScale( d ) | |
}) | |
.style('stroke-width', '1px') | |
.style('stroke', function(d, i){ | |
if( that.data.diff[fingerKey] > 0) | |
return that.options.colors.better; | |
return that.options.colors.worse; | |
}) | |
}); | |
this.vis['markers'] | |
.selectAll("g.start") | |
.data(this.options.bands[this.data['hand']]) | |
.join('g') | |
.attr('class', function(fingerKey){ return fingerKey; }) | |
.classed('start', true) | |
.style('opacity', '0') | |
.each(function(fingerKey){ | |
// text | |
var text_bounding; | |
var text = d3.select(this) | |
.selectAll("text") | |
.data([ that.data[that.options.groups[0]][fingerKey] ]) | |
.join("text") | |
.attr("x", function(){return 10}) | |
.attr("y", function(value){return that.vis.yScale( value )}) | |
.attr("dx", 10) | |
.attr("dy", 1) | |
.attr("font-size", "1rem") | |
.attr("fill", "black") | |
.attr("text-anchor", "start") | |
.style("alignment-baseline", "middle") | |
.style("font-weight", "normal") | |
.attr("class", "noselect") | |
.text(function(value, i) { | |
return value+"\u00B0"; | |
}) | |
.each(function(){ | |
text_bounding = d3.select(this).node().getBBox(); | |
}) | |
//rect | |
var rect_padding = 4; | |
var rect_bounding; | |
d3.select(this) | |
.selectAll("rect") | |
.data( [ text_bounding ] ) | |
.join("rect") | |
.attr('rx', 6) | |
.attr('ry', 6) | |
.attr('x', function(d){ return d.x - rect_padding }) | |
.attr('y', function(d){ return d.y -rect_padding }) | |
.attr('width', function(d){ return d.width + 2*rect_padding }) | |
.attr('height', function(d){ return d.height +2*rect_padding }) | |
.attr('fill', 'white') | |
.style('fill-opacity', "1") | |
.style('stroke-width', '1px') | |
.style('stroke', function(d, i){ | |
return 'black'; | |
}) | |
.each(function(){ | |
rect_bounding = d3.select(this).node().getBBox(); | |
}) | |
text.raise(); | |
//line | |
d3.select(this) | |
.selectAll('line') | |
.data([ that.data[that.options.groups[0]][fingerKey] ]) | |
.join("line") | |
.attr('x1', function(d, i){ | |
return that.vis.xScale(fingerKey) + that.vis.xScale.bandwidth() /2; | |
}) | |
.attr('y1', function(d, i){ | |
return that.vis.yScale( d ) | |
}) | |
.attr('x2', function(d, i){ return rect_bounding.x + rect_bounding.width }) | |
.attr('y2', function(d, i){ | |
return that.vis.yScale( d ) | |
}) | |
.style('stroke-width', '1px') | |
.style('stroke', function(d, i){ | |
return 'black' | |
}) | |
}); | |
}, | |
buildLegends: function(){ | |
var that = this; | |
var handMarker = this.vis.legends | |
.selectAll('text') | |
.data([that.data.hand]) | |
.join("text") | |
.attr("x", function(){return that.vis.headerRect.x;}) | |
.attr("y", function(){return that.vis.headerRect.center.y;}) | |
.attr("dx", 10) | |
.attr("dy", 2) | |
.attr("font-size", "1rem") | |
.attr("fill", "black") | |
.attr("text-anchor", "start") | |
.style("alignment-baseline", "middle") | |
.style("font-weight", "bold") | |
.attr("class", "noselect") | |
.text(function(d) { | |
switch(d){ | |
case 'left': | |
return "Левая рука" | |
break; | |
default: | |
return "Правая рука" | |
break; | |
} | |
}); | |
this.vis.legends | |
.selectAll('circle') | |
.data([0, 1]) | |
.enter() | |
.append("circle") | |
.attr("cx", function(d){ | |
switch(d){ | |
case 0: | |
return that.vis.headerRect.center.x; | |
break; | |
default: | |
return that.vis.headerRect.center.x + 90; | |
break; | |
} | |
}) | |
.attr("cy", that.vis.headerRect.center.y) | |
.attr("r", function(){return 0.3 * that.vis.headerRect.height / 2}) | |
.attr("fill", function(d){ | |
switch(d){ | |
case 0: | |
return that.options.colors.better; | |
break; | |
default: | |
return that.options.colors.worse; | |
break; | |
} | |
}); | |
this.vis.legends | |
.selectAll('text.legend-text') | |
.data([0, 1]) | |
.enter() | |
.append('text') | |
.classed("legend-text", true) | |
.attr("x", function(d){ | |
switch(d){ | |
case 0: | |
return that.vis.headerRect.center.x; | |
break; | |
default: | |
return that.vis.headerRect.center.x + 90; | |
break; | |
} | |
}) | |
.attr("y", that.vis.headerRect.center.y) | |
.attr("dx", 10) | |
.attr("dy", 2) | |
.attr("font-size", "1rem") | |
.attr("fill", "black") | |
.attr("text-anchor", "start") | |
.style("alignment-baseline", "middle") | |
.text(function(d) { | |
switch(d){ | |
case 0: | |
return "Лучше" | |
break; | |
default: | |
return "Хуже" | |
break; | |
} | |
}); | |
}, | |
buildSkeleton:function(){ | |
var that = this; | |
this.vis['background'].append('rect') | |
.attr('rx', 6) | |
.attr('ry', 6) | |
.attr('x', this.vis.headerRect.x) | |
.attr('y', this.vis.headerRect.y) | |
.attr('width', this.vis.headerRect.width) | |
.attr('height', this.vis.headerRect.height + this.vis.mainRect.height) | |
.attr('fill', 'white') | |
.style('stroke-width', '1px') | |
.style('stroke', this.options.colors.background) | |
this.vis['background'].append('line') | |
.attr('x1', this.vis.mainRect.x) | |
.attr('y1', this.vis.mainRect.y) | |
.attr('x2', this.vis.mainRect.x + this.vis.mainRect.width) | |
.attr('y2', this.vis.mainRect.y) | |
.style('stroke-width', '1px') | |
.style('stroke', this.options.colors.background) | |
// hand labels | |
this.vis['background'].selectAll('g.label') | |
.data(this.options.bands[this.data.hand]) | |
.join("g") | |
.classed('label', true) | |
.attr("transform",function(fingerKey,i) { | |
var bbox = that.el.select('#'+that.id+'-hand-left-middle').node().getBBox(); | |
x = that.vis.xScale(fingerKey) + that.vis.xScale.bandwidth()/2 - bbox.width/2; | |
ymin = that.vis.mainRect.y+that.vis.mainRect.height; | |
ymax = that.options.viewBox[1]; | |
y = ymin + ((ymax - ymin)/2) - bbox.height/2; | |
return "translate("+x+","+y+")"; | |
}) | |
.each(function(){ | |
d3.select(this).selectAll("*").remove(); | |
}) | |
.append("use") | |
.attr("xlink:href",function(fingerKey,i){return "#"+that.id+"-hand-"+that.data.hand+"-"+fingerKey}) | |
}, | |
buildAxes: function(){ | |
var yAxis = d3.axisLeft() | |
.ticks(5) | |
.tickSize(this.vis.mainRect.width) | |
.tickFormat(function(d){ | |
return d + "\u00B0"; | |
}) | |
.scale(this.vis.yScale); | |
this.vis.yAxis.attr("transform", "translate("+(this.vis.mainRect.x+this.vis.mainRect.width)+",0)") | |
.call(yAxis) | |
.call(function(g){ | |
g.select(".domain").remove(); | |
}) | |
.call(function(g){ | |
g.selectAll(".tick:not(:first-of-type) line") | |
.attr("stroke-opacity", 0.5) | |
.attr("stroke-dasharray", "2,2") | |
g.selectAll(".tick:first-of-type line").remove(); | |
}) | |
.call(function(g){ | |
g.selectAll(".tick text") | |
.style("text-anchor", "end") | |
.attr("dx", -6) | |
//.attr("dy", 0) | |
}) | |
}, | |
buildBars: function(){ | |
var that = this; | |
var roundRadius = 7; | |
// clip paths | |
this.vis.bars.selectAll("clipPath") | |
.data(this.data[this.options.groups[0]]['entries']) | |
.join("clipPath") | |
.attr("id", function(d){ return that.id+"-clip-"+d[0]}) | |
.append("path") | |
.attr("d", function(d){ | |
var onEndValue = that.data[that.options.groups[1]][d[0]]; | |
var worse = false; | |
if ((onEndValue - d[1]) < 0){ | |
worse = true; | |
} | |
var x = that.vis.xScale(d[0]) + that.options.barStrokeWidth/2; | |
var y = that.vis.yScale(d[1]) + that.options.barStrokeWidth/2; | |
var width = that.vis.xScale.bandwidth() - that.options.barStrokeWidth; | |
var height = (that.vis.mainRect.y + that.vis.mainRect.height -1) - that.vis.yScale(d[1]); | |
if(worse){ | |
return that.fullRoundedRect(x, y, width, height, roundRadius - that.options.barStrokeWidth/2) | |
} | |
return that.bottomRoundedRect(x, y, width, height, roundRadius) | |
}); | |
this.vis.bars.selectAll("g") | |
.data(this.options.bands[this.data['hand']]) | |
.join('g') | |
.each(function(fingerKey){ | |
d3.select(this) | |
.selectAll("path.on-start") | |
.data([ that.data[that.options.groups[0]][fingerKey] ]) | |
.join("path") | |
.classed("on-start", true) | |
.style("fill", "white") | |
.style('stroke', 'black') | |
.style('stroke-width', that.options.barStrokeWidth) | |
.attr("d", function(value){ | |
var onEndValue = that.data[that.options.groups[1]][fingerKey]; | |
var worse = false; | |
if ((onEndValue - value) < 0){ | |
worse = true; | |
} | |
var x = that.vis.xScale(fingerKey); | |
var y = that.vis.yScale(value); | |
var width = that.vis.xScale.bandwidth() | |
var height = (that.vis.mainRect.y + that.vis.mainRect.height -1) - that.vis.yScale(value); | |
if(worse){ | |
return that.fullRoundedRect(x, y, width, height, roundRadius) | |
} | |
return that.bottomRoundedRect(x, y, width, height, roundRadius) | |
}) | |
.on("mouseenter", function(event, value){ | |
that.el.select("g.markers g.start."+fingerKey) | |
.style('opacity', '1'); | |
}) | |
.on("mouseleave", function(event, value){ | |
that.el.select("g.markers g.start."+fingerKey) | |
.style('opacity', '0'); | |
}) | |
// onPeriodEnd | |
d3.select(this) | |
.selectAll("path.on-end") | |
.data([ that.data[that.options.groups[1]][fingerKey] ]) | |
.join("path") | |
.classed("on-end", true) | |
.style("fill", function(value){ | |
var onStartValue = that.data[that.options.groups[0]][fingerKey]; | |
var worse = false; | |
if ((value - onStartValue) < 0){ | |
worse = true; | |
} | |
if(worse){ | |
return that.options.colors.worse | |
} | |
return that.options.colors.better | |
}) | |
.style('stroke', function(value){ | |
var onStartValue = that.data[that.options.groups[0]][fingerKey]; | |
var worse = false; | |
if ((value - onStartValue) < 0){ | |
worse = true; | |
} | |
if(worse){ | |
return that.options.colors.worse | |
} | |
return that.options.colors.better | |
}) | |
.style('stroke-width', '0'/*that.options.barStrokeWidth*/) | |
.attr("clip-path",function(value){ | |
var onStartValue = that.data[that.options.groups[0]][fingerKey]; | |
var worse = false; | |
if ((value - onStartValue) < 0){ | |
worse = true; | |
} | |
if(worse) { | |
return "url(#"+that.id+"-clip-"+fingerKey+")" | |
} | |
return null; | |
}) | |
.attr("d", function(value){ | |
var onStartValue = that.data[that.options.groups[0]][fingerKey]; | |
var worse = false; | |
if ((value - onStartValue) < 0){ | |
worse = true; | |
} | |
var x = that.vis.xScale(fingerKey) - that.options.barStrokeWidth/2; | |
var y = that.vis.yScale(value); | |
var width = that.vis.xScale.bandwidth() + that.options.barStrokeWidth; | |
var height = that.vis.yScale(onStartValue) - that.vis.yScale(value) - that.options.barStrokeWidth/2; | |
if(worse) { | |
} | |
return that.figuredRect(x, y, width, height, roundRadius) | |
}).on("mouseenter", function(event, value){ | |
d3.select(this) | |
.style('stroke', function(value){ | |
var onStartValue = that.data[that.options.groups[0]][fingerKey]; | |
var worse = false; | |
if ((value - onStartValue) < 0){ | |
worse = true; | |
} | |
if(worse){ | |
return that.options.colors.worse_hover; | |
} | |
return that.options.colors.better_hover; | |
}) | |
.style('fill', function(value){ | |
var onStartValue = that.data[that.options.groups[0]][fingerKey]; | |
var worse = false; | |
if ((value - onStartValue) < 0){ | |
worse = true; | |
} | |
if(worse){ | |
return that.options.colors.worse_hover; | |
} | |
return that.options.colors.better_hover; | |
}) | |
that.el.select("g.markers g.end."+fingerKey) | |
.style('opacity', '1'); | |
}) | |
.on("mouseleave", function(event, value){ | |
d3.select(this) | |
.style('stroke', function(value){ | |
var onStartValue = that.data[that.options.groups[0]][fingerKey]; | |
var worse = false; | |
if ((value - onStartValue) < 0){ | |
worse = true; | |
} | |
if(worse){ | |
return that.options.colors.worse; | |
} | |
return that.options.colors.better; | |
}) | |
.style('fill', function(value){ | |
var onStartValue = that.data[that.options.groups[0]][fingerKey]; | |
var worse = false; | |
if ((value - onStartValue) < 0){ | |
worse = true; | |
} | |
if(worse){ | |
return that.options.colors.worse; | |
} | |
return that.options.colors.better; | |
}) | |
that.el.select("g.markers g.end."+fingerKey) | |
.style('opacity', '0'); | |
}) | |
}) | |
.on("mouseenter", function(event, fingerKey){ | |
}) | |
.on("mouseleave", function(event, fingerKey){ | |
}) | |
}, | |
buildDefs: function(){ | |
this.vis['defs'] | |
}, | |
buildUnchanged: function(){ | |
var that = this; | |
// create main vis svg | |
this.vis['svg'] = this.el | |
.append("svg") | |
.classed("svg-vis", true) | |
.attr('xmlns', 'http://www.w3.org/2000/svg') | |
.attr("viewBox", "0 0 "+this.options.viewBox[0]+" "+this.options.viewBox[1]) | |
.attr("perserveAspectRatio", "xMinYMid") | |
.on("click", function(event, d){ | |
that.deselectAllAndHide(); | |
}) | |
.append("svg:g") | |
this.vis['defs'] = this.vis['svg'] | |
.append("defs"); | |
this.vis.background = this.vis['svg'].append("svg:g") | |
.classed('background', true); | |
this.vis.legends = this.vis['svg'].append("svg:g") | |
.classed('legends', true); | |
this.vis.hand_legends = this.vis['svg'].append("svg:g") | |
.classed('hand_legends', true); | |
this.vis.yAxis = this.vis['svg'].append("svg:g") | |
.classed('y axis', true); | |
this.vis.markers = this.vis['svg'].append("svg:g") | |
.classed('markers', true); | |
this.vis.bars = this.vis['svg'].append("svg:g") | |
.classed('bars', true); | |
var active_fingers = [ | |
'left-thumb', | |
'left-pointing', | |
'left-middle', | |
'left-ring', | |
'left-pinky', | |
'right-thumb', | |
'right-pointing', | |
'right-middle', | |
'right-ring', | |
'right-pinky', | |
]; | |
var fingers = { | |
left: [ | |
{ | |
x1: 0, | |
y1: 14, | |
x2: 0, | |
y2: 32, | |
hand: 'left', | |
finger: 'pinky' | |
}, | |
{ | |
x1: 6, | |
y1: 6, | |
x2: 6, | |
y2: 32, | |
hand: 'left', | |
finger: 'ring' | |
}, | |
{ | |
x1: 12, | |
y1: 0, | |
x2: 12, | |
y2: 32, | |
hand: 'left', | |
finger: 'middle' | |
}, | |
{ | |
x1: 18, | |
y1: 5, | |
x2: 18, | |
y2: 32, | |
hand: 'left', | |
finger: 'pointing' | |
}, | |
{ | |
x1: 24, | |
y1: 20, | |
x2: 24, | |
y2: 32, | |
hand: 'left', | |
finger: 'thumb' | |
}, | |
], | |
right: [ | |
{ | |
x1: 24, | |
y1: 14, | |
x2: 24, | |
y2: 32, | |
hand: 'right', | |
finger: 'pinky' | |
}, | |
{ | |
x1: 18, | |
y1: 6, | |
x2: 18, | |
y2: 32, | |
hand: 'right', | |
finger: 'ring' | |
}, | |
{ | |
x1: 12, | |
y1: 0, | |
x2: 12, | |
y2: 32, | |
hand: 'right', | |
finger: 'middle' | |
}, | |
{ | |
x1: 6, | |
y1: 5, | |
x2: 6, | |
y2: 32, | |
hand: 'right', | |
finger: 'pointing' | |
}, | |
{ | |
x1: 0, | |
y1: 20, | |
x2: 0, | |
y2: 32, | |
hand: 'right', | |
finger: 'thumb' | |
}, | |
] | |
}; | |
this.vis['defs'].selectAll('g') | |
.data(active_fingers) | |
.enter() | |
.append('g') | |
.attr("id", function(d,i){return that.id+'-hand-'+d}) | |
.each(function(active_finger,i){ | |
d3.select(this).selectAll("line").data(function(){ | |
if(active_finger.indexOf('left') !== -1) | |
return fingers.left; | |
else | |
return fingers.right; | |
}).enter() | |
.append("line") | |
.attr("x1", function(d){return d.x1}) | |
.attr("y1", function(d){return d.y1}) | |
.attr("x2", function(d){return d.x2}) | |
.attr("y2", function(d){return d.y2}) | |
.style("stroke", function(d, i){ | |
if(active_finger == d.hand+'-'+d.finger) | |
return that.options.colors.better; | |
else | |
return that.options.colors.background; | |
}) | |
.style("stroke-linecap", "round") | |
.style("stroke-width", "4") | |
}) | |
}, | |
figuredRect: function(x, y, width, height, radius){ | |
if(Math.abs(height) < radius) | |
radius = Math.floor(Math.abs(height) / 2); | |
var arcRadius = 6; | |
var hLength = (width - 2 * radius - 2 * arcRadius) / 2; | |
if( hLength < 0){ | |
hLength = 0; | |
arcRadius = (width - 2 * radius) / 2; | |
if(arcRadius < 0) | |
arcRadius = 0; | |
} | |
if(height < 0){ | |
return "M" + (x ) + "," + y | |
+ "h" + ((width - 2 * arcRadius) / 2) | |
+ "a" + arcRadius + "," + arcRadius + " 0 0 1 " + arcRadius + "," + arcRadius | |
+ "a" + arcRadius + "," + arcRadius + " 0 0 1 " + arcRadius + "," + -arcRadius | |
+ "h" + ((width - 2 * arcRadius) / 2) | |
+ "v" + (height) | |
+ "h" + -width | |
+ "z" | |
} | |
return "M" + (x + radius) + "," + y | |
+ "h" + (hLength) | |
+ "a" + arcRadius + "," + arcRadius + " 0 0 0 " + arcRadius + "," + -arcRadius | |
+ "a" + arcRadius + "," + arcRadius + " 0 0 0 " + arcRadius + "," + arcRadius | |
+ "h" + (hLength) | |
+ "a" + radius + "," + radius + " 0 0 1 " + radius + "," + radius | |
+ "v" + (height - radius) | |
+ "h" + (-width) | |
+ "v" + (radius - height) | |
+ "a" + radius + "," + radius + " 0 0 1 " + radius + "," + -radius; | |
}, | |
fullRoundedRect: function(x, y, width, height, radius){ | |
return "M" + (x + radius) + "," + y | |
+ "h" + (width - 2 * radius) | |
+ "a" + radius + "," + radius + " 0 0 1 " + radius + "," + radius | |
+ "v" + (height - 2 * radius) | |
+ "a" + radius + "," + radius + " 0 0 1 " + -radius + "," + radius | |
+ "h" + (2 * radius - width) | |
+ "a" + radius + "," + radius + " 0 0 1 " + -radius + "," + -radius | |
+ "v" + (2 * radius - height) | |
+ "a" + radius + "," + radius + " 0 0 1 " + radius + "," + -radius; | |
}, | |
bottomRoundedRect: function(x, y, width, height, radius){ | |
return "M" + x + "," + y | |
+ "h" + width | |
+ "v" + (height - radius) | |
+ "a" + radius + "," + radius + " 0 0 1 " + -radius + "," + radius | |
+ "h" + (2 * radius - width) | |
+ "a" + radius + "," + radius + " 0 0 1 " + -radius + "," + -radius | |
+ "z"; | |
}, | |
deselectAllAndHide: function(){ | |
}, | |
onResize: function (){ | |
this.deselectAllAndHide(); | |
// this.updateSvgWidthAndHeight(); | |
}, | |
updateSvgWidthAndHeight: function (){ | |
var chartElContainer = d3.select(this.options.selector); | |
var chartEl = d3.select(this.options.selector + " > svg"); | |
var chartContainerBounding = chartElContainer.node().getBoundingClientRect(); | |
var targetWidth = chartContainerBounding.width; | |
chartEl.attr("width", targetWidth); | |
chartEl.attr("height", Math.round(targetWidth / this.aspect)); | |
}, | |
}; | |
var id1_data = { | |
"hand": "left", | |
"onPeriodStart": { | |
"pointing": 72.13, | |
"middle": 75.3, | |
"ring": 70.5, | |
"pinky": 76.9 | |
}, | |
"onPeriodEnd": { | |
"pointing": 79.9, | |
"middle": 83.2, | |
"ring": 72.5, | |
"pinky": 65.6 | |
} | |
}; | |
var chart_left = new CHART_1_class('id1', '#chart'); | |
chart_left.setData(id1_data); | |
chart_left.buildVis(); | |
var id2_data = { | |
"hand": "right", | |
"onPeriodStart": { | |
"pointing": 72.13, | |
"middle": 75.3, | |
"ring": 70.5, | |
"pinky": 76.9 | |
}, | |
"onPeriodEnd": { | |
"pointing": 79.9, | |
"middle": 83.2, | |
"ring": 80.5, | |
"pinky": 75.6 | |
} | |
}; | |
var chart_right = new CHART_1_class('id2', '#chart_right'); | |
chart_right.setData(id2_data); | |
chart_right.buildVis(); | |
var newData = { | |
"hand": "right", | |
"onPeriodStart": { | |
"pointing": 62.13, | |
"middle": 55.3, | |
"ring": 40.5, | |
"pinky": 36.9 | |
}, | |
"onPeriodEnd": { | |
"pointing": 87.9, | |
"middle": 79.2, | |
"ring": 23.5, | |
"pinky": 46.6 | |
} | |
}; | |
setTimeout(function(){ | |
chart_left.setData(newData); | |
chart_left.buildVis(); | |
}, 5000); | |
var newData2 = { | |
"hand": "left", | |
"onPeriodStart": { | |
"pointing": 87.13, | |
"middle": 83.3, | |
"ring": 79.5, | |
"pinky": 99.9 | |
}, | |
"onPeriodEnd": { | |
"pointing": 95.9, | |
"middle": 89.2, | |
"ring": 99.5, | |
"pinky": 120.6 | |
} | |
}; | |
setTimeout(function(){ | |
chart_left.setData(newData2); | |
chart_left.buildVis(); | |
}, 12000) | |
var newData3 = { | |
"hand": "left", | |
"onPeriodStart": { | |
"pointing": 95.9, | |
"middle": 89.2, | |
"ring": 99.5, | |
"pinky": 120.6 | |
}, | |
"onPeriodEnd": { | |
"pointing": 87.13, | |
"middle": 63.3, | |
"ring": 49.5, | |
"pinky": 39.9 | |
} | |
} | |
setTimeout(function(){ | |
chart_left.setData(newData3); | |
chart_left.buildVis(); | |
}, 19000) | |
var newData4 = { | |
"hand": "left", | |
"onPeriodStart": { | |
"pointing": 25.9, | |
"middle": 134.2, | |
"ring": 29.5, | |
"pinky": 32.6 | |
}, | |
"onPeriodEnd": { | |
"pointing": 97.13, | |
"middle": 45.3, | |
"ring": 109.5, | |
"pinky": 98.9 | |
} | |
} | |
setTimeout(function(){ | |
chart_left.setData(newData4); | |
chart_left.buildVis(); | |
}, 25000) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#chart { | |
width: 45%; | |
background-color: #ffffff; | |
} | |
#chart_right { | |
width: 40%; | |
background-color: #ffffff; | |
} | |
.noselect { | |
-webkit-touch-callout: none; /* iOS Safari */ | |
-webkit-user-select: none; /* Safari */ | |
-khtml-user-select: none; /* Konqueror HTML */ | |
-moz-user-select: none; /* Old versions of Firefox */ | |
-ms-user-select: none; /* Internet Explorer/Edge */ | |
user-select: none; /* Non-prefixed version, currently | |
supported by Chrome, Edge, Opera and Firefox */ | |
} | |
.y.axis line{ | |
stroke: #d7e5ec; | |
} | |
.y.axis path{ | |
stroke: #d7e5ec; | |
} | |
.y.axis text{ | |
fill: #487e98; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment