Skip to content

Commit a2d042c

Browse files
committed
feat: add RGB LED
close #100
1 parent 9090d58 commit a2d042c

File tree

4 files changed

+206
-0
lines changed

4 files changed

+206
-0
lines changed

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,4 @@ export { MPU6050Element } from './mpu6050-element';
4242
export { ESP32DevkitV1Element } from './esp32-devkit-v1-element';
4343
export { KY040Element } from './ky-040-element';
4444
export { PhotoresistorSensorElement } from './photoresistor-sensor-element';
45+
export { RGBLedElement } from './rgb-led-element';

src/react-types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import { MPU6050Element } from './mpu6050-element';
4141
import { ESP32DevkitV1Element } from './esp32-devkit-v1-element';
4242
import { KY040Element } from './ky-040-element';
4343
import { PhotoresistorSensorElement } from './photoresistor-sensor-element';
44+
import { RGBLedElement } from './rgb-led-element';
4445

4546
type WokwiElement<T> = Partial<T> & React.ClassAttributes<T>;
4647

@@ -87,6 +88,7 @@ declare global {
8788
'wokwi-esp32-devkit-v1': WokwiElement<ESP32DevkitV1Element>;
8889
'wokwi-ky-040': WokwiElement<KY040Element>;
8990
'wokwi-photoresistor-sensor': WokwiElement<PhotoresistorSensorElement>;
91+
'wokwi-rgb-led': WokwiElement<RGBLedElement>;
9092
}
9193
}
9294
}

src/rgb-led-element.stories.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { html } from 'lit-html';
2+
import './rgb-led-element';
3+
4+
export default {
5+
title: 'RGB Led',
6+
component: 'wokwi-rgb-led',
7+
argTypes: {
8+
ledRed: { control: { type: 'range', min: 0, max: 1, step: 0.01 } },
9+
ledGreen: { control: { type: 'range', min: 0, max: 1, step: 0.01 } },
10+
ledBlue: { control: { type: 'range', min: 0, max: 1, step: 0.01 } },
11+
background: { control: { type: 'color' } },
12+
},
13+
args: {
14+
ledRed: 0,
15+
ledGreen: 0,
16+
ledBlue: 0,
17+
background: '',
18+
},
19+
};
20+
21+
const Template = ({ ledRed, ledGreen, ledBlue, background }) =>
22+
html`<div style="background:${background}">
23+
<wokwi-rgb-led .ledRed=${ledRed} .ledGreen=${ledGreen} .ledBlue=${ledBlue}></wokwi-rgb-led>
24+
</div>`;
25+
26+
export const Default = Template.bind({});
27+
28+
export const DarkMode = Template.bind({});
29+
DarkMode.args = { background: '#333' };
30+
31+
export const Red = Template.bind({});
32+
Red.args = { ledRed: 1 };
33+
34+
export const Green = Template.bind({});
35+
Green.args = { ledGreen: 1 };
36+
37+
export const Blue = Template.bind({});
38+
Blue.args = { ledBlue: 1 };
39+
40+
export const Yellow = Template.bind({});
41+
Yellow.args = { ledRed: 1, ledGreen: 1, ledBlue: 0 };
42+
43+
export const White = Template.bind({});
44+
White.args = { ledRed: 1, ledGreen: 1, ledBlue: 1 };
45+
46+
export const Cyan = Template.bind({});
47+
Cyan.args = { ledRed: 0, ledGreen: 1, ledBlue: 1 };

src/rgb-led-element.ts

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import { customElement, html, LitElement, property } from 'lit-element';
2+
import { ElementPin } from '.';
3+
4+
@customElement('wokwi-rgb-led')
5+
export class RGBLedElement extends LitElement {
6+
@property() ledRed = 0;
7+
@property() ledGreen = 0;
8+
@property() ledBlue = 0;
9+
10+
readonly pinInfo: ElementPin[] = [
11+
{ name: 'R', x: 8.5, y: 44, signals: [] },
12+
{ name: 'COM', x: 17.5, y: 54, signals: [] },
13+
{ name: 'G', x: 26.4, y: 48, signals: [] },
14+
{ name: 'B', x: 35.7, y: 43, signals: [] },
15+
];
16+
17+
render() {
18+
const { ledRed, ledGreen, ledBlue } = this;
19+
const brightness = Math.max(ledRed, ledGreen, ledBlue);
20+
const opacity = brightness ? 0.2 + brightness * 0.6 : 0;
21+
22+
return html`
23+
<?xml version="1.0" encoding="UTF-8"?>
24+
<svg
25+
width="42.129"
26+
height="72.582"
27+
version="1.2"
28+
viewBox="-17 -10 37.3425 57.5115"
29+
xmlns="http://www.w3.org/2000/svg"
30+
>
31+
<!-- LED Legs -->
32+
<g fill="none" stroke="#9D9999" stroke-linecap="round" stroke-width=".89px">
33+
<path d="m3.3863 15.334 3.0611 13.971" />
34+
<path d="m7.2753 13.972 5.9987 4.0518 1.1777 6.5679" stroke-linejoin="round" />
35+
<path d="m-4.3793 14.184-5.0755 5.6592-0.10206 6.1694" stroke-linejoin="round" />
36+
<path d="m-1.1952 15.607-0.33725 19.49" />
37+
</g>
38+
39+
<!-- LED Body -->
40+
<path
41+
d="m8.3435 5.65v-5.9126c0-3.9132-3.168-7.0884-7.0855-7.0884-3.9125 0-7.0877 3.1694-7.0877 7.0884v13.649c1.4738 1.651 4.0968 2.7526 7.0877 2.7526 4.6195 0 8.3686-2.6179 8.3686-5.8594v-1.5235c-7.4e-4 -1.1426-0.47444-2.2039-1.283-3.1061z"
42+
opacity=".3"
43+
/>
44+
<path
45+
d="m8.3435 5.65v-5.9126c0-3.9132-3.168-7.0884-7.0855-7.0884-3.9125 0-7.0877 3.1694-7.0877 7.0884v13.649c1.4738 1.651 4.0968 2.7526 7.0877 2.7526 4.6195 0 8.3686-2.6179 8.3686-5.8594v-1.5235c-7.4e-4 -1.1426-0.47444-2.2039-1.283-3.1061z"
46+
fill="#e6e6e6"
47+
opacity=".5"
48+
/>
49+
<path
50+
d="m8.3435 5.65v3.1054c0 2.7389-3.1658 4.9651-7.0855 4.9651-3.9125 2e-5 -7.0877-2.219-7.0877-4.9651v4.6296c1.4738 1.6517 4.0968 2.7526 7.0877 2.7526 4.6195 0 8.3686-2.6179 8.3686-5.8586l-4e-5 -1.5235c-7e-4 -1.1419-0.4744-2.2032-1.283-3.1054z"
51+
fill="#d1d1d1"
52+
opacity=".9"
53+
/>
54+
<g transform="translate(-5.8295 -7.351)">
55+
<path
56+
d="m14.173 13.001v3.1054c0 2.7389-3.1658 4.9651-7.0855 4.9651-3.9125 2e-5 -7.0877-2.219-7.0877-4.9651v4.6296c1.4738 1.6517 4.0968 2.7526 7.0877 2.7526 4.6195 0 8.3686-2.6179 8.3686-5.8586l-4e-5 -1.5235c-7e-4 -1.1419-0.4744-2.2032-1.283-3.1054z"
57+
opacity=".7"
58+
/>
59+
<path
60+
d="m14.173 13.001v3.1054c0 2.7389-3.1658 4.9651-7.0855 4.9651-3.9125 2e-5 -7.0877-2.219-7.0877-4.9651v3.1054c1.4738 1.6502 4.0968 2.7526 7.0877 2.7526 4.6195 0 8.3686-2.6179 8.3686-5.8586-7.4e-4 -1.1412-0.47444-2.2025-1.283-3.1047z"
61+
opacity=".25"
62+
/>
63+
<ellipse cx="7.0877" cy="16.106" rx="7.087" ry="4.9608" opacity=".25" />
64+
</g>
65+
<polygon
66+
transform="translate(-5.8295 -7.351)"
67+
points="3.1961 13.095 6.0156 13.095 10.012 8.8049 3.407 8.8049 2.2032 9.648 2.2032 16.107 3.1961 16.107"
68+
fill="#666"
69+
/>
70+
<polygon
71+
transform="translate(-5.8295 -7.351)"
72+
points="11.06 13.095 11.06 16.107 11.974 16.107 11.974 8.5241 10.778 8.5241 11.215 9.0338 7.4117 13.095"
73+
fill="#666"
74+
/>
75+
<path
76+
d="m8.3435 5.65v-5.9126c0-3.9132-3.168-7.0884-7.0855-7.0884-3.9125 0-7.0877 3.1694-7.0877 7.0884v13.649c1.4738 1.651 4.0968 2.7526 7.0877 2.7526 4.6195 0 8.3686-2.6179 8.3686-5.8594v-1.5235c-7.4e-4 -1.1426-0.47444-2.2039-1.283-3.1061z"
77+
fill="white"
78+
opacity=".65"
79+
/>
80+
<g transform="translate(-5.8295 -7.351)" fill="#fff">
81+
<path
82+
d="m10.388 3.7541 1.4364-0.2736c-0.84168-1.1318-2.0822-1.9577-3.5417-2.2385l0.25416 1.0807c0.76388 0.27072 1.4068 0.78048 1.8511 1.4314z"
83+
opacity=".5"
84+
/>
85+
<path
86+
d="m0.76824 19.926v1.5199c0.64872 0.5292 1.4335 0.97632 2.3076 1.3169v-1.525c-0.8784-0.33624-1.6567-0.78194-2.3076-1.3118z"
87+
opacity=".5"
88+
/>
89+
<path
90+
d="m11.073 20.21c-0.2556 0.1224-0.52992 0.22968-0.80568 0.32976-0.05832 0.01944-0.11736 0.04032-0.17784 0.05832-0.56376 0.17928-1.1614 0.31896-1.795 0.39456-0.07488 0.0094-0.1512 0.01872-0.22464 0.01944-0.3204 0.03024-0.64368 0.05832-0.97056 0.05832-0.14832 0-0.30744-0.01512-0.4716-0.02376-1.2002-0.05688-2.3306-0.31464-3.2976-0.73944l-2e-5 -8.3895v-4.8254c0-1.471 0.84816-2.7295 2.0736-3.3494l-0.02232-0.05328-1.2478-1.512c-1.6697 1.003-2.79 2.8224-2.79 4.9118v11.905c-0.04968-0.04968-0.30816-0.30888-0.48024-0.52992l-0.30744 0.6876c1.4011 1.4818 3.8088 2.4617 6.5426 2.4617 1.6798 0 3.2371-0.37368 4.5115-1.0022l-0.52704-0.40896-0.01006 0.0072z"
91+
opacity=".5"
92+
/>
93+
</g>
94+
95+
<filter id="ledFilter" x="-0.8" y="-0.8" height="5.2" width="5.8">
96+
<feGaussianBlur stdDeviation="4" />
97+
</filter>
98+
<filter id="ledFilterRed" x="-0.8" y="-0.8" height="5.2" width="5.8">
99+
<feGaussianBlur stdDeviation="${ledRed * 3}" />
100+
</filter>
101+
<filter id="ledFilterGreen" x="-0.8" y="-0.8" height="5.2" width="5.8">
102+
<feGaussianBlur stdDeviation="${ledGreen * 3}" />
103+
</filter>
104+
<filter id="ledFilterBlue" x="-0.8" y="-0.8" height="5.2" width="5.8">
105+
<feGaussianBlur stdDeviation="${ledBlue * 3}" />
106+
</filter>
107+
108+
<circle
109+
cx="1.7"
110+
cy="3"
111+
r="${ledRed * 5 + 2}"
112+
fill="rgb(255, 0, 0)"
113+
opacity="${Math.min(ledRed * 20, 0.3)}"
114+
filter="url(#ledFilterRed)"
115+
/>
116+
<circle
117+
cx="2.7"
118+
cy="5"
119+
r="${ledGreen * 5 + 2}"
120+
fill="rgb(0, 255, 0)"
121+
opacity="${Math.min(ledGreen * 20, 0.3)}"
122+
filter="url(#ledFilterGreen)"
123+
/>
124+
<circle
125+
cx="0.7"
126+
cy="5"
127+
r="${ledBlue * 5 + 2}"
128+
fill="rgb(1,85,253)"
129+
opacity="${Math.min(ledBlue * 20, 0.3)}"
130+
filter="url(#ledFilterBlue)"
131+
/>
132+
133+
<circle
134+
cx="1.7"
135+
cy="4"
136+
r="10"
137+
fill="rgb(${ledRed * 255}, ${ledGreen * 255 + ledBlue * 90}, ${ledBlue * 255})"
138+
filter="url(#ledFilter)"
139+
opacity="${opacity}"
140+
/>
141+
142+
<!-- Grey hollow around the LED -->
143+
<circle
144+
cx="1.7"
145+
cy="4"
146+
r="13"
147+
stroke="#666"
148+
stroke-width="1"
149+
fill="none"
150+
filter="url(#ledFilter)"
151+
opacity="${opacity}"
152+
/>
153+
</svg>
154+
`;
155+
}
156+
}

0 commit comments

Comments
 (0)