Public
Edited
Jul 6, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Import the selected font faces
style1 = {
yield html`<style>
@import url('https://fonts.googleapis.com/css2?family=${fontName}&display=swap');
@import url('https://fonts.googleapis.com/css2?family=${fontTitle}&display=swap');
</style>`
}
Insert cell
Insert cell
darkRed = (opacity) => d3.color(`rgba(199, 30, 55,${opacity})`)
Insert cell
darkBlue = (opacity) => d3.color(`rgba(24,9,247,${opacity})`)
Insert cell
// function for the dot color
colorDots = (d,name) => {if (d.name === name) {return (d.team === "red") ? darkRed(0.8) : darkBlue(0.8);}
else {return (d.team === "red") ? darkRed(0.3) : darkBlue(0.3);}}
Insert cell
// function for the dot stroke
strokeDots = (d,name) => {if (d.name === name) {return (d.team === "red") ? darkRed(1) : darkBlue(1);}
else {return (d.team === "red") ? darkRed(0.5) : darkBlue(0.5);}}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Define the CCS for the game statistics sheet
html`
<style>
.outer{
border-radius: 8px; padding: 30px; height: ${outerHeight}px; width: ${outerWidth}px;

display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;

background: whitesmoke;

font-family: '${fontName}', sans-serif;
}

h1.game {
font-family: ${fontTitle} ;
text-transform: uppercase ;
text-align: center;
}

ul, li {
list-style: none;
list-style-position:inside;
margin:0;
padding:0;
}

.features{
height: ${heightFeatures}px; width: ${width}px;
margin:0px ; border: 0px; padding: 0px;

display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}

.statsBox {
border: 1px solid #f2f2f2;font-family: {font_family} ; height: ${heightStatsBox}px; width: ${widthStatsBox}px;
border-radius: 8px; padding: 15px;
background: white;

display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

.results {
font-family: {font_family} ; height: ${heightCharts}px; width: ${width}px;
background: white;
}

.note {
width: ${width}px;
font-size: 0.8rem;
}

.svg-tooltip {
font-family: {font_family} ;
background: rgba(69,77,93,.9);
border-radius: .1rem;
color: #fff;
display: block;
font-size: 11px;
max-width: 320px;
padding: .2rem .4rem;
position: absolute;
text-overflow: ellipsis;
white-space: pre;
z-index: 300;
visibility: hidden;
}

</style>`
Insert cell
Insert cell
Insert cell
charts = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, heightCharts]);

// Append a chart for each type of results
stat_row(svg, game_stats, "score", d => d.score, d=> xScore(d.score), xScore, xStat, [0,5000,10000,15000]) ;

stat_row(svg, game_stats, "tags", d => d.tags, d=> xTags(d.tags), xTags, xStat, [0,50,100,150]) ;

stat_row(svg, game_stats, "hits", d => d.hits, d=> xHits(d.hits), xHits, xStat, [0,25,50,75,100]) ;

stat_row(svg, game_stats, "efficiency", d => d.efficiency, d=> xEfficiency(d.efficiency), xEfficiency, xStat, [0,2,4, 6]) ;
return svg.node();
}
Insert cell
Insert cell
stat_row = (svg, data, statName, statFunction, statXPosition, xScale, xLabel, tickValues) => {

// add selectedName (to filter and highlight)

// Create the x axis
svg.append("g")
.attr("transform", `translate(0,${y(statName)+y.bandwidth()/6})`)
.call(d3.axisBottom(xScale).ticks(null, data.format).tickValues(tickValues))
.call(g => g.selectAll(".tick line").clone().attr("stroke-opacity", 0.1)
.attr("transform", `translate(0,${-y.bandwidth()/6})`).attr("y2", y.bandwidth()/6))
.call(g => g.selectAll(".domain").remove());

const g = svg.append("g")
// Append a grey line
g.append("line")
.attr("stroke", "#aaa")
.attr("x1", xScale(0))//d3.min([(xScale(0), xScale(d3.min(data, statFunction)))]))
.attr("x2", xScale(d3.max(data, statFunction)))
.attr("y1", y(statName))
.attr("y2", y(statName))
.style("stroke-dasharray", ("1,1"));
// Append the dots
g.selectAll("circle")
.data(data)
.join("circle")
.attr("id", "dotsPlayers")
.attr("cx", statXPosition)
.attr("cy", y(statName))
.attr("fill", d => colorDots(d,player))//d => (d.team === "red") ? darkRed(0.3) : darkBlue(0.3))//blue) //"orange")//red(0.7)
.attr("stroke", d => strokeDots(d,player))
.attr("stroke-width",d => (d.name === player) ? 3 : 0)
.attr("r", 10)
.append("title")
.text((d,i) => `${d.name}: ${game_stats.map(statFunction)[i]}`);

// Append the label
g.append("text")
.attr("dy", "0.35em")
.attr("x", 0)//xLabel) // place the label at the begining of the row
.attr("y", y(statName))
//.text(d=> `${statName}`)
.text(d=> `${statName}${(statName === "efficiency") ? "*" : ""}`)
//.text(d=> `${statName}${(statName === "efficiency") ? " (m/s)" : ""}${(statName === "efficiency") ? "*" : ""}`) // display the unit for efficiency
.style("text-transform", "capitalize")

// Append the figure
g.append("text")
.attr("dy", "0.35em")
.attr("text-anchor", "end")
.attr("text-align", "right")
.attr("x", xStat)
.attr("y", y(statName))
.text(d=> `${game_stats.filter(d=>d.name === player).map(statFunction)[0]}`);

/* // used to place figures and dot charts
g.append("circle")
.attr("cx", xStat)
.attr("cy", y(statName))
.attr("fill", "orange")
.attr("r", 5);
*/
return svg.node();
}
Insert cell
tooltip = {
stat_row
const tooltip = d3.select("body").append("div")
.attr("class", "svg-tooltip")
.style("position", "absolute")
.style("visibility", "hidden")
.text("I'm a circle!");

d3.select("#dotsPlayers")
.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");
});
}
Insert cell
Insert cell
playerRank = game_stats.filter(d=>d.name === player).map(d=>d.rank)[0]
Insert cell
playerTeam = game_stats.filter(d=>d.name === player).map(d=>d.team)[0]
Insert cell
playerTeamColor = (game_stats.filter(d=>d.name === player).map(d=>d.team)[0] === "red") ? darkRed(1) : darkBlue(1);
Insert cell
//playerTeamColor.formatHex()
Insert cell
Insert cell
y = d3.scaleBand()
.domain(statsList)
.range([margin.top, heightCharts - margin.bottom])
.padding(0.1)
.round(true)
Insert cell
xScore = d3.scaleLinear()
.domain(d3.extent(game_stats, d => d.score))
.range([xStat + margin.left, width - margin.right])
.interpolate(d3.interpolateRound)
Insert cell
xTags = d3.scaleLinear()
.domain([0, d3.max(game_stats, d => d.tags)])
.range([xStat + margin.left, width - margin.right])
.interpolate(d3.interpolateRound)
Insert cell
xHits = d3.scaleLinear()
.domain([0, d3.max(game_stats, d => d.hits)])
.range([xStat + margin.left, width - margin.right])
.interpolate(d3.interpolateRound)
Insert cell
xEfficiency = d3.scaleLinear()
.domain([0, d3.max(game_stats, d => d.efficiency)])
.range([xStat + margin.left, width - margin.right])
.interpolate(d3.interpolateRound)
Insert cell
Insert cell
Insert cell
statsList = ["score","tags","hits","efficiency"]
Insert cell
workbook = FileAttachment("game.xlsx").xlsx()
Insert cell
game_stats = workbook.sheet(0, { headers: true, range: ":H" })
Insert cell
game_stats
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
html = htl.html
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more