Skip to content

Instantly share code, notes, and snippets.

@valex
Created October 20, 2020 22:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save valex/bad305817024915849744ed436ee0339 to your computer and use it in GitHub Desktop.
Save valex/bad305817024915849744ed436ee0339 to your computer and use it in GitHub Desktop.
<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>
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',
worse: 'red',
},
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.2)
.paddingOuter(0.3);
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")
.data(this.options.bands[this.data['hand']])
.join('g')
.attr('class', function(fingerKey){ return fingerKey; })
.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;
})
})
},
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)
});
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', 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);
var y = that.vis.yScale(value);
var width = that.vis.xScale.bandwidth()
var height = that.vis.yScale(onStartValue) - that.vis.yScale(value) - that.options.barStrokeWidth;
if(worse) {
}
return that.figuredRect(x, y, width*0.999, height, roundRadius)
});
})
.on("mouseenter", function(event, fingerKey){
that.el.select("g.markers g."+fingerKey)
.style('opacity', '1');
})
.on("mouseleave", function(event, fingerKey){
that.el.select("g.markers g."+fingerKey)
.style('opacity', '0');
})
},
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)
#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