feature/layout-updates #1
29
src/tone.js
29
src/tone.js
@ -42,8 +42,8 @@ const pulse = (inNode, inStart, inDuration) =>
|
||||
change(inNode, 0, (inStart+inDuration) );
|
||||
};
|
||||
|
||||
/** @type {(inDuration:number, inContinuous:boolean, inChannel:number, inFreq:number, indBHL:number)=>void} */
|
||||
const Start = (inDuration, inContinuous, inChannel, inFreq, indBHL) =>
|
||||
/** @type {(inContinuous:boolean, inChannel:number, inFreq:number, indBHL:number)=>void} */
|
||||
export const Play = (inContinuous, inChannel, inFreq, indBHL) =>
|
||||
{
|
||||
Context.resume();
|
||||
GainBeep.gain.cancelScheduledValues(Context.currentTime);
|
||||
@ -64,29 +64,4 @@ const Start = (inDuration, inContinuous, inChannel, inFreq, indBHL) =>
|
||||
pulse(GainBeep.gain, 0.33, 0.2);
|
||||
pulse(GainBeep.gain, 0.66, 0.2);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export const useTone =()=>
|
||||
{
|
||||
const [responseGet, responseSet] = React.useState(0);
|
||||
const [playGet, playSet] = React.useState(0);
|
||||
React.useEffect(()=>
|
||||
{
|
||||
/** @type {number|undefined} */
|
||||
let timer;
|
||||
if(playGet == 1)
|
||||
{
|
||||
let volNorm = 0.5//(State.dBHL-10)/ 130;
|
||||
|
||||
Start(1, false, 0, 500, (volNorm*0.8) + 0.2);
|
||||
|
||||
//responseSet(State.dBHL - currentChan.Answer[0]);
|
||||
timer = setTimeout(()=>{playSet(2)}, 300 + Math.random()*1000);
|
||||
}
|
||||
return () => clearTimeout(timer);
|
||||
|
||||
}, [playGet]);
|
||||
|
||||
return {Play:()=>{playSet(1)}, Playing:playGet == 1, Response:playGet == 2 && responseGet };
|
||||
};
|
@ -29,7 +29,8 @@ export const Configure = {
|
||||
},
|
||||
animation:
|
||||
{
|
||||
flash: "flash 1s both"
|
||||
flash: "flash 1s both",
|
||||
pulse: "pulse 3s ease-in-out 0s 1 both"
|
||||
},
|
||||
strokeWidth:
|
||||
{
|
||||
|
68
src/ui.js
68
src/ui.js
@ -19,16 +19,16 @@ export function Button({children, icon, light, disabled, inactive, onClick})
|
||||
return html`
|
||||
<button
|
||||
onClick=${handleClick}
|
||||
class="shadow-sss relative flex rounded-lg text(lg white) font-sans group transition-all ${disabled ? "scale-90 bg-gray-400" : "bg-emerald-500"} ${(inactive||disabled) && "cursor-default"}"
|
||||
class="shadow-sss relative flex items-stretch rounded-lg text(lg white) font-sans group transition-all ${disabled ? "scale-90 bg-gray-400" : "bg-emerald-500"} ${(inactive||disabled) && "cursor-default"}"
|
||||
>
|
||||
<span class="absolute top-0 left-0 w-full h-full rounded-lg bg-black transition-opacity duration-300 opacity-0 ${(!inactive && !disabled) && "group-hover:opacity-50"}"></span>
|
||||
${ FlashGet > 0 && html`<span key=${FlashGet} class="absolute top-0 left-0 w-full h-full rounded-lg bg-green-400 shadow-glow-green-300 animate-flash"></span>` }
|
||||
|
||||
${ icon && html`<span class="block relative p-2 border-r(1 [#00000066])">
|
||||
${ icon && html`<span class="flex items-center block relative px-2 border-r(1 [#00000066])">
|
||||
<span class="absolute top-0 left-0 w-full h-full bg-black rounded(tl-lg bl-lg) opacity-20"></span>
|
||||
<span class="relative">${icon}</span>
|
||||
</span>` }
|
||||
<span class="p-2 relative border-l(1 [#ffffff44])">
|
||||
<span class="flex items-center p-2 relative border-l(1 [#ffffff44])">
|
||||
<span class="absolute shadow-glow-yellow-500 top-0 left-1/2 w-6 h-[6px] bg-white rounded-full translate(-x-1/2 -y-1/2) transition-all duration-500 ${light ? "opacity-100" : "opacity-0 scale-y-0"}"></span>
|
||||
${children}
|
||||
</span>
|
||||
@ -56,7 +56,27 @@ export const Controls =()=>
|
||||
{
|
||||
const [State, Dispatch] = Store.Consumer();
|
||||
|
||||
const {Play} = Tone.useTone();
|
||||
const [pulsedGet, pulsedSet] = React.useState(true);
|
||||
const [playGet, playSet] = React.useState(0);
|
||||
React.useEffect(()=>
|
||||
{
|
||||
/** @type {number|undefined} */
|
||||
let timer;
|
||||
if(playGet == 1)
|
||||
{
|
||||
const volNorm = (State.Stim.Value-State.Stim.Min)/(State.Stim.Max-State.Stim.Min);
|
||||
Tone.Play(!pulsedGet, State.Chan.Value, Store.ColumnMapping[State.Freq.Value][0], (volNorm*0.8) + 0.1);
|
||||
|
||||
if(State.Live.Freq)
|
||||
{
|
||||
const testMark = State.Live.Freq[/** @type {"TestL"|"TestR"}*/(`Test${State.Chan.Value ? "R":"L"}`)];
|
||||
const handler = testMark.Stim <= State.Stim.Value ? ()=>{playSet(2)} : ()=>{playSet(0)}
|
||||
timer = setTimeout(handler, 500 + Math.random()*1000);
|
||||
}
|
||||
}
|
||||
return () => clearTimeout(timer);
|
||||
|
||||
}, [playGet]);
|
||||
|
||||
return html`
|
||||
<div class="flex">
|
||||
@ -77,16 +97,48 @@ export const Controls =()=>
|
||||
<${Button} disabled=${State.Stim.Value == State.Stim.Min} onClick=${()=>Dispatch({Name:"Stim", Data:-1})}>-<//>
|
||||
<${Button} disabled=${State.Stim.Value == State.Stim.Max} onClick=${()=>Dispatch({Name:"Stim", Data:1})}>+<//>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div>Tone</div>
|
||||
<${Button} onClick=${()=>{pulsedSet(true)}} light=${pulsedGet} inactive${pulsedGet}>Pulsed<//>
|
||||
<${Button} onClick=${()=>{pulsedSet(false)}} light=${!pulsedGet} inactive${!pulsedGet}>Continuous<//>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div>Present</div>
|
||||
<svg width="60" height="60" viewBox="0 0 79 79" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle fill="url(#metal)" cx="39" cy="40" r="35"></circle>
|
||||
<circle fill="url(#metal)" cx="39.5" cy="39.5" r="29.5" transform="rotate(180 39.5 39.5)"></circle>
|
||||
<circle fill="url(#metal)" cx="39" cy="40" r="27"></circle>
|
||||
<circle fill="url(#backwall)" cx="39" cy="40" r="25"></circle>
|
||||
<ellipse fill="url(#clearcoat)" cx="39" cy="33" rx="20" ry="16"></ellipse>
|
||||
${playGet == 2 && html`<circle fill="url(#light)" cx="39.5" cy="39.5" r="36" class="animate-pulse"></circle>`}
|
||||
<defs>
|
||||
<linearGradient id="metal" x1="39.5" y1="1" x2="39.5" y2="78" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.0" stop-color="#C4C4C4" stop-opacity="1.0"></stop>
|
||||
<stop offset="1.0" stop-color="#F2F2F2" stop-opacity="1.0"></stop>
|
||||
</linearGradient>
|
||||
<radialGradient id="backwall" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(39 56) rotate(-90) scale(45.5 74.4907)">
|
||||
<stop offset="0.0" stop-color="#AAAAAA" stop-opacity="1.0"></stop>
|
||||
<stop offset="1.0" stop-color="#333333" stop-opacity="1.0"></stop>
|
||||
</radialGradient>
|
||||
<radialGradient id="clearcoat" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(39 38.5) rotate(90) scale(50.5 71.9394)">
|
||||
<stop offset="0.0" stop-color="#ffffff" stop-opacity="0.0"></stop>
|
||||
<stop offset="0.7" stop-color="#ffffff" stop-opacity="1.0"></stop>
|
||||
</radialGradient>
|
||||
<radialGradient id="light" cx="0" cy="0" r="1.0" gradientUnits="userSpaceOnUse" gradientTransform="translate(39.5 39.5) rotate(90) scale(39.5)">
|
||||
<stop offset="0.2" stop-color="#ffffff" stop-opacity="1.0"></stop>
|
||||
<stop offset="0.5" stop-color="#ff8800" stop-opacity="1.6"></stop>
|
||||
<stop offset="0.9" stop-color="#ffffff" stop-opacity="0.0"></stop>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
<${Button} onClick=${()=>playSet(1)} disabled=${playGet==1} icon=${"p!"}>Play<//>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div>Mark</div>
|
||||
<${Button} onClick=${()=>Dispatch({Name:"Mark", Data:true })}>Response<//>
|
||||
<${Button} onClick=${()=>Dispatch({Name:"Mark", Data:false})}>No Response<//>
|
||||
<${Button} onClick=${()=>Dispatch({Name:"Mark", Data:null })} disabled=${State.Live.Mark == undefined}>Clear<//>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div>Play</div>
|
||||
<${Button} onClick=${Play}>continuous<//>
|
||||
</div>
|
||||
`;
|
||||
};
|
||||
|
||||
|
2
store.d.ts
vendored
2
store.d.ts
vendored
@ -49,4 +49,4 @@ declare namespace Store {
|
||||
type DrawChart = { Cross?:DrawPoint, UserL: DrawGroup, UserR: DrawGroup, TestL: DrawGroup, TestR: DrawGroup };
|
||||
|
||||
type Binding = [state:State, dispatch:(inAction:Action)=>void]
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user