feat(*): Add logic

This commit is contained in:
Josh Creek
2022-10-07 18:56:05 +01:00
parent e30dbf3cdb
commit a7e1a81a34
+202
View File
@@ -0,0 +1,202 @@
import * as d3 from 'd3';
const padding = {
top: 20,
right: 40,
bottom: 0,
left: 0,
};
const w = 500 - padding.left - padding.right;
const h = 500 - padding.top - padding.bottom;
const r = Math.min(w, h) / 2;
let rotation = 0;
let oldrotation = 0;
let picked = 100000;
let oldpick = [];
const color = d3.scaleOrdinal(d3.schemeCategory10);
let data = [];
const testData = ['Person 1', 'Person 2', 'Person 3', 'Person 4'];
// eslint-disable-next-line no-unused-vars
function rotTween(to) {
const i = d3.interpolate(oldrotation % 360, rotation);
return (t) => `rotate(${i(t)})`;
}
function stopSpinning() {
console.log('done');
const chartElement = document.getElementById('chart');
chartElement.remove();
const questionElement = document.getElementById('question');
questionElement.remove();
document.getElementById('input-lines').style.display = 'block';
document.getElementById('startSpinning').style.display = 'block';
}
function makeArrowAndCircle(
svg: d3.Selection<SVGSVGElement, any[], HTMLElement, any>,
container: d3.Selection<SVGGElement, any[], HTMLElement, any>,
) {
// make arrow
svg
.append('g')
.attr(
'transform',
`translate(${w + padding.left + padding.right},${h / 2 + padding.top})`,
)
.append('path')
.attr('d', `M-${r * 0.15},0L0,${r * 0.05}L0,-${r * 0.05}Z`)
.style('fill', 'black');
// draw spin circle
container
.append('circle')
.attr('cx', 0)
.attr('cy', 0)
.attr('r', 60)
.style('fill', 'white')
.style('cursor', 'pointer');
// spin text
container
.append('text')
.attr('x', 0)
.attr('y', 10)
.attr('text-anchor', 'middle')
.text('SPIN')
.style('font-weight', 'bold')
.style('font-size', '30px');
}
function drawWheel() {
const svg = d3
.select('#chart')
.append('svg')
.data([data])
.attr('width', w + padding.left + padding.right)
.attr('height', h + padding.top + padding.bottom);
const container = svg
.append('g')
.attr('class', 'chartholder')
.attr(
'transform',
`translate(${w / 2 + padding.left},${h / 2 + padding.top})`,
);
const vis = container.append('g');
const pie = d3
.pie()
.sort(null)
// eslint-disable-next-line no-unused-vars
.value((d) => 1);
// declare an arc generator function
const arc = d3.arc().outerRadius(r).innerRadius(60);
// select paths, use arc generator to draw
const arcs = vis
.selectAll('g.slice')
.data(pie)
.enter()
.append('g')
.attr('class', 'slice');
arcs
.append('path')
.attr('fill', (d, i) => color(i))
.attr('d', (d) => arc(d));
// add the text
arcs
.append('text')
.attr('transform', (d) => {
d.innerRadius = 0;
d.outerRadius = r;
d.angle = (d.startAngle + d.endAngle) / 2;
return `rotate(${(d.angle * 180) / Math.PI - 90})translate(${
d.outerRadius - 10
})`;
})
.attr('text-anchor', 'end')
.text((d, i) => data[i].label);
function spin(d) {
container.on('click', null);
// all slices have been seen, all done
// console.log(`OldPick: ${oldpick.length}`, `Data length: ${data.length}`);
if (oldpick.length === data.length) {
stopSpinning();
return;
}
const ps = 360 / data.length;
const rng = Math.floor(Math.random() * 1440 + 360);
rotation = Math.round(rng / ps) * ps;
picked = Math.round(data.length - (rotation % 360) / ps);
picked = picked >= data.length ? picked % data.length : picked;
if (oldpick.indexOf(picked) !== -1) {
d3.select(this).call(spin);
return;
}
oldpick.push(picked);
rotation += 90 - Math.round(ps / 2);
vis
.transition()
.duration(3000)
.attrTween('transform', rotTween)
.on('end', () => {
// mark question as seen
d3.select(`.slice:nth-child(${picked + 1}) path`).attr('fill', '#111');
// populate question
d3.select('#question h1').text(data[picked].label.trim());
oldrotation = rotation;
/* Get the result value from object "data" */
// console.log(data[picked].value);
/* Comment the below line for restrict spin to single time */
container.on('click', spin);
});
}
container.on('click', spin);
makeArrowAndCircle(svg, container);
}
function startSpinning() {
const textArea = <HTMLInputElement>document.getElementById('input-lines');
const inputData = textArea.value.trim()
? textArea.value.split('\n')
: testData;
const tempData = [];
for (let index = 0; index < inputData.length; index += 1) {
const datum = inputData[index];
tempData.push({
label: datum,
value: index + 1,
question: datum,
});
}
data = tempData;
oldpick = [];
// Make the elements
const chartElement = document.createElement('div');
chartElement.setAttribute('id', 'chart');
document.getElementById('spinner-container').appendChild(chartElement);
const questionElement = document.createElement('div');
questionElement.setAttribute('id', 'question');
const h1Element = document.createElement('h1');
questionElement.appendChild(h1Element);
document.getElementById('spinner-container').appendChild(questionElement);
drawWheel();
document.getElementById('chart').style.display = 'block';
document.getElementById('question').style.display = 'block';
document.getElementById('input-lines').style.display = 'none';
document.getElementById('startSpinning').style.display = 'none';
}
const button = document.getElementById('startSpinning');
button.onclick = startSpinning;