D3 + React Tooltip Not Showing - reactjs

I built a basic heatmap in html using d3, and the tooltips show properly. I've got the same code working in React, and the heatmap is working, and the mouseover, mousemove, and mouseleave functions are working (and the data is printing into the console accurately), but no matter what i try, I can't get the tooltip to actually show up. Any help would be appreciated
Below is my code-
import rd3 from 'react-d3-library';
import * as d3 from 'd3';
import React from 'react';
import data2 from '../data/hmap_current_year.csv';
const node = document.createElement('div');
// set the dimensions and margins of the graph
const margin = { top: 30, right: 60, bottom: 29, left: 60 },
width = 1400 - margin.left - margin.right,
height = 630 - margin.top - margin.bottom;
// append the svg object to the body of the page
const svg = d3
.select(node)
.append("svg")
//add mobile-friendly
.attr("viewBox", `0 0 ${width + margin.left + margin.right} ${height + margin.top + margin.bottom}`)
// .attr("width", width + margin.left + margin.right)
// .attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
d3.csv(data2).then(function (data) {
const var0 = data.map(function (d0) {
return {
month: d3.timeParse("%Y-%m-%d")(d0.time).getMonth(),
day: d3.timeParse("%Y-%m-%d")(d0.time).getDate(),
value: d0.tmed
}
})
const myGroups = Array.from({ length: 31 }, (_, i) => i + 1)
const myMonths = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
]
// Build X scales and axis:
const x = d3.scaleBand()
.range([0, width])
.domain(myGroups)
.padding(0.01);
svg.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x))
.call(g => g.select(".domain").remove());
svg.append("g")
.call(d3.axisTop(x))
.call(g => g.select(".domain").remove());
// Build X scales and axis:
const y = d3.scaleBand()
.range([0, height])
.domain(myMonths)
.padding(0.01);
svg.append("g")
.call(d3.axisLeft(y))
.call(g => g.select(".domain").remove());
svg.append("g")
.call(d3.axisRight(y))
.attr("transform", `translate(${width}, 0)`)
.call(g => g.select(".domain").remove());
// Build color scale
const myColor = d3.scaleQuantile()
.domain([0, 5, 20, 40, 60, 80, 95, 100])
.range([
"#08306B",
"#2171B5",
"#6BAED6",
"#FFFFFF",
"#FCBBA1",
"#FA6A4A",
"#CB181D"
]);
// create a tooltip
const tooltip = d3.select(node)
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px")
.style("margin-bottom", '51px')
// Three function that change the tooltip when user hover / move / leave a cell
const mouseover = function (event, d) {
tooltip
.style("opacity", 1)
d3.select(this)
.style("stroke", "black")
.style("opacity", 1)
}
const mousemove = function (event, d) {
tooltip
.html("The exact value of<br>this cell is: " + d.value)
//accessing values correctly
console.log(d.value, 'HELLO')
.style("left", (event.x) / 2 + "px")
.style("top", (event.y) / 2 + "px")
};
const mouseleave = function (event, d) {
tooltip
.style("opacity", 0)
d3.select(this)
.style("stroke", "none")
.style("opacity", 1)
}
svg.selectAll()
.data(var0)
.join("rect")
.attr("x", function (d) { return x(d.day) })
.attr("y", function (d) { return y(myMonths[d.month]) })
.attr("width", x.bandwidth())
.attr("height", y.bandwidth())
.style("fill", function (d) { return myColor(d.value) })
.style("stroke", "none")
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave)
});
const RD3Component = rd3.Component;
class HeatmapInteractive extends React.Component {
constructor(props) {
super(props);
this.state = {d3: ''}
}
componentDidMount() {
this.setState({d3: node});
}
render() {
return (
<div>
<RD3Component data={this.state.d3}/>
</div>
)
}
}
export default HeatmapInteractive;

here you have done perfectly for defining the tooltip initially
const tooltip = d3.select(node)
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px")
.style("margin-bottom", '51px')
but while hovering you dont have to select any node by using d3.select(this) in mouseover and mouseleave state
you've written this
const mouseover = function (event, d) {
tooltip
.style("opacity", 1)
d3.select(this)
.style("stroke", "black")
.style("opacity", 1)
}
you can simply remove the d3.select(node) from chaining
Insted of doing like that you can simple change only opacity in mouseover
const mouseover = function(event, d) {
tooltip.style("opacity", 1)
}
if it's mouseleave just reverse
const mouseleave = function(event, d) {
tooltip.style("opacity", 0)
}
if it's a mousemove then you have to add html and postion properties for dynamic float of tooltip according to the mouse values like
Note one more thing dont use console in middle of chaining that may break the chaining, if you have tested with it then have to remove otherwise it won't work
const mousemove = function (event, d) {
tooltip
.html("The exact value of<br>this cell is: " + d.value)
.style("opacity", 1)
.style("left", (event.x) + 20 + "px")
.style("top", (event.y) + 20 + "px")
};
i hope this answer will get clarifies you

Related

d3-delaunay lines not showing

I am trying to implement a D3-delaunay on a linechart that has circles as points through which the line crosses. I think i am doing everything right, but i cant seem to see the overlay lines that show up. What am i doing wrong here? i am using the code on this site (https://observablehq.com/#didoesdigital/9-may-2020-d3-scatterplot-with-voronoi-tooltips) as a reference and to implement it on my linechart. If this reference is not suitable, than please provide another template that is similar to scatter plot which I can implement.
class Linechart extends React.Component {
constructor(props) {
super(props)
this.createLineChart = this.createLineChart.bind(this)
}
metricToPercent(metric) {
return (metric / 2 + 0.5) * 100;
};
scoreToDescrip(score) {
if (score >= 0.6) {
return "Good";
} else if (score >= 0) {
return "Average";
} else {
return "Poor";
}
};
componentDidMount() {
this.createLineChart()
}
componentDidUpdate() {
this.createLineChart()
}
createLineChart() {
var margin = {
top: 85,
right: 60,
bottom: 60,
left: 80
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var node = this.node
var divObj = d3.select(node)
var svgObj = divObj
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//Read the data
d3.json("https://raw.githubusercontent.com/QamarFarooq/data-for-testing/main/experience_scores.json").then(function(data) {
var dataArrayWithRemovedEmptyDates = []
// Remove all elements in the array that dont have companyReviewDate property
data.forEach(function(d, i) {
if (d.hasOwnProperty('companyReviewDate')) {
dataArrayWithRemovedEmptyDates.push(d)
}
})
// Transform `companyReviewDate` into an actual date
dataArrayWithRemovedEmptyDates.forEach(function(d) {
d.companyReviewDate = new Date(d.companyReviewDate);
})
// Remove all whitespace in CompanyBusinessName, it creates problems
data.forEach(function(d, i) {
d.companyBusinessName = d.companyBusinessName.split(' ').join('');
})
// group the data: I want to draw one line per group
var sumstat = d3.nest()
.key(function(d) {
return d.companyBusinessName;
})
.entries(dataArrayWithRemovedEmptyDates);
console.log(sumstat)
// Define the div for the tooltip
var tooltip = divObj
.append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.style("background-color", "white")
.style("box-shadow", "0 0 4px #000000")
.style("padding", "10px")
const monthNames = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
var d = new Date();
tooltip.append("div")
.attr("class", "tooltipDate")
.html(monthNames[d.getMonth()] + " " + "(" + d.getFullYear() + ")")
.style("font-size", "20px")
.style("text-align", "center")
tooltip.append("div")
.attr("class", "tooltipName")
.style("text-align", "center")
.style("color", "grey")
tooltip.append("div")
.attr("class", "tooltipTitle")
.style("text-align", "center")
.html("Customer Sentiment")
.style("padding-top", "10px")
tooltip.append("div")
.attr("class", "tooltipScore")
.style("text-align", "center")
.style("color", 'DarkGrey')
.style("font-size", "20px")
tooltip.append("div")
.attr("class", "tooltipPerception")
.style("text-align", "center")
// Add title for linechart
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 25)
.attr("x", 110)
.attr("y", -50)
.text("Customer Experience Score");
// Add X axis --> it is a date format
var x = d3.scaleTime()
.domain(d3.extent(data, function(d) {
return d.companyReviewDate;
}))
.range([0, width]);
svgObj.append("g")
.attr("transform", "translate(0," + height + ")")
.attr("stroke-width", "0.3")
.style("opacity", "0.5")
.call(d3.axisBottom(x).tickSize(-height).tickFormat('').ticks(6))
// ticks
svgObj.append("g")
.style("opacity", "0.7")
.style("font", "14px times")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(5));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return +d.customerExperienceScore;
})])
.range([height, 0]);
svgObj.append("g")
.attr("stroke-width", "0.3")
.style("opacity", "0.5")
.call(d3.axisLeft(y).tickSize(-width).tickFormat('').ticks(5))
// ticks
svgObj.append("g")
.style("opacity", "0.7")
.style("font", "14px times")
.call(d3.axisLeft(y).ticks(5));
// Add X axis label:
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 20)
.attr("x", width / 2 + margin.left)
.attr("y", height + 50)
.style("fill", d3.color("grey"))
.text("Company Review Date");
// Add Y axis label:
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 20)
.attr("transform", "rotate(-90)")
.attr("x", -height / 2 + 40)
.attr("y", -margin.left + 25)
.style("fill", d3.color("grey"))
.text("Customer Experience Score")
// color palette
var key = sumstat.map(function(d) {
return d.key
}) // list of group names
var color = d3.scaleOrdinal()
.domain(key)
.range(['#e41a1c', '#377eb8', '#4daf4a'])
// Add one DOT in the legend for each name.
svgObj.selectAll(".dots")
.data(key)
.enter()
.append("circle")
.attr("cx", function(d, i) {
return 250 + i * 120
})
.attr("cy", -30)
.attr("r", 7)
.style("fill", function(d) {
return color(d)
})
// Add LABEL for legends of each dot.
svgObj.selectAll(".labels")
.data(key)
.enter()
.append("text")
.style("fill", d3.color("grey"))
.attr("x", function(d, i) {
return 270 + i * 120
})
.attr("y", -28)
.text(function(d) {
return d
})
.attr("text-anchor", "left")
.style("alignment-baseline", "middle")
// Highlight individual line and show tooltip
var highlightAndShowTooltip = function(d) {
// this means i am on top of dot circle
if (d.key == null) {
console.log("I am on top of a dot circle of key " + d.companyBusinessName)
//show tooltip
tooltip.style("visibility", "visible")
//Data for Tooltip
tooltip.selectAll(".tooltipName")
.html(d.key)
var score = 12 //this will be dynamic, for now i just set it to 12 to test it out
tooltip.selectAll(".tooltipScore")
.html("<span style='color: #cb9f9e;'>" + score + "</span> / 100")
// first every group turns grey
svgObj.selectAll(".line")
.transition().duration(200)
.style("opacity", "0.5")
svgObj.selectAll(".dot")
.transition().duration(200)
.style("opacity", "0.5")
// Second the hovered line takes its color
svgObj.selectAll("." + d.companyBusinessName)
.transition().duration(200)
.style("stroke", color(d.companyBusinessName))
.style("opacity", "1")
svgObj.selectAll("." + d.companyBusinessName)
.transition().duration(200)
.style("stroke", color(d.companyBusinessName))
.style("opacity", "1")
}
// this means i am on top of line
else if (d.companyBusinessName == null) {
var selected_line = d.key
console.log("i am on top of line " + d.key)
// first every group turns grey
svgObj.selectAll(".line")
.transition().duration(200)
.style("opacity", "0.5")
svgObj.selectAll(".dot")
.transition().duration(200)
.style("opacity", "0.5")
// Second the hovered line takes its color
svgObj.selectAll("." + selected_line)
.transition().duration(200)
.style("stroke", color(selected_line))
.style("opacity", "1")
svgObj.selectAll("." + selected_line)
.transition().duration(200)
.style("stroke", color(selected_line))
.style("opacity", "1")
}
}
// UnHighlight and hide tooltip
var doNotHighlightAndHideTooltip = function(d) {
//hide tooltip
tooltip.style("visibility", "hidden")
//return other lines back to normal opacity
svgObj.selectAll(".line")
.transition().duration(200).delay(50)
.style("stroke", function(d) {
return (color(d.key))
})
.style("opacity", "1")
svgObj.selectAll(".dot")
.transition().duration(200).delay(50)
.style("stroke", function(d) {
return (color(d.companyBusinessName))
})
.style("opacity", "1")
}
// keep showing tooltip as cursor moves along line
var keepShowingTooltip = function(d) {
tooltip.style("top", (d3.event.pageY - 10) + "px").style("left", (d3.event.pageX + 10) + "px")
}
// Draw the line
svgObj.selectAll(".line")
.data(sumstat)
.enter()
.append("path")
.attr("class", function(d) {
return "line " + d.key
}) // 2 class for each line: 'line' and the group name
.attr("fill", "none")
.attr("stroke", function(d) {
return color(d.key)
})
.attr("stroke-width", 4.5)
.attr("d", function(d) {
return d3.line()
.curve(d3.curveMonotoneX)
.x(function(d) {
return x(d.companyReviewDate);
})
.y(function(d) {
return y(+d.customerExperienceScore);
})
(d.values)
});
// This is the experiment with voronoi
// Draw dots on points
svgObj.selectAll(".dot")
//i am using the raw data array, NOT the nested array
.data(dataArrayWithRemovedEmptyDates)
.enter()
.append("circle")
.attr("class", function(d, i) {
return i;
})
.style("fill", "white")
.style("stroke-width", "3px")
.style("stroke", function(d) {
return color(d.companyBusinessName)
})
.attr("cx", function(d) {
return x(d.companyReviewDate);
})
.attr("cy", function(d) {
return y(d.customerExperienceScore);
})
.attr("r", 5.5)
var voronoi = d3.Delaunay
.from(dataArrayWithRemovedEmptyDates, d => x(d.x), d => y(d.y))
.voronoi([margin.left, margin.top, width - margin.right, height - margin.bottom]); // ensures voronoi is limited to the
//Create the voronoi grid
svgObj.append("g")
.attr("class", "voronoiWrapper")
.selectAll("path")
.data(dataArrayWithRemovedEmptyDates)
.enter()
.append("path")
.attr("opacity", 0.5)
.attr("stroke", "#ff1493") // Hide overlay
.attr("fill", "none")
.style("pointer-events", "all")
.attr("d", (d, i) => voronoi.renderCell(i))
.on("mouseover", highlightAndShowTooltip)
.on("mouseout", doNotHighlightAndHideTooltip);
})
}
render() {
return <div ref = {
node => this.node = node
}
className = "example_div" > < /div>
}
}
ReactDOM.render( <Linechart / >, document.querySelector('body'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script src="https://unpkg.com/d3-delaunay#5.3.0/dist/d3-delaunay.min.js"></script>
You didn't look at your data structure well enough: you don't use d.x and d.y, you have your own names for those:
.from(dataArrayWithRemovedEmptyDates, d => x(d.companyReviewDate), d => y(d.customerExperienceScore))
I also removed the margins from the Voronoi. The reasoning is that svgObj is not an svg for you, but a g with a transform. That means that you already applied the margins correctly, so if you add them here, you apply them twice. All this yields the following result:
class Linechart extends React.Component {
constructor(props) {
super(props)
this.createLineChart = this.createLineChart.bind(this)
}
metricToPercent(metric) {
return (metric / 2 + 0.5) * 100;
};
scoreToDescrip(score) {
if (score >= 0.6) {
return "Good";
} else if (score >= 0) {
return "Average";
} else {
return "Poor";
}
};
componentDidMount() {
this.createLineChart()
}
componentDidUpdate() {
this.createLineChart()
}
createLineChart() {
var margin = {
top: 85,
right: 60,
bottom: 60,
left: 80
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var node = this.node
var divObj = d3.select(node)
var svgObj = divObj
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//Read the data
d3.json("https://raw.githubusercontent.com/QamarFarooq/data-for-testing/main/experience_scores.json").then(function(data) {
var dataArrayWithRemovedEmptyDates = []
// Remove all elements in the array that dont have companyReviewDate property
data.forEach(function(d, i) {
if (d.hasOwnProperty('companyReviewDate')) {
dataArrayWithRemovedEmptyDates.push(d)
}
})
// Transform `companyReviewDate` into an actual date
dataArrayWithRemovedEmptyDates.forEach(function(d) {
d.companyReviewDate = new Date(d.companyReviewDate);
})
// Remove all whitespace in CompanyBusinessName, it creates problems
data.forEach(function(d, i) {
d.companyBusinessName = d.companyBusinessName.split(' ').join('');
})
// group the data: I want to draw one line per group
var sumstat = d3.nest()
.key(function(d) {
return d.companyBusinessName;
})
.entries(dataArrayWithRemovedEmptyDates);
console.log(sumstat)
// Define the div for the tooltip
var tooltip = divObj
.append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.style("background-color", "white")
.style("box-shadow", "0 0 4px #000000")
.style("padding", "10px")
const monthNames = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
var d = new Date();
tooltip.append("div")
.attr("class", "tooltipDate")
.html(monthNames[d.getMonth()] + " " + "(" + d.getFullYear() + ")")
.style("font-size", "20px")
.style("text-align", "center")
tooltip.append("div")
.attr("class", "tooltipName")
.style("text-align", "center")
.style("color", "grey")
tooltip.append("div")
.attr("class", "tooltipTitle")
.style("text-align", "center")
.html("Customer Sentiment")
.style("padding-top", "10px")
tooltip.append("div")
.attr("class", "tooltipScore")
.style("text-align", "center")
.style("color", 'DarkGrey')
.style("font-size", "20px")
tooltip.append("div")
.attr("class", "tooltipPerception")
.style("text-align", "center")
// Add title for linechart
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 25)
.attr("x", 110)
.attr("y", -50)
.text("Customer Experience Score");
// Add X axis --> it is a date format
var x = d3.scaleTime()
.domain(d3.extent(data, function(d) {
return d.companyReviewDate;
}))
.range([0, width]);
svgObj.append("g")
.attr("transform", "translate(0," + height + ")")
.attr("stroke-width", "0.3")
.style("opacity", "0.5")
.call(d3.axisBottom(x).tickSize(-height).tickFormat('').ticks(6))
// ticks
svgObj.append("g")
.style("opacity", "0.7")
.style("font", "14px times")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(5));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return +d.customerExperienceScore;
})])
.range([height, 0]);
svgObj.append("g")
.attr("stroke-width", "0.3")
.style("opacity", "0.5")
.call(d3.axisLeft(y).tickSize(-width).tickFormat('').ticks(5))
// ticks
svgObj.append("g")
.style("opacity", "0.7")
.style("font", "14px times")
.call(d3.axisLeft(y).ticks(5));
// Add X axis label:
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 20)
.attr("x", width / 2 + margin.left)
.attr("y", height + 50)
.style("fill", d3.color("grey"))
.text("Company Review Date");
// Add Y axis label:
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 20)
.attr("transform", "rotate(-90)")
.attr("x", -height / 2 + 40)
.attr("y", -margin.left + 25)
.style("fill", d3.color("grey"))
.text("Customer Experience Score")
// color palette
var key = sumstat.map(function(d) {
return d.key
}) // list of group names
var color = d3.scaleOrdinal()
.domain(key)
.range(['#e41a1c', '#377eb8', '#4daf4a'])
// Add one DOT in the legend for each name.
svgObj.selectAll(".dots")
.data(key)
.enter()
.append("circle")
.attr("cx", function(d, i) {
return 250 + i * 120
})
.attr("cy", -30)
.attr("r", 7)
.style("fill", function(d) {
return color(d)
})
// Add LABEL for legends of each dot.
svgObj.selectAll(".labels")
.data(key)
.enter()
.append("text")
.style("fill", d3.color("grey"))
.attr("x", function(d, i) {
return 270 + i * 120
})
.attr("y", -28)
.text(function(d) {
return d
})
.attr("text-anchor", "left")
.style("alignment-baseline", "middle")
// Highlight individual line and show tooltip
var highlightAndShowTooltip = function(d) {
// this means i am on top of dot circle
if (d.key == null) {
console.log("I am on top of a dot circle of key " + d.companyBusinessName)
//show tooltip
tooltip.style("visibility", "visible")
//Data for Tooltip
tooltip.selectAll(".tooltipName")
.html(d.key)
var score = 12 //this will be dynamic, for now i just set it to 12 to test it out
tooltip.selectAll(".tooltipScore")
.html("<span style='color: #cb9f9e;'>" + score + "</span> / 100")
// first every group turns grey
svgObj.selectAll(".line")
.transition().duration(200)
.style("opacity", "0.5")
svgObj.selectAll(".dot")
.transition().duration(200)
.style("opacity", "0.5")
// Second the hovered line takes its color
svgObj.selectAll("." + d.companyBusinessName)
.transition().duration(200)
.style("stroke", color(d.companyBusinessName))
.style("opacity", "1")
svgObj.selectAll("." + d.companyBusinessName)
.transition().duration(200)
.style("stroke", color(d.companyBusinessName))
.style("opacity", "1")
}
// this means i am on top of line
else if (d.companyBusinessName == null) {
var selected_line = d.key
console.log("i am on top of line " + d.key)
// first every group turns grey
svgObj.selectAll(".line")
.transition().duration(200)
.style("opacity", "0.5")
svgObj.selectAll(".dot")
.transition().duration(200)
.style("opacity", "0.5")
// Second the hovered line takes its color
svgObj.selectAll("." + selected_line)
.transition().duration(200)
.style("stroke", color(selected_line))
.style("opacity", "1")
svgObj.selectAll("." + selected_line)
.transition().duration(200)
.style("stroke", color(selected_line))
.style("opacity", "1")
}
}
// UnHighlight and hide tooltip
var doNotHighlightAndHideTooltip = function(d) {
//hide tooltip
tooltip.style("visibility", "hidden")
//return other lines back to normal opacity
svgObj.selectAll(".line")
.transition().duration(200).delay(50)
.style("stroke", function(d) {
return (color(d.key))
})
.style("opacity", "1")
svgObj.selectAll(".dot")
.transition().duration(200).delay(50)
.style("stroke", function(d) {
return (color(d.companyBusinessName))
})
.style("opacity", "1")
}
// keep showing tooltip as cursor moves along line
var keepShowingTooltip = function(d) {
tooltip.style("top", (d3.event.pageY - 10) + "px").style("left", (d3.event.pageX + 10) + "px")
}
// Draw the line
svgObj.selectAll(".line")
.data(sumstat)
.enter()
.append("path")
.attr("class", function(d) {
return "line " + d.key
}) // 2 class for each line: 'line' and the group name
.attr("fill", "none")
.attr("stroke", function(d) {
return color(d.key)
})
.attr("stroke-width", 4.5)
.attr("d", function(d) {
return d3.line()
.curve(d3.curveMonotoneX)
.x(function(d) {
return x(d.companyReviewDate);
})
.y(function(d) {
return y(+d.customerExperienceScore);
})
(d.values)
});
// This is the experiment with voronoi
// Draw dots on points
svgObj.selectAll(".dot")
//i am using the raw data array, NOT the nested array
.data(dataArrayWithRemovedEmptyDates)
.enter()
.append("circle")
.attr("class", function(d, i) {
return i;
})
.style("fill", "white")
.style("stroke-width", "3px")
.style("stroke", function(d) {
return color(d.companyBusinessName)
})
.attr("cx", function(d) {
return x(d.companyReviewDate);
})
.attr("cy", function(d) {
return y(d.customerExperienceScore);
})
.attr("r", 5.5)
var voronoi = d3.Delaunay
.from(dataArrayWithRemovedEmptyDates, d => x(d.companyReviewDate), d => y(d.customerExperienceScore))
.voronoi([0, 0, width, height]); // ensures voronoi is limited to the
console.log(voronoi, dataArrayWithRemovedEmptyDates);
//Create the voronoi grid
svgObj.append("g")
.attr("class", "voronoiWrapper")
.selectAll("path")
.data(dataArrayWithRemovedEmptyDates)
.enter()
.append("path")
.attr("opacity", 0.5)
.attr("stroke", "#ff1493") // Hide overlay
.attr("fill", "none")
.style("pointer-events", "all")
.attr("d", (d, i) => {
return voronoi.renderCell(i);
})
.on("mouseover", highlightAndShowTooltip)
.on("mouseout", doNotHighlightAndHideTooltip);
})
}
render() {
return <div ref = {
node => this.node = node
}
className = "example_div" > < /div>
}
}
ReactDOM.render( <Linechart / >, document.querySelector('body'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script src="https://unpkg.com/d3-delaunay#5.3.0/dist/d3-delaunay.min.js"></script>

Make Axis line grey or reduce opacity

I want to make the axis lines either less opaque, or make them light grey. I tried to just do .style(opacity, 0.5), but it only makes the TICKS opaque, not the actual line itself. I want to make the ACTUAL LINE less opaque/light grey. I also tried adding the call(d3.axisLeft...).style(less opaque) approach but I still get nothing. How do I go about doing that?
import React, {Component, useRef, useEffect} from 'react';
import ExperienceScoresData from './experience_scores';
import * as d3 from "d3";
import { select, csv} from 'd3';
import { extent, max, min } from "d3-array";
ExperienceScoresData.map(function(val){
val.customerExperienceScore *= 100;
return 0;
})
class Linechart extends Component {
constructor(props){
super(props)
this.createBarChart = this.createBarChart.bind(this)
}
componentDidMount() {
this.createBarChart()
}
componentDidUpdate() {
this.createBarChart()
}
createBarChart() {
var margin = {top: 85, right: 60, bottom: 60, left: 80},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var node = this.node
var divObj = select(node)
var svgObj = divObj
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform","translate(" + margin.left + "," + margin.top + ")");
//Read the data
d3.csv("https://raw.githubusercontent.com/QamarFarooq/data-for-testing/main/5_OneCatSevNumOrdered.csv", function(data) {
// group the data: I want to draw one line per group
var sumstat = d3.nest() // nest function allows to group the calculation per level of a factor
.key(function(d) { return d.name;})
.entries(data);
//console.log(sumstat)
// Define the div for the tooltip
var tooltip = divObj
.append("div")
.attr("class","tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "1px")
.style("border-radius", "5px")
.style("padding", "10px")
.text("I AM A TOOLTIP pakistan zindabad");
// Add title for linechart
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 25)
.attr("x", 110)
.attr("y", -50)
.text("Online Ratings");
// Add X axis --> it is a date format
var x = d3.scaleLinear()
.domain(d3.extent(data, function(d) { return d.year; }))
.range([ 0, width ]);
svgObj.append("g")
.attr("transform", "translate(0," + height + ")")
.attr("stroke-width","0.3")
.style("opacity","0.5")
.call(d3.axisBottom(x).tickSize(-height).tickFormat('').ticks(5));
// ticks
svgObj.append("g")
.style("opacity","0.85")
.style("font", "14px times")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(5));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return +d.n; })])
.range([ height, 0 ]);
svgObj.append("g")
.attr("stroke-width","0.3")
.style("opacity","0.5")
.call(d3.axisLeft(y).tickSize(-width).tickFormat('').ticks(5));
// ticks
svgObj.append("g")
.style("opacity","0.85")
.style("font", "14px times")
.call(d3.axisLeft(y).ticks(5));
// Add X axis label:
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 20)
.attr("x", width/2 + margin.left)
.attr("y", height + 50)
.style("fill", d3.color("grey"))
.text("Year Of Birth");
// Add Y axis label:
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 20)
.attr("transform", "rotate(-90)")
.attr("x", -height/2 + 40)
.attr("y", -margin.left + 25)
.style("fill", d3.color("grey"))
.text("N-Value")
// color palette
var key = sumstat.map(function(d){ return d.key }) // list of group names
var color = d3.scaleOrdinal()
.domain(key)
.range(['#e41a1c','#377eb8','#4daf4a'])
// Add one DOT in the legend for each name.
svgObj.selectAll(".dots")
.data(key)
.enter()
.append("circle")
.attr("cx", function(d,i){ return 250 + i*120})
.attr("cy", -30)
.attr("r", 7)
.style("fill", function(d){ return color(d)})
// Add LABEL for legends of each dot.
svgObj.selectAll(".labels")
.data(key)
.enter()
.append("text")
.style("fill", d3.color("grey"))
.attr("x", function(d,i){ return 270 + i*120})
.attr("y", -28)
.text(function(d){ return d})
.attr("text-anchor", "left")
.style("alignment-baseline", "middle")
// Draw the line
svgObj.selectAll(".line")
.data(sumstat)
.enter()
.append("path")
.attr("fill", "none")
.attr("stroke", function(d){ return color(d.key) })
.attr("stroke-width", 4.5)
.attr("d", function(d){
return d3.line()
.curve(d3.curveMonotoneX)
.x(function(d) { return x(d.year); })
.y(function(d) { return y(+d.n); })
(d.values)
})
.on("mouseover", function(){return tooltip.style("visibility", "visible");})
.on("mousemove", function(){return tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px");})
.on("mouseout", function(){return tooltip.style("visibility", "hidden");})
var dataUnpacked = sumstat.map( function(d){return d.values})
console.log(data)
// Draw dots on points
svgObj.selectAll(".lineChartDots")
.data(data)
.enter()
.append("circle")
.attr("class","lineChartDots")
.style("fill","white")
.style("stroke-width", "3px")
.style("stroke", function (d) { return color(d.name) })
.attr("cx", function(d) {return x(d.year); })
.attr("cy", function(d) {return y(d.n); })
.attr("r", 5.5)
})
}
render() {
return <div ref={node => this.node = node} className="example_div"> </div>
}
}
export default Linechart;
The following could change the axis line's opacity.
svg.append("g")
.style("opacity", 0.5)
.call(d3.axisLeft(y))
.call(g => { // manipulate the elements' attrs here
g.select("path")
.attr("opacity", 0.5)
});
I run your code and found that the above code actually worked but since there are two svg lines in the axis, both the axis path and the first background grid line, so you might feel the opacity wasn't changed. See jsfiddle here.
a simple demo:
<!DOCTYPE html>
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<script>
// set the dimensions and margins of the graph
var margin = {top: 10, right: 30, bottom: 30, left: 60},
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
//Read the data
d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/3_TwoNumOrdered_comma.csv",
// When reading the csv, I must format variables:
function(d){
return { date : d3.timeParse("%Y-%m-%d")(d.date), value : d.value }
},
// Now I can use this dataset:
function(data) {
// Add X axis --> it is a date format
var x = d3.scaleTime()
.domain(d3.extent(data, function(d) { return d.date; }))
.range([ 0, width ]);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return +d.value; })])
.range([ height, 0 ]);
svg.append("g")
.style("opacity", 0.5)
.call(d3.axisLeft(y))
.call(g => {
g.select("path")
.attr("opacity", 0.5)
});
// Add the line
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d) { return x(d.date) })
.y(function(d) { return y(d.value) })
)
})
</script>

Color shading with D3 comparative histogram

Edit: due to sizing, probably easiest to view the snippet full screen. Also, use buttons to see what each bars actual color is, which may be helpful.
I am working on an interactive, comparative histogram in D3, however I am struggling with setting the colors appropriately. See below for what I have so far.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedName: 'none'
}
this.chartProps = {
myLightGrey: '#EEE',
myMidGrey: '#888',
myDarkGrey: '#333',
chartWidth: 800, // Dont Change These, For Viewbox
chartHeight: 480, // Dont Change These, For Viewbox
padding: 80,
margin: {top: 20, right: 20, bottom: 30, left: 40},
logoRadius: 800 / 36,
svgID: "nbaStatHistograms"
};
}
// Helper Functions
generateStatData() {
var data = [{"Pos":"PG","teamAbb":"GSW","PTS":37,"REB":6,"AST":3,"STL":0,"BLK":0,"TOV":2,"X3PM":6,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":29,"REB":13,"AST":3,"STL":1,"BLK":3,"TOV":6,"X3PM":4,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":14,"REB":2,"AST":1,"STL":0,"BLK":1,"TOV":0,"X3PM":2,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":29,"REB":2,"AST":8,"STL":4,"BLK":0,"TOV":6,"X3PM":2,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":25,"REB":8,"AST":6,"STL":0,"BLK":1,"TOV":2,"X3PM":4,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":21,"REB":4,"AST":3,"STL":0,"BLK":1,"TOV":2,"X3PM":3,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":30,"REB":4,"AST":5,"STL":3,"BLK":1,"TOV":2,"X3PM":4,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":29,"REB":4,"AST":5,"STL":1,"BLK":0,"TOV":1,"X3PM":3,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":22,"REB":8,"AST":5,"STL":1,"BLK":1,"TOV":4,"X3PM":4,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":20,"REB":5,"AST":8,"STL":2,"BLK":0,"TOV":2,"X3PM":3,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":31,"REB":11,"AST":6,"STL":1,"BLK":2,"TOV":4,"X3PM":4,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":18,"REB":2,"AST":3,"STL":0,"BLK":2,"TOV":1,"X3PM":2,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":27,"REB":6,"AST":8,"STL":1,"BLK":0,"TOV":5,"X3PM":3,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":28,"REB":6,"AST":4,"STL":0,"BLK":2,"TOV":3,"X3PM":3,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":29,"REB":2,"AST":0,"STL":2,"BLK":0,"TOV":4,"X3PM":4,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":31,"REB":5,"AST":6,"STL":2,"BLK":1,"TOV":1,"X3PM":7,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":19,"REB":7,"AST":4,"STL":0,"BLK":0,"TOV":1,"X3PM":2,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":15,"REB":5,"AST":6,"STL":0,"BLK":0,"TOV":3,"X3PM":1,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":21,"REB":8,"AST":4,"STL":3,"BLK":0,"TOV":2,"X3PM":3,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":24,"REB":8,"AST":5,"STL":0,"BLK":3,"TOV":2,"X3PM":2,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":27,"REB":3,"AST":2,"STL":0,"BLK":1,"TOV":1,"X3PM":5,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":22,"REB":0,"AST":11,"STL":2,"BLK":0,"TOV":3,"X3PM":5,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":25,"REB":7,"AST":7,"STL":0,"BLK":2,"TOV":4,"X3PM":4,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":15,"REB":2,"AST":2,"STL":1,"BLK":0,"TOV":2,"X3PM":3,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":16,"REB":5,"AST":4,"STL":2,"BLK":0,"TOV":1,"X3PM":2,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":21,"REB":8,"AST":6,"STL":1,"BLK":3,"TOV":1,"X3PM":1,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":13,"REB":6,"AST":2,"STL":1,"BLK":2,"TOV":2,"X3PM":3,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":22,"REB":8,"AST":8,"STL":2,"BLK":1,"TOV":5,"X3PM":2,"fullName":"Stephen-Curry"},{"Pos":"SG","teamAbb":"GSW","PTS":28,"REB":5,"AST":3,"STL":1,"BLK":0,"TOV":1,"X3PM":6,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":22,"REB":4,"AST":9,"STL":1,"BLK":0,"TOV":2,"X3PM":3,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":29,"REB":5,"AST":4,"STL":2,"BLK":2,"TOV":4,"X3PM":3,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":23,"REB":1,"AST":2,"STL":1,"BLK":0,"TOV":1,"X3PM":4,"fullName":"Klay-Thompson"},{"Pos":"SF","teamAbb":"GSW","PTS":21,"REB":7,"AST":8,"STL":0,"BLK":0,"TOV":2,"X3PM":0,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":15,"REB":4,"AST":5,"STL":0,"BLK":0,"TOV":2,"X3PM":3,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":9,"REB":6,"AST":5,"STL":4,"BLK":0,"TOV":4,"X3PM":2,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":24,"REB":3,"AST":3,"STL":1,"BLK":2,"TOV":3,"X3PM":2,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":13,"REB":7,"AST":3,"STL":0,"BLK":1,"TOV":1,"X3PM":3,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":35,"REB":5,"AST":5,"STL":0,"BLK":1,"TOV":2,"X3PM":4,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":27,"REB":5,"AST":3,"STL":2,"BLK":2,"TOV":4,"X3PM":1,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":17,"REB":4,"AST":1,"STL":0,"BLK":0,"TOV":1,"X3PM":1,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":39,"REB":11,"AST":7,"STL":3,"BLK":0,"TOV":7,"X3PM":4,"fullName":"Stephen-Curry"},{"Pos":"SG","teamAbb":"GSW","PTS":23,"REB":10,"AST":1,"STL":2,"BLK":1,"TOV":2,"X3PM":1,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":24,"REB":5,"AST":6,"STL":1,"BLK":0,"TOV":6,"X3PM":3,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":21,"REB":5,"AST":2,"STL":2,"BLK":0,"TOV":4,"X3PM":3,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":9,"REB":4,"AST":2,"STL":0,"BLK":1,"TOV":1,"X3PM":3,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":33,"REB":7,"AST":4,"STL":2,"BLK":0,"TOV":2,"X3PM":4,"fullName":"Stephen-Curry"},{"Pos":"SG","teamAbb":"GSW","PTS":29,"REB":4,"AST":1,"STL":1,"BLK":1,"TOV":4,"X3PM":5,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":27,"REB":4,"AST":6,"STL":1,"BLK":0,"TOV":1,"X3PM":3,"fullName":"Stephen-Curry"},{"Pos":"SG","teamAbb":"GSW","PTS":24,"REB":4,"AST":2,"STL":2,"BLK":2,"TOV":0,"X3PM":4,"fullName":"Klay-Thompson"},{"Pos":"SG","teamAbb":"GSW","PTS":21,"REB":5,"AST":2,"STL":1,"BLK":1,"TOV":1,"X3PM":5,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":28,"REB":5,"AST":7,"STL":0,"BLK":0,"TOV":5,"X3PM":3,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":29,"REB":7,"AST":5,"STL":1,"BLK":1,"TOV":6,"X3PM":3,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":20,"REB":3,"AST":2,"STL":0,"BLK":0,"TOV":0,"X3PM":4,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":23,"REB":6,"AST":10,"STL":3,"BLK":0,"TOV":4,"X3PM":3,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":25,"REB":2,"AST":7,"STL":0,"BLK":4,"TOV":1,"X3PM":0,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":27,"REB":3,"AST":5,"STL":0,"BLK":0,"TOV":0,"X3PM":3,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":30,"REB":2,"AST":3,"STL":2,"BLK":0,"TOV":0,"X3PM":5,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":24,"REB":3,"AST":7,"STL":1,"BLK":0,"TOV":4,"X3PM":2,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":19,"REB":5,"AST":4,"STL":0,"BLK":0,"TOV":1,"X3PM":2,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":31,"REB":5,"AST":11,"STL":1,"BLK":0,"TOV":2,"X3PM":5,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":19,"REB":7,"AST":5,"STL":2,"BLK":1,"TOV":7,"X3PM":1,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":22,"REB":3,"AST":1,"STL":1,"BLK":0,"TOV":0,"X3PM":4,"fullName":"Klay-Thompson"},{"Pos":"SF","teamAbb":"GSW","PTS":35,"REB":11,"AST":10,"STL":0,"BLK":2,"TOV":3,"X3PM":3,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":22,"REB":4,"AST":3,"STL":0,"BLK":0,"TOV":3,"X3PM":4,"fullName":"Klay-Thompson"},{"Pos":"SF","teamAbb":"GSW","PTS":36,"REB":10,"AST":7,"STL":1,"BLK":5,"TOV":2,"X3PM":3,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":21,"REB":4,"AST":5,"STL":1,"BLK":0,"TOV":3,"X3PM":2,"fullName":"Klay-Thompson"},{"Pos":"SF","teamAbb":"GSW","PTS":28,"REB":9,"AST":5,"STL":0,"BLK":3,"TOV":4,"X3PM":2,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":24,"REB":3,"AST":3,"STL":1,"BLK":0,"TOV":4,"X3PM":4,"fullName":"Klay-Thompson"},{"Pos":"SF","teamAbb":"GSW","PTS":36,"REB":11,"AST":7,"STL":0,"BLK":2,"TOV":5,"X3PM":4,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":25,"REB":5,"AST":0,"STL":0,"BLK":0,"TOV":4,"X3PM":5,"fullName":"Klay-Thompson"},{"Pos":"SF","teamAbb":"GSW","PTS":36,"REB":11,"AST":8,"STL":1,"BLK":3,"TOV":2,"X3PM":4,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":17,"REB":10,"AST":2,"STL":0,"BLK":0,"TOV":2,"X3PM":4,"fullName":"Klay-Thompson"},{"Pos":"SF","teamAbb":"GSW","PTS":22,"REB":8,"AST":2,"STL":0,"BLK":2,"TOV":4,"X3PM":2,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":29,"REB":2,"AST":5,"STL":2,"BLK":0,"TOV":3,"X3PM":3,"fullName":"Klay-Thompson"},{"Pos":"SF","teamAbb":"GSW","PTS":33,"REB":7,"AST":7,"STL":2,"BLK":4,"TOV":1,"X3PM":3,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":16,"REB":1,"AST":1,"STL":1,"BLK":2,"TOV":2,"X3PM":2,"fullName":"Klay-Thompson"},{"Pos":"SF","teamAbb":"GSW","PTS":18,"REB":6,"AST":1,"STL":2,"BLK":2,"TOV":3,"X3PM":0,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":15,"REB":5,"AST":4,"STL":3,"BLK":0,"TOV":3,"X3PM":1,"fullName":"Klay-Thompson"},{"Pos":"SF","teamAbb":"GSW","PTS":25,"REB":7,"AST":3,"STL":2,"BLK":5,"TOV":4,"X3PM":3,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":24,"REB":7,"AST":2,"STL":0,"BLK":0,"TOV":0,"X3PM":4,"fullName":"Klay-Thompson"},{"Pos":"SF","teamAbb":"GSW","PTS":21,"REB":6,"AST":4,"STL":0,"BLK":3,"TOV":2,"X3PM":2,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":15,"REB":0,"AST":1,"STL":0,"BLK":1,"TOV":2,"X3PM":3,"fullName":"Klay-Thompson"},{"Pos":"SF","teamAbb":"GSW","PTS":27,"REB":4,"AST":6,"STL":0,"BLK":0,"TOV":3,"X3PM":4,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":24,"REB":3,"AST":2,"STL":0,"BLK":0,"TOV":2,"X3PM":3,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":38,"REB":4,"AST":3,"STL":0,"BLK":0,"TOV":0,"X3PM":10,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":20,"REB":5,"AST":9,"STL":1,"BLK":1,"TOV":1,"X3PM":2,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":21,"REB":0,"AST":5,"STL":0,"BLK":0,"TOV":3,"X3PM":5,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":32,"REB":5,"AST":8,"STL":1,"BLK":0,"TOV":3,"X3PM":6,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":25,"REB":12,"AST":6,"STL":0,"BLK":4,"TOV":2,"X3PM":1,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":25,"REB":5,"AST":4,"STL":2,"BLK":1,"TOV":1,"X3PM":3,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":29,"REB":9,"AST":5,"STL":1,"BLK":0,"TOV":3,"X3PM":4,"fullName":"Stephen-Curry"},{"Pos":"SG","teamAbb":"GSW","PTS":28,"REB":3,"AST":4,"STL":0,"BLK":0,"TOV":1,"X3PM":6,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":45,"REB":6,"AST":3,"STL":3,"BLK":0,"TOV":2,"X3PM":8,"fullName":"Stephen-Curry"},{"Pos":"SG","teamAbb":"GSW","PTS":10,"REB":4,"AST":3,"STL":1,"BLK":1,"TOV":2,"X3PM":2,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":32,"REB":4,"AST":9,"STL":2,"BLK":0,"TOV":6,"X3PM":5,"fullName":"Stephen-Curry"},{"Pos":"SG","teamAbb":"GSW","PTS":19,"REB":5,"AST":1,"STL":0,"BLK":2,"TOV":0,"X3PM":3,"fullName":"Klay-Thompson"},{"Pos":"SF","teamAbb":"GSW","PTS":40,"REB":4,"AST":4,"STL":1,"BLK":1,"TOV":5,"X3PM":6,"fullName":"Kevin-Durant"},{"Pos":"SF","teamAbb":"GSW","PTS":26,"REB":6,"AST":6,"STL":2,"BLK":0,"TOV":3,"X3PM":2,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":12,"REB":5,"AST":2,"STL":0,"BLK":0,"TOV":2,"X3PM":0,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":24,"REB":6,"AST":9,"STL":1,"BLK":0,"TOV":1,"X3PM":2,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":25,"REB":6,"AST":5,"STL":0,"BLK":1,"TOV":1,"X3PM":3,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":26,"REB":3,"AST":0,"STL":2,"BLK":0,"TOV":0,"X3PM":2,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":23,"REB":4,"AST":8,"STL":2,"BLK":0,"TOV":3,"X3PM":4,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":32,"REB":5,"AST":8,"STL":3,"BLK":1,"TOV":3,"X3PM":4,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":17,"REB":4,"AST":2,"STL":1,"BLK":1,"TOV":2,"X3PM":3,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":30,"REB":9,"AST":4,"STL":1,"BLK":0,"TOV":6,"X3PM":6,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":19,"REB":8,"AST":7,"STL":1,"BLK":0,"TOV":0,"X3PM":0,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":38,"REB":4,"AST":2,"STL":0,"BLK":1,"TOV":3,"X3PM":7,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":19,"REB":1,"AST":8,"STL":2,"BLK":0,"TOV":6,"X3PM":5,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":26,"REB":7,"AST":5,"STL":0,"BLK":2,"TOV":4,"X3PM":4,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":8,"REB":1,"AST":1,"STL":2,"BLK":0,"TOV":1,"X3PM":2,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":32,"REB":6,"AST":7,"STL":0,"BLK":0,"TOV":1,"X3PM":8,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":14,"REB":4,"AST":14,"STL":2,"BLK":2,"TOV":5,"X3PM":2,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":9,"REB":2,"AST":4,"STL":0,"BLK":0,"TOV":0,"X3PM":0,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":25,"REB":5,"AST":9,"STL":3,"BLK":0,"TOV":2,"X3PM":5,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":28,"REB":10,"AST":11,"STL":2,"BLK":3,"TOV":4,"X3PM":6,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":25,"REB":5,"AST":3,"STL":1,"BLK":1,"TOV":3,"X3PM":7,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":49,"REB":4,"AST":5,"STL":2,"BLK":0,"TOV":1,"X3PM":8,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":20,"REB":9,"AST":2,"STL":1,"BLK":1,"TOV":2,"X3PM":1,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":7,"REB":4,"AST":3,"STL":1,"BLK":2,"TOV":1,"X3PM":0,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":14,"REB":2,"AST":5,"STL":0,"BLK":0,"TOV":3,"X3PM":1,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":17,"REB":2,"AST":3,"STL":1,"BLK":0,"TOV":0,"X3PM":0,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":27,"REB":6,"AST":3,"STL":2,"BLK":0,"TOV":3,"X3PM":3,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":23,"REB":5,"AST":6,"STL":2,"BLK":0,"TOV":6,"X3PM":3,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":33,"REB":4,"AST":6,"STL":0,"BLK":0,"TOV":5,"X3PM":6,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":20,"REB":6,"AST":3,"STL":0,"BLK":0,"TOV":1,"X3PM":4,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":24,"REB":6,"AST":4,"STL":2,"BLK":0,"TOV":5,"X3PM":5,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":31,"REB":6,"AST":7,"STL":0,"BLK":2,"TOV":1,"X3PM":0,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":16,"REB":1,"AST":5,"STL":2,"BLK":0,"TOV":0,"X3PM":2,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":21,"REB":5,"AST":5,"STL":1,"BLK":1,"TOV":3,"X3PM":2,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":33,"REB":6,"AST":1,"STL":1,"BLK":1,"TOV":5,"X3PM":3,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":12,"REB":4,"AST":2,"STL":1,"BLK":0,"TOV":3,"X3PM":2,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":20,"REB":7,"AST":8,"STL":0,"BLK":0,"TOV":4,"X3PM":4,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":24,"REB":9,"AST":4,"STL":1,"BLK":2,"TOV":1,"X3PM":4,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":18,"REB":5,"AST":4,"STL":0,"BLK":0,"TOV":3,"X3PM":2,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":17,"REB":4,"AST":8,"STL":2,"BLK":0,"TOV":2,"X3PM":3,"fullName":"Stephen-Curry"},{"Pos":"SF","teamAbb":"GSW","PTS":10,"REB":6,"AST":6,"STL":0,"BLK":2,"TOV":1,"X3PM":0,"fullName":"Kevin-Durant"},{"Pos":"SG","teamAbb":"GSW","PTS":25,"REB":3,"AST":0,"STL":0,"BLK":0,"TOV":3,"X3PM":5,"fullName":"Klay-Thompson"},{"Pos":"PG","teamAbb":"GSW","PTS":22,"REB":9,"AST":7,"STL":0,"BLK":1,"TOV":3,"X3PM":3,"fullName":"Stephen-Curry"}];
return data;
}
round(number, precision) {
var factor = Math.pow(10, precision);
return Math.round(number * factor) / factor;
}
updateButtonColors(button, parent, self) {
const {myLightGrey, myMidGrey, myDarkGrey} = self.chartProps;
parent.selectAll("rect")
.attr("fill", myLightGrey)
parent.selectAll("text")
.attr("fill", myDarkGrey)
button.select("rect")
.attr("fill", myDarkGrey)
button.select("text")
.attr("fill", myLightGrey)
}
xScaleFunc(self) {
const {chartWidth, margin } = self.chartProps;
const statData = self.generateStatData();
// looks to be working correctly here
return d3.scaleLinear()
.domain(d3.extent(statData, stat => stat.AST)).nice()
.range([margin.left, chartWidth - margin.right]);
}
yScaleFunc(self, maxY) {
const { chartHeight, margin } = self.chartProps;
const statData = self.generateStatData();
return d3.scaleLinear()
.domain([0, maxY]).nice()
.range([chartHeight - margin.bottom, margin.top])
}
// Draw Graph Functions
drawHistogram() {
// 0. Setup | Scales and Other Constants
// =======================================
const { chartHeight, chartWidth, margin, myDarkGrey } = this.chartProps;
const { xScaleFunc, yScaleFunc } = this;
const xScale = xScaleFunc(this);
const statData = this.generateStatData()
const histogram = d3.histogram()
.domain(xScale.domain())
.thresholds(xScale.ticks(10))
// ======
// 1. Draw The Histogram For Each Guy
// ===================================
const histogramBars = d3.select('g.histogramBars');
const allPlayers = [... new Set(statData.map(row => row.fullName))]
// loop to find max Y for yScale
let maxY = 0;
for(var i = 0; i < allPlayers.length; i++) {
const playerStats = statData
.filter(row => row.fullName == allPlayers[i])
.map(row => row.AST)
const playerBinnedData = histogram(playerStats)
let thisYmax = d3.max(playerBinnedData, d => d.length)
maxY = (thisYmax > maxY) ? thisYmax : maxY;
}
const yScale = yScaleFunc(this, maxY);
// loop to create histogram for each player
const colors = ['yellow', 'red', 'blue'];
for(var i = 0; i < allPlayers.length; i++) {
const playerStats = statData
.filter(row => row.fullName == allPlayers[i])
.map(row => row.AST)
const playerBinnedData = histogram(playerStats)
const playerBars = histogramBars
.append("g")
.selectAll(`.rect-${allPlayers[i]}`)
.data(playerBinnedData)
.enter()
.append("rect")
.attr("class", `rect-${allPlayers[i]}`)
.attr("x", d => xScale(d.x0) + 1)
.attr("width", d => Math.max(0, xScale(d.x1) - xScale(d.x0) - 1))
.attr("y", d => yScale(d.length))
.attr("height", d => yScale(0) - yScale(d.length))
.attr("fill", colors[i])
.attr("stroke", myDarkGrey)
.attr("stroke-width", 2)
.attr("opacity", 0.5);
}
const xAxis = g => g
.attr("transform", `translate(0,${chartHeight - margin.bottom})`)
.call(d3.axisBottom(xScale).tickSizeOuter(0))
.call(g => g.append("text")
.attr("x", chartWidth - margin.right)
.attr("y", -4)
.attr("fill", "#000")
.attr("font-weight", "bold")
.attr("text-anchor", "end")
.text('X Axis Name Goes Here'))
histogramBars.append("g")
.call(xAxis);
const yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(yScale))
.call(g => g.select(".domain").remove())
.call(g => g.select(".tick:last-of-type text").clone()
.attr("x", 4)
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text('# of Games'))
histogramBars.append("g")
.call(yAxis);
}
drawNameHoverButtons() {
// Setup Constants
// ==================
const { myLightGrey, myMidGrey, myDarkGrey } = this.chartProps;
const { updateButtonColors } = this;
const bWidth= 75;
const bHeight= 25;
const bSpace= 5;
const statData = this.generateStatData()
const allPlayers = [... new Set(statData.map(row => row.fullName))]
const nameHoverButtons = d3.select('g.nameHoverButtons')
// ====
// Add buttons
// ==================
const self = this;
const buttonGroup = nameHoverButtons.selectAll("g.nameButton")
.data(allPlayers)
.enter()
.append("g")
.attr("class", "button")
.style("cursor", "pointer")
buttonGroup.append("rect")
.attr("class","buttonRect")
.attr("width",bWidth)
.attr("height",bHeight)
.attr("x", (d,i) => 500 + (bWidth+bSpace)*i)
.attr("y", 0)
.attr("rx", 4) // rx and ry give the buttons rounded corners
.attr("ry", 4)
.attr("fill", myLightGrey)
.attr("stroke", myDarkGrey)
.attr("stroke-width", "0.1em")
// adding text to each toggle button group
buttonGroup.append("text")
.attr("class","buttonText")
.attr("font-family", "arial")
.attr("font-size", "0.6em")
.attr("x", (d,i) => 500 + (bWidth+bSpace)*i + bWidth/2)
.attr("y", 10)
.attr("text-anchor","middle")
.attr("dominant-baseline","central")
.attr("fill", '#222')
.text(d => d)
buttonGroup
.on("click", function(d,i) {
updateButtonColors(d3.select(this), d3.select(this.parentNode), self)
self.setState({selectedName: allPlayers[i]})
})
.on("mouseover", function(d, i) {
if (d3.select(this).select("rect").attr("fill") != myDarkGrey) {
d3.select(this)
.select("rect")
.attr("fill", myMidGrey); // lol almost here keep trying
}
d3.selectAll(`g.histogramBars rect`)
.attr('opacity', 0.1)
d3.selectAll(`.rect-${allPlayers[i]}`)
.attr('z-index', 3)
.attr('opacity', 1)
})
.on("mouseout", function(d, i) {
if (d3.select(this).select("rect").attr("fill") != myDarkGrey) {
d3.select(this)
.select("rect")
.attr("fill", myLightGrey);
}
d3.selectAll(`g.histogramBars rect`)
.attr('opacity', 0.5)
d3.selectAll(`.rect-${allPlayers[i]}`)
.attr('z-index', 1)
.attr('opacity', 0.5)
})
}
drawStatButtons() {
}
// When component mounts, get
componentDidMount() {
const { chartHeight, chartWidth, svgID } = this.chartProps;
d3.select(`#${svgID}`)
.attr('width', '100%')
.attr('height', '100%')
.attr('viewBox', "0 0 " + chartWidth + " " + chartHeight)
.attr('preserveAspectRatio', "xMaxYMax");
this.drawHistogram()
this.drawNameHoverButtons()
}
render() {
const { svgID } = this.chartProps;
return (
<div ref="scatter">
<svg id={svgID}>
<g className="histogramBars" />
<g className="nameHoverButtons" />
<g className="points" />
</svg>
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.2.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.8.0-alpha.1/d3-tip.js"></script>
<div id='root'>
FUCKING WORK
</div>
My issue I think is a simple one, but hard to describe typing, but I will try.
The 3 main colors used in this graph are red, blue and yellow. However, if you look in column 3, you will see blue, darker blue, and purple. This is because of the order of my for loop, where the histogram for yellow is plotted first, then the histogram for red, then the histogram for blue bars. Since the blue bars are plotted last, the color with by far the most emphasis is blue, even though I've used an opacity of 0.5.
For example, if you were to change the line in my code where I create the color array, by reordering the colors, you'll see a new emphasis placed on whichever color is plotted last.
Instead of blue, dark blue, purple, I would like to see the yellow, red and blue in each bar column. If it is the case for a particular histogram column that yellow has the lowest y value (say y=3), then red (y=5), then blue (y=8), I would like the color of emphasis for the bottom part of the bar (0-3) to be yellow, for the middle part of the bar (3-5) to be red, and for the top part of the bar to be blue (5-8).
Please let me know if I can elaborate more on what I'm looking for. Otherwise, appreciate in advance any help I can get with this!

How to create a bar chart with custom string labels with d3 in angular?

I am using d3 in angular to create a bar chart of feelings from very bad (1) to very good (5) with the feelings as labels on the yAxis. I am running into an error: Argument of type '(d: any, i: any) => any' is not assignable to parameter of type 'string'. I've been able to use "any" to get around similar type errors, but it isn't working in this part: .tickFormat(function(d:any,i:any): any { return tickLabels[i] }) ;
interface Datum {
created_at: string,
decription: string,
feeling: string,
feeling_attachments: any,
feeling_in_number: number,
id: number,
tag_user_ids: string,
tags: any,
visibility: string
}
buildChart2(feels: Array<Datum>){
var feelsData = feels.reverse()
var margin = {top: 20, right: 30, bottom: 30, left: 40},
width = 800 - margin.left - margin.right,
height = 250 - margin.top - margin.bottom;
var ticks = [0,1,2,3,4,5];
var tickLabels = ['','very bad','bad','neutral','good','very good']
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], 0);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickValues(ticks)
.tickFormat(function(d:any,i:any): any { return tickLabels[i] }) ;
var chart = d3.select(".feelsChart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
y.domain([0, d3.max(feelsData, function(d: any): any { return d.feeling_in_number; })]);
var barWidth = width / feelsData.length;
var bar = chart.selectAll("g")
.data(feelsData)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(" + i * barWidth + ",0)"; });
bar.append("rect")
.attr("y", function(d) { return y(d.feeling_in_number); })
.attr("height", function(d) { return height - y(d.feeling_in_number); })
.attr("width", barWidth - 1);
bar.append("text")
.attr("x", barWidth / 2)
.attr("y", function(d) { return y(d.feeling_in_number) + 3; })
.attr("dy", ".75em");
// .text(function(d) { return d.feeling_in_number; });
chart.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Frequency");
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
}
I've been trying to work off Mike Bostock's Let's Make A Bar Chart tutorial and a few other stack overflow questions about d3 in angular.
D3.JS change text in axis ticks to custom strings
It looks like you are trying to follow some guides that uses javascript with the older style of declaring functions. Typescript uses the newer ES6 syntax with arrow functions. So the function should be written like this in typescript:
.tickFormat((d:any, i:any): any => return tickLabels[i]);
You can read more about functions in typescript here

How do i give ellipsis in axis labels in d3 v4?

Here is my code snippet for implementing the ellipsis on x axis labels in d3 v3.
Can someone help me figure out the changes needed to my code in v4??
//function for adding '...' if length is more than 50 px
var wrap = function () {
var self = d3.select(this),
textLength = self.node().getComputedTextLength(),
text = self.text();
while (textLength > (50) && text.length > 0) {
text = text.slice(0, -1);
self.text(text + '...');
textLength = self.node().getComputedTextLength();
}
};
//calling the function
svg.select('.x.axis')
.call(xAxis)
.selectAll('text')
.style('text-anchor', 'end')
.attr('fill', '#8a9299')
.attr('transform', 'rotate(-60)')
.each(wrap);
You just need to save the group element containing x-axis into a variable and use as shown below.
var wrap = function() {
var self = d3.select(this),
textLength = self.node().getComputedTextLength(),
text = self.text();
while (textLength > (50) && text.length > 0) {
text = text.slice(0, -1);
self.text(text + '...');
textLength = self.node().getComputedTextLength();
}
};
//calling the function
xAxis.selectAll('text')
.style('text-anchor', 'end')
.attr('fill', '#8a9299')
.attr('transform', 'rotate(-60)')
.each(wrap);
// set the dimensions and margins of the graph
var margin = {
top: 20,
right: 20,
bottom: 30,
left: 40
},
width = 250 - margin.left - margin.right,
height = 250 - margin.top - margin.bottom;
// set the ranges
var x = d3.scaleBand()
.range([0, width])
.padding(0.1);
var y = d3.scaleLinear()
.range([height, 0]);
// append the svg object to the body of the page
// append a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
var data = [{
"salesperson": "Bob Patrickson",
"sales": 33
},
{
"salesperson": "Robin Dearden",
"sales": 12
},
{
"salesperson": "Anne Hathaway",
"sales": 41
},
{
"salesperson": "Mark Wahlberg",
"sales": 16
}
];
// format the data
data.forEach(function(d) {
d.sales = +d.sales;
});
// Scale the range of the data in the domains
x.domain(data.map(function(d) {
return d.salesperson;
}));
y.domain([0, d3.max(data, function(d) {
return d.sales;
})]);
// append the rectangles for the bar chart
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.salesperson);
})
.attr("width", x.bandwidth())
.attr("y", function(d) {
return y(d.sales);
})
.attr("height", function(d) {
return height - y(d.sales);
});
// add the x Axis
var xAxis = svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the y Axis
svg.append("g")
.call(d3.axisLeft(y));
var wrap = function() {
var self = d3.select(this),
textLength = self.node().getComputedTextLength(),
text = self.text();
while (textLength > (50) && text.length > 0) {
text = text.slice(0, -1);
self.text(text + '...');
textLength = self.node().getComputedTextLength();
}
};
//calling the function
xAxis.selectAll('text')
.style('text-anchor', 'end')
.attr('fill', '#8a9299')
.attr('transform', 'rotate(-60)')
.each(wrap);
.bar {
fill: steelblue;
}
<script src="//d3js.org/d3.v4.min.js"></script>

Resources