UNPKG

lume

Version:

Build next-level interactive web applications.

86 lines (73 loc) 2.31 kB
import html from 'solid-js/html' import {element, numberAttribute, stringAttribute, type ElementAttributes} from '@lume/element' import {autoDefineElements} from '../LumeConfig.js' import {Element3D, type Element3DAttributes} from '../core/Element3D.js' import {Motor} from '../core/Motor.js' import type {PointLight} from '../lights/PointLight.js' import type {Sphere} from '../meshes/Sphere.js' export type FlickeringOrbAttributes = | Element3DAttributes | 'color' | 'intensity' | 'shadowBias' | 'flickerRange' | 'shadowMapWidth' | 'shadowMapHeight' export @element('flickering-orb', autoDefineElements) class FlickeringOrb extends Element3D { @stringAttribute color = 'royalblue' @numberAttribute intensity = 1.3 @numberAttribute shadowBias = 0 @numberAttribute flickerRange = 0.4 @numberAttribute shadowMapWidth = 512 @numberAttribute shadowMapHeight = 512 light?: PointLight sphere?: Sphere override template = () => html` <lume-point-light ref=${(l: PointLight) => (this.light = l)} color=${() => this.color} intensity=${() => this.intensity} shadow-bias=${() => this.shadowBias} shadow-map-width=${() => this.shadowMapWidth} shadow-map-height=${() => this.shadowMapHeight} > <lume-sphere ref=${(s: Sphere) => (this.sphere = s)} has="basic-material" color=${() => this.color} opacity="0.5" mount-point="0.5 0.5 0.5" size="10 10 10" cast-shadow="false" receive-shadow="false" ></lume-sphere> </lume-point-light> ` override connectedCallback() { super.connectedCallback() const initialIntensity = this.intensity const initialOpacity = this.opacity // Prior art: https://www.instructables.com/Realistic-Fire-Effect-with-Arduino-and-LEDs/ const flickerFunction = () => { const flicker = Math.random() - 1 this.light!.intensity = initialIntensity + flicker * this.flickerRange this.sphere!.opacity = initialOpacity + flicker * 0.4 setTimeout(() => Motor.once(flickerFunction), Math.random() * 100) } Motor.once(flickerFunction) } } declare module 'solid-js' { namespace JSX { interface IntrinsicElements { 'flickering-orb': ElementAttributes<FlickeringOrb, FlickeringOrbAttributes> } } } declare global { interface HTMLElementTagNameMap { 'flickering-orb': FlickeringOrb } }