Verbeter grafische kwaliteit van kleurplaten (v0.4.67-beta) #5
3 changed files with 15 additions and 4 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
0.3.67-beta
|
0.3.68-beta
|
||||||
|
|
|
||||||
|
|
@ -654,6 +654,8 @@ function mountFractions(root,init){
|
||||||
den.onchange=show.onchange=draw;learningShell(root,[field(T('fractionRows'),den),field(T('fractionLabels'),show)],stage);draw();return{getState:()=>({...S})};
|
den.onchange=show.onchange=draw;learningShell(root,[field(T('fractionRows'),den),field(T('fractionLabels'),show)],stage);draw();return{getState:()=>({...S})};
|
||||||
}
|
}
|
||||||
const clockTurnDelta=(next,previous)=>((next-previous+540)%360)-180;
|
const clockTurnDelta=(next,previous)=>((next-previous+540)%360)-180;
|
||||||
|
const clockHourCrossing=(next,previous)=>{const delta=clockTurnDelta(next,previous);return delta>0&&next<previous?1:delta<0&&next>previous?-1:0};
|
||||||
|
const clockStepHour=(hour,step,use24)=>use24?(hour+step+24)%24:((hour-1+step+12)%12)+1;
|
||||||
const clock24Angle=(angle,delta)=>(angle+delta+720)%720;
|
const clock24Angle=(angle,delta)=>(angle+delta+720)%720;
|
||||||
const clock24Hour=(angle,minute)=>((Math.round((angle-minute/2)/30)%24)+24)%24;
|
const clock24Hour=(angle,minute)=>((Math.round((angle-minute/2)/30)%24)+24)%24;
|
||||||
function mountClock(root,init){
|
function mountClock(root,init){
|
||||||
|
|
@ -677,12 +679,12 @@ function mountClock(root,init){
|
||||||
if(interactive){
|
if(interactive){
|
||||||
const updateAnswer=()=>{face.setAttribute('aria-label',time(S.h,S.m));const answer=stage.querySelector('.clock-live-answer');if(answer){answer.innerHTML='';answer.append(timeBlocks(S.h,S.m))}stage.querySelectorAll('.clock-period .tbtn').forEach(button=>{const active=+button.dataset.period===(S.h>=12?12:0);button.classList.toggle('active',active);button.setAttribute('aria-pressed',String(active))})};
|
const updateAnswer=()=>{face.setAttribute('aria-label',time(S.h,S.m));const answer=stage.querySelector('.clock-live-answer');if(answer){answer.innerHTML='';answer.append(timeBlocks(S.h,S.m))}stage.querySelectorAll('.clock-period .tbtn').forEach(button=>{const active=+button.dataset.period===(S.h>=12?12:0);button.classList.toggle('active',active);button.setAttribute('aria-pressed',String(active))})};
|
||||||
const move=e=>{const r=face.getBoundingClientRect(),dx=e.clientX-r.left-r.width/2,dy=e.clientY-r.top-r.height/2,deg=(Math.atan2(dx,-dy)*180/Math.PI+360)%360;
|
const move=e=>{const r=face.getBoundingClientRect(),dx=e.clientX-r.left-r.width/2,dy=e.clientY-r.top-r.height/2,deg=(Math.atan2(dx,-dy)*180/Math.PI+360)%360;
|
||||||
if(face.dataset.hand==='minute'){const wanted=Math.round(deg/6)%60,allowed=minuteValues(),distance=v=>Math.min(Math.abs(v-wanted),60-Math.abs(v-wanted));S.m=allowed.reduce((best,v)=>distance(v)<distance(best)?v:best)}
|
if(face.dataset.hand==='minute'){const previous=face._lastPointerAngle;if(Number.isFinite(previous)){const step=clockHourCrossing(deg,previous);if(step)S.h=clockStepHour(S.h,step,uses24())}face._lastPointerAngle=deg;const wanted=Math.round(deg/6)%60,allowed=minuteValues(),distance=v=>Math.min(Math.abs(v-wanted),60-Math.abs(v-wanted));S.m=allowed.reduce((best,v)=>distance(v)<distance(best)?v:best)}
|
||||||
else if(uses24()){const previous=face._lastPointerAngle;if(Number.isFinite(previous)){face._dragAngle=clock24Angle(face._dragAngle,clockTurnDelta(deg,previous));if(S.linkHands){let bestH=0,bestM=0,bestDistance=720;for(let hour=0;hour<24;hour++)minuteValues().forEach(minute=>{const angle=hour*30+minute/2,difference=Math.min(Math.abs(angle-face._dragAngle),720-Math.abs(angle-face._dragAngle));if(difference<bestDistance){bestDistance=difference;bestH=hour;bestM=minute}});S.h=bestH;S.m=bestM}else S.h=clock24Hour(face._dragAngle,S.m)}face._lastPointerAngle=deg}
|
else if(uses24()){const previous=face._lastPointerAngle;if(Number.isFinite(previous)){face._dragAngle=clock24Angle(face._dragAngle,clockTurnDelta(deg,previous));if(S.linkHands){let bestH=0,bestM=0,bestDistance=720;for(let hour=0;hour<24;hour++)minuteValues().forEach(minute=>{const angle=hour*30+minute/2,difference=Math.min(Math.abs(angle-face._dragAngle),720-Math.abs(angle-face._dragAngle));if(difference<bestDistance){bestDistance=difference;bestH=hour;bestM=minute}});S.h=bestH;S.m=bestM}else S.h=clock24Hour(face._dragAngle,S.m)}face._lastPointerAngle=deg}
|
||||||
else if(S.linkHands){let bestH=12,bestM=0,bestDistance=360;for(let hour=1;hour<=12;hour++)minuteValues().forEach(minute=>{const angle=(hour%12)*30+minute/2,difference=Math.min(Math.abs(angle-deg),360-Math.abs(angle-deg));if(difference<bestDistance){bestDistance=difference;bestH=hour;bestM=minute}});S.h=bestH;S.m=bestM}
|
else if(S.linkHands){let bestH=12,bestM=0,bestDistance=360;for(let hour=1;hour<=12;hour++)minuteValues().forEach(minute=>{const angle=(hour%12)*30+minute/2,difference=Math.min(Math.abs(angle-deg),360-Math.abs(angle-deg));if(difference<bestDistance){bestDistance=difference;bestH=hour;bestM=minute}});S.h=bestH;S.m=bestM}
|
||||||
else S.h=(Math.round((deg-S.m/2)/30)+11)%12+1;paint();updateAnswer()};
|
else S.h=(Math.round((deg-S.m/2)/30)+11)%12+1;paint();updateAnswer()};
|
||||||
const clearDrag=()=>{delete face.dataset.hand;delete face._dragAngle;delete face._lastPointerAngle};
|
const clearDrag=()=>{delete face.dataset.hand;delete face._dragAngle;delete face._lastPointerAngle};
|
||||||
const start=(e,hand)=>{if(S.solved)return;e.preventDefault();e.stopPropagation();face.dataset.hand=hand;if(hand==='hour'&&uses24()){face._dragAngle=S.h*30+S.m/2;face._lastPointerAngle=null}face.setPointerCapture(e.pointerId);move(e)};
|
const start=(e,hand)=>{if(S.solved)return;e.preventDefault();e.stopPropagation();face.dataset.hand=hand;if(hand==='minute')face._lastPointerAngle=null;else if(uses24()){face._dragAngle=S.h*30+S.m/2;face._lastPointerAngle=null}face.setPointerCapture(e.pointerId);move(e)};
|
||||||
hourHand.onpointerdown=e=>start(e,'hour');minuteHand.onpointerdown=e=>start(e,'minute');
|
hourHand.onpointerdown=e=>start(e,'hour');minuteHand.onpointerdown=e=>start(e,'minute');
|
||||||
face.onpointermove=e=>{if(face.hasPointerCapture(e.pointerId))move(e)};
|
face.onpointermove=e=>{if(face.hasPointerCapture(e.pointerId))move(e)};
|
||||||
face.onpointerup=e=>{move(e);face.releasePointerCapture(e.pointerId);clearDrag()};
|
face.onpointerup=e=>{move(e);face.releasePointerCapture(e.pointerId);clearDrag()};
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,8 @@ test('analoge oefenklok is bedienbaar en houdt opdrachtacties buiten instellinge
|
||||||
assert.ok(clockSource.includes('S.h=uses24()?0:12'), 'een 24-uursopdracht begint met een geldige invoerwaarde');
|
assert.ok(clockSource.includes('S.h=uses24()?0:12'), 'een 24-uursopdracht begint met een geldige invoerwaarde');
|
||||||
assert.ok(clockSource.includes("hourHand.onpointerdown=e=>start(e,'hour')"));
|
assert.ok(clockSource.includes("hourHand.onpointerdown=e=>start(e,'hour')"));
|
||||||
assert.ok(clockSource.includes("minuteHand.onpointerdown=e=>start(e,'minute')"));
|
assert.ok(clockSource.includes("minuteHand.onpointerdown=e=>start(e,'minute')"));
|
||||||
|
assert.ok(clockSource.includes("if(hand==='minute')face._lastPointerAngle=null"), 'de minutenwijzer volgt zijn draairichting over twaalf uur');
|
||||||
|
assert.ok(clockSource.includes('if(step)S.h=clockStepHour(S.h,step,uses24())'), 'een volledige minutenomloop verzet de urenwijzer');
|
||||||
assert.ok(!clockSource.includes('face.onpointerdown='), 'de hele klok is geen sleepzone');
|
assert.ok(!clockSource.includes('face.onpointerdown='), 'de hele klok is geen sleepzone');
|
||||||
assert.doesNotMatch(css,/\.clock-hand::(?:before|after)/, 'geen extra sleepzones rond de wijzers');
|
assert.doesNotMatch(css,/\.clock-hand::(?:before|after)/, 'geen extra sleepzones rond de wijzers');
|
||||||
for(const key of ['clockMorning','clockAfternoon','clockEvening','clockNight'])assert.equal((core.match(new RegExp(key+':','g'))||[]).length,2,key);
|
for(const key of ['clockMorning','clockAfternoon','clockEvening','clockNight'])assert.equal((core.match(new RegExp(key+':','g'))||[]).length,2,key);
|
||||||
|
|
@ -110,9 +112,16 @@ test('analoge oefenklok is bedienbaar en houdt opdrachtacties buiten instellinge
|
||||||
assert.match(css,/clock-set-answer\{[^}]*align-items:center[^}]*justify-content:center/);
|
assert.match(css,/clock-set-answer\{[^}]*align-items:center[^}]*justify-content:center/);
|
||||||
assert.match(css,/clock-period \.tbtn\.active\{[^}]*background:var\(--purple\)/);
|
assert.match(css,/clock-period \.tbtn\.active\{[^}]*background:var\(--purple\)/);
|
||||||
const context={};
|
const context={};
|
||||||
runInNewContext(source+';globalThis.__clock24={delta:clockTurnDelta,angle:clock24Angle,hour:clock24Hour}',context);
|
runInNewContext(source+';globalThis.__clock24={delta:clockTurnDelta,crossing:clockHourCrossing,step:clockStepHour,angle:clock24Angle,hour:clock24Hour}',context);
|
||||||
assert.equal(context.__clock24.delta(2,358),4,'vooruit over twaalf uur blijft vooruit draaien');
|
assert.equal(context.__clock24.delta(2,358),4,'vooruit over twaalf uur blijft vooruit draaien');
|
||||||
assert.equal(context.__clock24.delta(358,2),-4,'achteruit over twaalf uur blijft achteruit draaien');
|
assert.equal(context.__clock24.delta(358,2),-4,'achteruit over twaalf uur blijft achteruit draaien');
|
||||||
|
assert.equal(context.__clock24.crossing(2,358),1,'de grote wijzer verhoogt het uur bij een voorwaartse omloop');
|
||||||
|
assert.equal(context.__clock24.crossing(358,2),-1,'de grote wijzer verlaagt het uur bij een achterwaartse omloop');
|
||||||
|
assert.equal(context.__clock24.crossing(30,20),0,'bewegen binnen hetzelfde uur verzet de kleine wijzer niet');
|
||||||
|
assert.deepEqual([
|
||||||
|
context.__clock24.step(11,1,false),context.__clock24.step(12,1,false),context.__clock24.step(1,-1,false),
|
||||||
|
context.__clock24.step(23,1,true),context.__clock24.step(0,-1,true),
|
||||||
|
],[12,1,12,0,23]);
|
||||||
assert.equal(context.__clock24.angle(719,2),1,'na 23 uur draait de klok door naar 0 uur');
|
assert.equal(context.__clock24.angle(719,2),1,'na 23 uur draait de klok door naar 0 uur');
|
||||||
assert.equal(context.__clock24.angle(1,-2),719,'achteruit vanaf 0 uur komt de klok bij 23 uur');
|
assert.equal(context.__clock24.angle(1,-2),719,'achteruit vanaf 0 uur komt de klok bij 23 uur');
|
||||||
assert.deepEqual([0,11,12,23].map(hour=>context.__clock24.hour(hour*30,0)),[0,11,12,23]);
|
assert.deepEqual([0,11,12,23].map(hour=>context.__clock24.hour(hour*30,0)),[0,11,12,23]);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue