function likertscales() {
const numCols = dimensions.numCols
const container = html`<div class="tooltip-demo">
<style>
@font-face {
font-family: 'Raleway';
font-style: regular;
font-weight: 400;
src: url(${fontData}) format('truetype');
}
div.tooltip-demo > div.tooltip {
position: fixed;
display: none;
padding: 12px 6px;
background: #fff;
border: 1px solid #333;
pointer-events: none;
font-family: 'Raleway';
}
</style>
</div>`;
const rowScale = d3.scaleBand()
.domain(d3.range(sub_data.length))
.range([0, dimensions.visHeight])
.padding(0.05)
const y = d3.scaleLinear()
.domain([0,1])
.range([(rowScale.bandwidth()+dimensions.margins.top)/2, rowScale.bandwidth()-dimensions.margins.top]);
const y2 = d3.scaleLinear()
.domain([0,1])
.range([(rowScale.bandwidth()+dimensions.margins.top)/2, dimensions.margins.top*2]);
const x = d3.scaleLinear()
.domain([0, maximum_X_axis])
.range([dimensions.margins.left, colScale.bandwidth()-dimensions.margins.right]);
const xAxis1 = d3.axisTop(x).ticks(maximum_X_axis/dimensions.thickTicksforEvery_x_Entries);
const xAxis2 = d3.axisTop(x).ticks(maximum_X_axis/dimensions.thinTicksforEvery_x_Entries).tickFormat("").tickSize(0);
const yAxis = d3.axisLeft(y);
const svg = d3
.select(container)
.append("svg")
.attr("viewBox", `0 0 ${dimensions.visWidth} ${dimensions.visHeight + dimensions.margins.top + dimensions.margins.bottom}`);
const div = d3
.select(container)
.append("div")
.classed("tooltip", true);
const tooltip = new Tooltip(div);
function tooltipContents(datum) {
const unit = (datum[1] == 1 ? design.xAxisUnit.slice(0,design.xAxisUnit.length-1) : design.xAxisUnit)
return `${datum[0]}: ${datum[1] + " " + unit} `;
}
const defs = html`
<defs>
<style>
@font-face {
font-family: 'Raleway';
font-style: regular;
font-weight: 400;
src: url(${fontData}) format('truetype');
}
<\style>
<\defs>`;
svg.append(() => defs);
svg.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr("width", "100%")
.attr("height", "100%")
.attr("fill", design.backgroundColor);
svg.append('text')
.attr('y', dimensions.margins.top)
.attr('x', dimensions.visWidth/2)
.attr("text-anchor", 'middle')
.attr("font-family", "Raleway")
.attr("fill", "black")
.attr("font-size", design.titleFontSize)
.attr("font-weight", 900)
.text(design.title)
const g = svg.append('g')
.attr('transform', `translate(0, ${dimensions.margins.top})`);
const likerts = g.selectAll('g')
.data(sub_data)
.join('g')
.attr('transform', (d, i) => {
const r = Math.floor(i / numCols);
const c = i % numCols ;
return `translate(${colScale(c)}, ${rowScale(r)})`;
});
likerts.append('rect')
.attr('width', "100%")
.attr('height', "100%")
.attr('fill', design.backgroundColor)
likerts.append('rect')
.attr('width', dimensions.visWidth - dimensions.margins.left/1.3)
.attr('height', rowScale.bandwidth() - dimensions.margins.top)
.attr("x", dimensions.margins.left/2)
.attr("y", dimensions.margins.top-design.questionFontSize/3)
.attr('fill', "none")
.attr('stroke', "#d5d1ab")
.attr("stroke-width", design.gridStrokeWidth*3)
likerts.append("rect")
.attr("x", dimensions.margins.left-dimensions.labelMargins.left)
.attr("y", dimensions.margins.top-dimensions.labelMargins.top - design.questionFontSize)
.attr("width", d => label_lengths_post
.filter(e => e.info == d.question)[0].width
+ 2*dimensions.labelMargins.left)
.attr("height", d => label_lengths_post
.filter(e => e.info == d.question)[0].height
+ 2*dimensions.labelMargins.top)
.attr("fill", design.backgroundColor)
.attr("stroke", "none")
likerts.append('text')
.data(sub_data)
.join('text')
.attr("x", dimensions.margins.left)
.attr("y", dimensions.margins.top)
.attr("text-anchor", "start")
.attr("font-family", "Raleway")
.attr("font-size", design.questionFontSize)
.text(d => d.question);
likerts.append("g")
.attr("transform", `translate(0, ${dimensions.margins.top+30})`)
.attr("color", design.gridColor)
.attr("stroke-width", 1.5)
.call(xAxis1)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll('.tick line')
.clone()
.attr('stroke', design.gridColor)
.attr('stroke-width', design.gridStrokeWidth)
.attr('stroke-dasharray', '2,2')
.attr('y1', 0)
.attr('y2', (dimensions.visHeight/sub_data.length)-dimensions.margins.bottom-dimensions.margins.top-30))
.append("text")
.attr("x", dimensions.visWidth-dimensions.margins.right+8)
.attr("y", -8)
.attr("fill", design.gridColor)
.attr("text-anchor", "start")
.attr("font-family", 'Raleway')
.attr("font-size", design.labelFontSize * 0.7)
.attr("font-weight", 900)
.text(design.xAxisUnit);
likerts.append("g")
.attr("transform", `translate(0, ${dimensions.margins.top+30})`)
.call(xAxis2)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll('.tick line')
.clone()
.attr('stroke', design.gridColor)
.attr('stroke-width', design.gridStrokeWidth)
.attr('stroke-dasharray', '2,10')
.attr('y1', 0)
.attr('y2', (dimensions.visHeight/sub_data.length)-dimensions.margins.bottom-dimensions.margins.top-30))
.append("text")
.attr("x", dimensions.margins.left+6)
.attr("y", -8)
.attr("fill", design.gridColor)
.attr("text-anchor", "start")
.attr("font-family", 'Raleway')
.attr("font-size", design.labelFontSize * 0.7)
.attr("font-weight", 900)
.text(design.xAxisUnit);
likerts.append('g')
.attr('class', 'hi')
.attr("width", "100%")
.attr("height", "100%")
const bubbles = likerts.selectAll('.hi')
.data(d => d.construction)
.join('g')
.attr('transform', d => `translate (${colScale2(d.last_amt)+dimensions.margins.left}, 0)`)
const xs = d3.scaleLinear()
.domain([0, maximum_X_axis])
.range([0, colScale.bandwidth()-dimensions.margins.left-dimensions.margins.right]);
const line1 = d3.line()
.x(d => xs(d["amt"]))
.y(d => y(d["ht"]))
const line2 = d3.line()
.x(d => xs(d["amt"]))
.y(d => y2(d["ht"]))
for(var k = design.desiredLayers-1; k >= 0; k--){
bubbles.append("path")
.attr("fill", d => d.color)
.attr("stroke", "black")
.attr("stroke-width", design.bubbleStrokeWidth)
.attr("d", d => line1.curve(d3.curveBundle.beta(1/design.desiredLayers*k))(d.pts))
.on("mouseover", (event, d) => tooltip.display([d.type, d.amt], tooltipContents))
.on("mouseout", () => tooltip.hide())
.on("mousemove", event => tooltip.move(event))
bubbles.append("path")
.attr("fill", d => d.color)
.attr("stroke", "black")
.attr("stroke-width", design.bubbleStrokeWidth)
.attr("d", d => line2.curve(d3.curveBundle.beta(1/design.desiredLayers*k))(d.pts))
.on("mouseover", (event, d) => tooltip.display([d.type, d.amt], tooltipContents))
.on("mouseout", () => tooltip.hide())
.on("mousemove", event => tooltip.move(event))
}
bubbles.filter(d => d.show_legend =="true" || d.show_legend =="TRUE").append("rect")
.attr("x", d => xs(d.pts[2].amt) - dimensions.margins.left/5)
.attr("y", (d, i) => (i%2 == 0 ? y(1.2)
- label_lengths_post.filter(e => e.info == d.type)[0].height
- dimensions.labelMargins.top/2
:
y2(1.2)
-label_lengths_post.filter(e => e.info == d.type)[0].height
- dimensions.labelMargins.top/2
))
.attr("width", d => label_lengths_post.filter(e => e.info == d.type)[0].width
+ 2*dimensions.labelMargins.left)
.attr("height", d => label_lengths_post.filter(e => e.info == d.type)[0].height
+ 2*dimensions.labelMargins.top)
.attr("fill", "white")
.attr("stroke", d => d.color)
.attr("stroke-width", design.labelStrokeWidth)
bubbles.filter(d => d.show_legend =="true" || d.show_legend =="TRUE").append("text")
.attr("x", d => xs(d.pts[2].amt))
.attr("y", (d, i) => (i%2 == 0 ? y(1.2) : y2(1.2)))
.attr("fill", "black")
.attr("text-anchor", "start")
.attr("font-family", "Raleway")
.attr("font-size", design.labelFontSize)
.text(d => d.type)
bubbles.filter(d => d.show_legend =="true" || d.show_legend =="TRUE").append("path")
.attr("fill", "white")
.attr("stroke", d => d.color)
.attr("d", (d, i)=> `M ${xs(d.pts[2].amt) - 5}
${(i%2 == 0 ? y(1.2)
- label_lengths_post.filter(e => e.info == d.type)[0].height
- dimensions.labelMargins.top/2
+ 1.5
:
y2(1.2)
-label_lengths_post.filter(e => e.info == d.type)[0].height
- dimensions.labelMargins.top/2
+ label_lengths_post.filter(e => e.info == d.type)[0].height
+ 2*dimensions.labelMargins.top)
-0.6 }
L ${xs(d.pts[2].amt)}
${(i%2 == 0 ? y(0.3) : y2(0.3))}
L ${xs(d.pts[2].amt) + 5}
${(i%2 == 0 ? y(1.2)
- label_lengths_post.filter(e => e.info == d.type)[0].height
- dimensions.labelMargins.top/2
+ 1.5
:
y2(1.2)
-label_lengths_post.filter(e => e.info == d.type)[0].height
- dimensions.labelMargins.top/2
+ label_lengths_post.filter(e => e.info == d.type)[0].height
+ 2*dimensions.labelMargins.top)
-0.6 }`)
.attr("stroke-width", design.labelStrokeWidth)
if(design.showCredit){
svg.append('text')
.attr('y', dimensions.visHeight + dimensions.margins.bottom)
.attr('x', 7*dimensions.visWidth/10)
.attr("text-anchor", 'start')
.attr("font-family", "Raleway")
.attr("fill", "grey")
.attr("font-size", 10)
.text("made using observablehq.com/@racquellevia/stylized-likert-scales")
}
return container;
}