JSFiddle - React, Tailwind, and code Playground
by Josh Pullen
CSS
body {
font-family: sans-serif;
}
.PhasorBox {
height: 200px;
width: 200px;
}
.WaveBox {
width: 400px;
height: 200px;
}
.columns {
display: grid;
grid-template-columns: 2fr 1fr;
grid-template-rows: auto;
grid-gap: 16px;
}
.column {
display: flex;
flex-direction: column;
align-items: flex-end;
}
.diagram {
position: relative;
border: 1px solid #ddd;
box-shadow: 0 4px 8px #eee;
border-radius: 12px;
padding: 16px;
margin-bottom: 16px;
display: flex;
justify-content: center;
}
.labels {
position: absolute;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: flex-end;
padding: 4px;
}
.label {
font-size: 14px;
font-family: monospace;
color: white;
padding: 2px 8px;
min-width: 6px;
border-radius: 999px;
display: flex;
align-items: center;
justify-content: center;
margin-left: 4px;
cursor: pointer;
user-select: none;
}
.label-hidden {
opacity: 0.4;
}
JavaScript
import { html, render, useState, useEffect, useContext, createContext } from "https://unpkg.com/htm/preact/standalone.module.js";
const WaveBoxContext = createContext({ omega: 0, time: 0 });
function ACPhasorApplet() {
const [time, timeVel, setTime] = useProgressValue(0, 0);
const [omega, setOmega] = useState(250); // rad/s
const [R, setR] = useState(250);
const [L, setL] = useState(500);
const [C, setC] = useState(20);
const phi = Math.atan((omega*L/10**3 - 10**6/(omega*C)) / R);
const angle = omega * time - phi;
const V_0 = 250;
const I = V_0 / Math.sqrt(
R**2 +
(omega*L/10**3 - 10**6/(omega*C))**2
);
const V_R = I*R;
const V_L = I*omega*L/10**3;
const V_C = omega === 0 ? 0 : I**2 * 10**6/(omega*C);
const vScale = 0.2;
const iScale = vScale * 100;
console.log(I);
const [showI, setShowI] = useState(true);
const [showR, setShowR] = useState(true);
const [showL, setShowL] = useState(false);
const [showC, setShowC] = useState(false);
return html`
<div class="columns">
<div class="column">
<div class="diagram">
<${WaveBox} time=${time} omega=${omega} phi=${phi}>
${showL && html`<${Wave} dirDiff=${Math.PI / 2} mag=${V_L*vScale} color="#2fcc5b" />`}
${showR && html`<${Wave} dirDiff=${0} mag=${V_R*vScale} color="#0e8a30" />`}
${showC && html`<${Wave} dirDiff=${-Math.PI / 2} mag=${V_C*vScale} color="#043612" />`}
${showI && html`<${Wave} dirDiff=${0} mag=${I*iScale} color="#7d2b8b" />`}
<//>
</div>
<div style=${{ width: 432, display: "flex", alignItems: "center" }}>
<button
onClick=${() => {
if (timeVel === 0) {
setTime(time, 0.1 / 5);
} else {
setTime(time, 0);
}
}}
>
${timeVel === 0 ? "Play" : "Pause"}
</button>
<label style=${{ display:...