Classroom Participation Wheel chooses a useful way for students to respond, such as explaining an answer, asking a question, giving an example, or summarizing a key idea.
class participationresponse strategiesdiscussion promptsactive learning
Wheel of Names
Elimination: OFFAccumulation: OFFAuto-Spin: OFFFair Rotation: OFF
Add entries and spin the wheel.
(()=>{
const r=document.currentScript.closest(‘.wnx-spinner’);
if(!r||r.dataset.ready)return;
r.dataset.ready=’1′;
const $=s=>r.querySelector(s),$$=s=>[…r.querySelectorAll(s)];
const params=new URLSearchParams(location.search),cfg=document.querySelector(‘.wnx-config’);
const mode=cfg?.dataset.mode||r.dataset.mode||’standard’;
const title=cfg?.dataset.title||r.dataset.title||document.querySelector(‘.wn-page h1′)?.textContent||’Wheel of Names’;
const raw=params.get(‘wnitems’)||cfg?.dataset.items||r.dataset.items||’Alice~Bob~Charlie~David~Eve~Frank’;
const palettes=[
((cfg?.dataset.palette)||r.dataset.palette||”).split(‘,’).filter(Boolean),
[‘#6366f1′,’#8b5cf6′,’#ec4899′,’#f97316′,’#14b8a6′,’#3b82f6’],
[‘#ef476f’,’#f78c6b’,’#ffd166′,’#06d6a0′,’#118ab2′,’#7353ba’],
[‘#22c55e’,’#06b6d4′,’#3b82f6′,’#8b5cf6′,’#ec4899′,’#f59e0b’]
].filter(x=>x.length>2);
let colors=palettes[0];
let entries=raw.split(‘~’).map(v=>{try{return decodeURIComponent(v)}catch(e){return v}}).filter(Boolean).map(v=>{
const p=v.split(‘|’);
const weight=mode===’weighted’?Math.max(1,Number(p.pop())||1):1;
return{name:p.join(‘|’),weight,count:0,last:-999,image:”};
});
let angle=0,busy=false,history=[],undo=[],redo=[],spinNumber=0,lastReceipt=null,preSpin=[];
let backgroundImage=”,centerImage=”,backgroundOpacity=.45,centerRadius=76,pendingEntryImage=”,pendingEntryFilename=”;
const imageCache=new Map();
const canvas=$(‘.wnx-canvas’),ctx=canvas.getContext(‘2d’),spin=$(‘.wnx-spin’),result=$(‘.wnx-result’),list=$(‘.wnx-list’);
const elimination=$(‘.wnx-elimination’),accumulation=$(‘.wnx-accumulation’),auto=$(‘.wnx-auto’),winnerCount=$(‘.wnx-winner-count’),duration=$(‘.wnx-duration’);
const balance=$(‘.wnx-smart-balance’),cooldown=$(‘.wnx-smart-cooldown’);
$(‘.wnx-title’).textContent=title;
elimination.checked=mode===’norepeat’||params.get(‘wnremove’)===’1′;
winnerCount.value=mode===’multi’?Math.max(1,Number(cfg?.dataset.count||r.dataset.count)||3):1;
$(‘.wnx-multi-field’).classList.toggle(‘wnx-hidden’,mode!==’multi’);
const escapeHtml=s=>String(s).replace(/[&”‘]/g,m=>({‘&’:’&’,”:’>’,'”‘:’"’,”‘”:’'’}[m]));
const snapshot=()=>JSON.stringify(entries);
const save=()=>{undo.push(snapshot());if(undo.length>25)undo.shift();redo=[];};
const randomInt=n=>{if(n=limit);return a[0]%n;};
function getImage(src){
if(!src)return null;
if(imageCache.has(src))return imageCache.get(src);
const img=new Image();
img.onload=draw;
img.src=src;
imageCache.set(src,img);
return img;
}
function drawCover(img,x,y,w,h){
if(!img||!img.complete||!img.naturalWidth)return;
const scale=Math.max(w/img.naturalWidth,h/img.naturalHeight);
const dw=img.naturalWidth*scale,dh=img.naturalHeight*scale;
ctx.drawImage(img,x+(w-dw)/2,y+(h-dh)/2,dw,dh);
}
function readOptimizedImage(file,maxSize=1000){
return new Promise((resolve,reject)=>{
if(!file||!file.type.startsWith(‘image/’)){reject(new Error(‘Please choose an image file.’));return;}
const reader=new FileReader();
reader.onerror=()=>reject(new Error(‘The image could not be read.’));
reader.onload=()=>{
const img=new Image();
img.onerror=()=>reject(new Error(‘The image format is not supported.’));
img.onload=()=>{
const scale=Math.min(1,maxSize/Math.max(img.naturalWidth,img.naturalHeight));
const w=Math.max(1,Math.round(img.naturalWidth*scale)),h=Math.max(1,Math.round(img.naturalHeight*scale));
const temp=document.createElement(‘canvas’);temp.width=w;temp.height=h;
const t=temp.getContext(‘2d’);t.drawImage(img,0,0,w,h);
const type=file.type===’image/png’?’image/png’:’image/jpeg’;
resolve(temp.toDataURL(type,type===’image/jpeg’?.86:undefined));
};
img.src=String(reader.result||”);
};
reader.readAsDataURL(file);
});
}
const smartOn=()=>!elimination.checked&&(balance.checked||Number(cooldown.value)>0);
function eligibleEntries(){
let pool=[…entries];
if(!smartOn())return pool;
const cd=Number(cooldown.value);
if(cd>0){const cooled=pool.filter(e=>spinNumber-e.last>=cd);if(cooled.length)pool=cooled;}
if(balance.checked&&pool.length){const min=Math.min(…pool.map(e=>e.count));pool=pool.filter(e=>e.count===min);}
return pool.length?pool:[…entries];
}
function segments(){
const total=entries.reduce((s,e)=>s+e.weight,0)||1;
let used=0;
return entries.map(entry=>{const start=used/total*Math.PI*2;used+=entry.weight;return{entry,start,end:used/total*Math.PI*2};});
}
function draw(){
const size=900,center=450,radius=418,segs=segments(),allowed=new Set(eligibleEntries());
ctx.clearRect(0,0,size,size);
if(backgroundImage){
const img=getImage(backgroundImage);
ctx.save();ctx.beginPath();ctx.arc(center,center,radius,0,Math.PI*2);ctx.clip();ctx.globalAlpha=backgroundOpacity;drawCover(img,center-radius,center-radius,radius*2,radius*2);ctx.restore();
}
if(!segs.length){
ctx.beginPath();ctx.arc(center,center,radius,0,Math.PI*2);ctx.fillStyle=’#0b1628′;ctx.fill();ctx.strokeStyle=’rgba(129,140,248,.24)’;ctx.lineWidth=6;ctx.stroke();ctx.fillStyle=’#94a3b8′;ctx.font=’800 34px system-ui’;ctx.textAlign=’center’;ctx.fillText(‘Add entries’,center,center);return;
}
segs.forEach((seg,index)=>{
const dim=smartOn()&&!allowed.has(seg.entry);
const start=seg.start+angle,end=seg.end+angle;
ctx.save();
ctx.globalAlpha=dim?.2:1;
ctx.beginPath();ctx.moveTo(center,center);ctx.arc(center,center,radius,start,end);ctx.closePath();
if(seg.entry.image){
ctx.save();ctx.clip();drawCover(getImage(seg.entry.image),center-radius,center-radius,radius*2,radius*2);ctx.restore();
ctx.globalAlpha=dim?.12:.22;ctx.fillStyle=colors[index%colors.length];ctx.fill();ctx.globalAlpha=dim?.2:1;
}else{
ctx.fillStyle=colors[index%colors.length];
if(backgroundImage)ctx.globalAlpha=dim?.14:.72;
ctx.fill();ctx.globalAlpha=dim?.2:1;
}
ctx.strokeStyle=’rgba(255,255,255,.82)’;ctx.lineWidth=5;ctx.stroke();
const mid=(seg.start+seg.end)/2+angle;
ctx.translate(center,center);ctx.rotate(mid);ctx.textAlign=’right’;ctx.fillStyle=’#fff’;ctx.shadowColor=’rgba(0,0,0,.55)’;ctx.shadowBlur=8;
ctx.font=`850 ${Math.max(18,Math.min(33,350/entries.length+16))}px system-ui`;
const label=seg.entry.name.length>22?seg.entry.name.slice(0,20)+’…’:seg.entry.name;
ctx.fillText(label,radius-34,10);ctx.restore();
});
ctx.save();ctx.beginPath();ctx.arc(center,center,centerRadius,0,Math.PI*2);ctx.clip();
if(centerImage){drawCover(getImage(centerImage),center-centerRadius,center-centerRadius,centerRadius*2,centerRadius*2);}else{ctx.fillStyle=’#0b1628′;ctx.fillRect(center-centerRadius,center-centerRadius,centerRadius*2,centerRadius*2);}
ctx.restore();ctx.beginPath();ctx.arc(center,center,centerRadius,0,Math.PI*2);ctx.strokeStyle=’rgba(255,255,255,.24)’;ctx.lineWidth=10;ctx.stroke();
}
function updateBadges(){
[[ $(‘.wnx-badge-elimination’),elimination,’Elimination’],[$(‘.wnx-badge-accumulation’),accumulation,’Accumulation’],[$(‘.wnx-badge-auto’),auto,’Auto-Spin’],[$(‘.wnx-badge-smart’),{checked:smartOn()},’Fair Rotation’]].forEach(([el,input,label])=>{el.textContent=`${label}: ${input.checked?’ON’:’OFF’}`;el.classList.toggle(‘is-on’,input.checked);});
}
function balanceScore(){
if(!entries.length)return 100;
const total=entries.reduce((s,e)=>s+e.count,0),mean=total/entries.length;
if(!mean)return 100;
const deviation=entries.reduce((s,e)=>s+Math.abs(e.count-mean),0)/entries.length;
return Math.max(0,Math.round(100-deviation/mean*100));
}
function updateDashboard(){
$(‘.wnx-balance-score’).textContent=balanceScore()+’%’;$(‘.wnx-smart-spins’).textContent=String(spinNumber);
$(‘.wnx-smart-counts’).innerHTML=[…entries].sort((a,b)=>a.count-b.count||a.name.localeCompare(b.name)).map(e=>`
${escapeHtml(e.name)}${e.count}
`).join(”)||’
No entries yet.
‘;
const status=$(‘.wnx-smart-status’);
if(elimination.checked&&(balance.checked||Number(cooldown.value)>0))status.textContent=’Smart Fair Rotation is paused while Elimination mode is active.’;
else if(!smartOn())status.textContent=’Pure random mode is active.’;
else{const parts=[];if(balance.checked)parts.push(‘least-selected priority’);if(Number(cooldown.value)>0)parts.push(`${cooldown.value}-spin cooldown`);status.textContent=`Smart mode active: ${parts.join(‘ + ‘)}. Dimmed slices are temporarily ineligible.`;}
}
function render(){
list.innerHTML=entries.map((entry,index)=>`
Classroom Participation Wheel is a free browser-based classroom participation randomizer for questions, examples, review prompts, and low-pressure turns. Edit the sample entries, confirm the eligible list, choose the mode that matches the activity, and spin for a visible random result. Offer think time, opt-outs, partner responses, and approved accommodations so visible randomness supports participation without creating anxiety.
The wheel changes the response format, not the learning goal. Teachers can select the student separately, invite volunteers, or let pairs prepare before sharing. Every wheel entry should be suitable for the lesson and understandable without extra guessing.
💬
Explain
Describe how an answer was reached rather than stating only the final result.
🔎
Question
Ask a relevant question that helps the class inspect an idea more closely.
🧠
Connect
Give an example, comparison, or link to earlier learning.
Adapt the participation wheel to the lesson
Write observable actions
Use clear verbs such as explain, compare, summarize, identify, ask, or demonstrate.
Provide thinking time
Let everyone prepare before the wheel result is used with a student, pair, or group.
Offer equivalent routes
Allow spoken, written, visual, or supported responses when they meet the same learning purpose.