js实现新年快乐夜晚可调节参数好看带声音的烟花效果代码
代码语言:html
所属分类:粒子
代码描述:js实现新年快乐夜晚可调节参数好看带声音的烟花效果代码
代码标签: js 新年 快乐 夜晚 可调节 参数 好看 烟花
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> @import url(https://fonts.googleapis.com/css?family=Archivo+Black); body { display: grid; place-items: center; height: 100vh; padding: 0; margin: 0; background: rgb(255,255,255); background: radial-gradient(circle, rgba(255,255,255,1) 50%, rgba(197,217,224,1) 100%); } .main { text-align: center; border-top: 5px solid; border-bottom: 5px solid; border-image: linear-gradient(150deg, rgba(155,93,229,1) 0%, rgba(241,91,181,1) 20%, rgba(254,228,64,1) 40%, rgba(0,187,249,1) 60%, rgba(0,245,212,1) 80%) 10% 30%; } h1 { font-size: 10rem; font-family: "Archivo Black"; background: rgb(155,93,229); background: linear-gradient(150deg, rgba(155,93,229,1) 0%, rgba(241,91,181,1) 20%, rgba(254,228,64,1) 40%, rgba(0,187,249,1) 60%, rgba(0,245,212,1) 80%); background-size: 20% 20%; background-color: #840b2a; -webkit-background-clip: text; -webkit-text-fill-color: transparent; animation: gradient 5s linear infinite; } h2 { font-family: "Roboto"; letter-spacing: 15px; position: relative; top: -100px; } @keyframes gradient { 0% { background-position: 0% 0%; } 50% { background-position: 50% 50%; } 100% { background-position: 100% 100%; } } * { position: relative; box-sizing: border-box; } html, body { height: 100%; } html { background-color: #000; } body { overflow: hidden; color: rgba(255, 255, 255, 0.5); font-family: "Russo One", arial, sans-serif; line-height: 1.25; letter-spacing: 0.06em; } .hide { opacity: 0; visibility: hidden; } .remove { display: none !important; } .blur { -webkit-filter: blur(12px); filter: blur(12px); } .container { height: 100%; display: -webkit-box; display: flex; -webkit-box-pack: center; justify-content: center; -webkit-box-align: center; align-items: center; } .loading-init { width: 100%; align-self: center; text-align: center; text-transform: uppercase; } .loading-init__header { font-size: 2.2em; } .loading-init__status { margin-top: 1em; font-size: 0.8em; opacity: 0.75; } .stage-container { overflow: hidden; box-sizing: initial; border: 1px solid #222; margin: -1px; } @media (max-width: 840px) { .stage-container { border: none; margin: 0; } } .canvas-container { width: 100%; height: 100%; -webkit-transition: -webkit-filter 0.3s; transition: -webkit-filter 0.3s; transition: filter 0.3s; transition: filter 0.3s, -webkit-filter 0.3s; } .canvas-container canvas { position: absolute; mix-blend-mode: lighten; -webkit-transform: translateZ(0); transform: translateZ(0); } .controls { position: absolute; top: 0; width: 100%; padding-bottom: 50px; display: -webkit-box; display: flex; -webkit-box-pack: justify; justify-content: space-between; -webkit-transition: opacity 0.3s, visibility 0.3s; transition: opacity 0.3s, visibility 0.3s; } @media (min-width: 840px) { .controls { visibility: visible; } .controls.hide:hover { opacity: 1; } } .menu { position: absolute; top: 0; bottom: 0; left: 0; right: 0; background-color: rgba(0, 0, 0, 0.42); -webkit-transition: opacity 0.3s, visibility 0.3s; transition: opacity 0.3s, visibility 0.3s; } .menu__inner-wrap { display: -webkit-box; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; flex-direction: column; -webkit-box-pack: center; justify-content: center; -webkit-box-align: center; align-items: center; position: absolute; top: 0; bottom: 0; left: 0; right: 0; -webkit-transition: opacity 0.3s; transition: opacity 0.3s; } .menu__header { margin-top: auto; margin-bottom: 8px; padding-top: 16px; font-size: 2em; text-transform: uppercase; } .menu__subheader { margin-bottom: auto; padding-bottom: 12px; font-size: 0.86em; opacity: 0.8; } .menu form { width: 100%; max-width: 400px; padding: 0 10px; overflow: auto; -webkit-overflow-scrolling: touch; } .menu .form-option { display: -webkit-box; display: flex; -webkit-box-align: center; align-items: center; margin: 16px 0; -webkit-transition: opacity 0.3s; transition: opacity 0.3s; } .menu .form-option label { display: block; width: 50%; padding-right: 12px; text-align: right; text-transform: uppercase; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .menu .form-option--select select { display: block; width: 50%; height: 30px; font-size: 1rem; font-family: "Russo One", arial, sans-serif; color: rgba(255, 255, 255, 0.5); letter-spacing: 0.06em; background-color: transparent; border: 1px solid rgba(255, 255, 255, 0.5); } .menu .form-option--select select option { background-color: black; } .menu .form-option--checkbox input { display: block; width: 26px; height: 26px; margin: 0; opacity: 0.5; } @media (max-width: 840px) { .menu .form-option select, .menu .form-option input { outline: none; } } .close-menu-btn { position: absolute; top: 0; right: 0; } .btn { opacity: 0.16; width: 50px; height: 50px; display: -webkit-box; display: flex; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; cursor: default; -webkit-transition: opacity 0.3s; transition: opacity 0.3s; } .btn--bright { opacity: 0.5; } @media (min-width: 840px) { .btn:hover { opacity: 0.32; } .btn--bright:hover { opacity: 0.75; } } .btn svg { display: block; margin: auto; } .credits { margin-top: auto; margin-bottom: 10px; padding-top: 6px; font-size: 0.8em; opacity: 0.75; } .credits a { color: rgba(255, 255, 255, 0.5); text-decoration: none; } .credits a:hover, .credits a:active { color: rgba(255, 255, 255, 0.75); text-decoration: underline; } .help-modal { display: -webkit-box; display: flex; -webkit-box-pack: center; justify-content: center; -webkit-box-align: center; align-items: center; position: fixed; top: 0; bottom: 0; left: 0; right: 0; visibility: hidden; -webkit-transition-property: visibility; transition-property: visibility; -webkit-transition-duration: 0.25s; transition-duration: 0.25s; } .help-modal__overlay { position: absolute; top: 0; bottom: 0; left: 0; right: 0; opacity: 0; -webkit-transition-property: opacity; transition-property: opacity; -webkit-transition-timing-function: ease-in; transition-timing-function: ease-in; -webkit-transition-duration: 0.25s; transition-duration: 0.25s; } .help-modal__dialog { display: -webkit-box; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; flex-direction: column; -webkit-box-align: center; align-items: center; max-width: 400px; max-height: calc(100vh - 100px); margin: 10px; padding: 20px; border-radius: 0.3em; background-color: rgba(0, 0, 0, 0.4); opacity: 0; -webkit-transform: scale(0.9, 0.9); transform: scale(0.9, 0.9); -webkit-transition-property: opacity, -webkit-transform; transition-property: opacity, -webkit-transform; transition-property: opacity, transform; transition-property: opacity, transform, -webkit-transform; -webkit-transition-timing-function: ease-in; transition-timing-function: ease-in; -webkit-transition-duration: 0.25s; transition-duration: 0.25s; } @media (min-width: 840px) { .help-modal__dialog { font-size: 1.25rem; max-width: 500px; } } .help-modal__header { font-size: 1.75em; text-transform: uppercase; text-align: center; } .help-modal__body { overflow-y: auto; -webkit-overflow-scrolling: touch; margin: 1em 0; padding: 1em 0; border-top: 1px solid rgba(255, 255, 255, 0.25); border-bottom: 1px solid rgba(255, 255, 255, 0.25); line-height: 1.5; color: rgba(255, 255, 255, 0.75); } .help-modal__close-btn { flex-shrink: 0; outline: none; border: none; border-radius: 2px; padding: 0.25em 0.75em; margin-top: 0.36em; font-family: "Russo One", arial, sans-serif; font-size: 1em; color: rgba(255, 255, 255, 0.5); text-transform: uppercase; letter-spacing: 0.06em; background-color: rgba(255, 255, 255, 0.25); -webkit-transition: color 0.3s, background-color 0.3s; transition: color 0.3s, background-color 0.3s; } .help-modal__close-btn:hover, .help-modal__close-btn:active, .help-modal__close-btn:focus { color: #FFF; background-color: #09F; } .help-modal.active { visibility: visible; -webkit-transition-duration: 0.4s; transition-duration: 0.4s; } .help-modal.active .help-modal__overlay { opacity: 1; -webkit-transition-timing-function: ease-out; transition-timing-function: ease-out; -webkit-transition-duration: 0.4s; transition-duration: 0.4s; } .help-modal.active .help-modal__dialog { opacity: 1; -webkit-transform: scale(1, 1); transform: scale(1, 1); -webkit-transition-timing-function: ease-out; transition-timing-function: ease-out; -webkit-transition-duration: 0.4s; transition-duration: 0.4s; } </style> </head> <body> <div style="height: 0; width: 0; position: absolute; visibility: hidden;"> <svg xmlns="http://www.w3.org/2000/svg"> <symbol id="icon-play" viewBox="0 0 24 24"> <path d="M8 5v14l11-7z"/> </symbol> <symbol id="icon-pause" viewBox="0 0 24 24"> <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/> </symbol> <symbol id="icon-close" viewBox="0 0 24 24"> <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/> </symbol> <symbol id="icon-settings" viewBox="0 0 24 24"> <path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/> </symbol> <symbol id="icon-sound-on" viewBox="0 0 24 24"> <path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/> </symbol> <symbol id="icon-sound-off" viewBox="0 0 24 24"> <path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"/> </symbol> </svg> </div> <!-- App --> <div class="container"> <div class="loading-init"> <div class="loading-init__header">By Zure</div> <div class="loading-init__status">KN x TP</div> </div> <div class="stage-container remove"> <div class="canvas-container"> <canvas id="trails-canvas"></canvas> <canvas id="main-canvas"></canvas> </div> <div class="controls"> <div class="btn pause-btn"> <svg fill="white" width="24" height="24"><use href="#icon-pause" xlink:href="#icon-pause"></use></svg> </div> <div class="btn sound-btn"> <svg fill="white" width="24" height="24"><use href="#icon-sound-off" xlink:href="#icon-sound-off"></use></svg> </div> <div class="btn settings-btn"> <svg fill="white" width="24" height="24"><use href="#icon-settings" xlink:href="#icon-settings"></use></svg> </div> </div> <div class="menu hide"> <div class="menu__inner-wrap"> <div class="btn btn--bright close-menu-btn"> <svg fill="white" width="24" height="24"><use href="#icon-close" xlink:href="#icon-close"></use></svg> </div> <div class="menu__header">Settings</div> <div class="menu__subheader">For more info, click any label.</div> <form> <div class="form-option form-option--select"> <label class="shell-type-label">Shell Type</label> <select class="shell-type"></select> </div> <div class="form-option form-option--select"> <label class="shell-size-label">Shell Size</label> <select class="shell-size"></select> </div> <div class="form-option form-option--select"> <label class="quality-ui-label">Quality</label> <select class="quality-ui"></select> </div> <div class="form-option form-option--select"> <label class="sky-lighting-label">Sky Lighting</label> <select class="sky-lighting"></select> </div> <div class="form-option form-option--select"> <label class="scaleFactor-label">Scale</label> <select class="scaleFactor"></select> </div> <div class="form-option form-option--checkbox"> <label class="auto-launch-label">Auto Fire</label> <input class="auto-launch" type="checkbox" /> </div> <div class="form-option form-option--checkbox form-option--finale-mode"> <label class="finale-mode-label">Finale Mode</label> <input class="finale-mode" type="checkbox" /> </div> <div class="form-option form-option--checkbox"> <label class="hide-controls-label">Hide Controls</label> <input class="hide-controls" type="checkbox" /> </div> <div class="form-option form-option--checkbox form-option--fullscreen"> <label class="fullscreen-label">Fullscreen</label> <input class="fullscreen" type="checkbox" /> </div> <div class="form-option form-option--checkbox"> <label class="long-exposure-label">Open Shutter</label> <input class="long-exposure" type="checkbox" /> </div> </form> <div class="credits"> Passionately built Sayn Achhava. </div> </div> </div> </div> <div class="help-modal"> <div class="help-modal__overlay"></div> <div class="help-modal__dialog"> <div class="help-modal__header"></div> <div class="help-modal__body"></div> <button type="button" class="help-modal__close-btn">Close</button> </div> </div> </div> <div class="main"> <h1>2024</h1> <h2>Happy New Year</h2> <p>点击开始</p> </div> <!-- partial --> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/fscreen.1.0.1.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/Stage.0.1.4.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/MyMath.js"></script> <script > 'use strict'; console.clear(); function fireapp(){ const IS_MOBILE = window.innerWidth <= 640; const IS_DESKTOP = window.innerWidth > 800; const IS_HEADER = IS_DESKTOP && window.innerHeight < 300; // Detect high end devices. This will be a moving target. const IS_HIGH_END_DEVICE = (() => { const hwConcurrency = navigator.hardwareConcurrency; if (!hwConcurrency) { return false; } // Large screens indicate a full size computer, which often have hyper threading these days. // So a quad core desktop machine has 8 cores. We'll place a higher min threshold there. const minCount = window.innerWidth <= 1024 ? 4 : 8; return hwConcurrency >= minCount; })(); // Prevent canvases from getting too large on ridiculous screen sizes. // 8K - can restrict this if needed const MAX_WIDTH = 7680; const MAX_HEIGHT = 4320; const GRAVITY = 0.9; // Acceleration in px/s let simSpeed = 1; function getDefaultScaleFactor() { if (IS_MOBILE) return 0.9; if (IS_HEADER) return 0.75; return 1; } // Width/height values that take scale into account. // USE THESE FOR DRAWING POSITIONS let stageW, stageH; // All quality globals will be overwritten and updated via `configDidUpdate`. let quality = 1; let isLowQuality = false; let isNormalQuality = true; let isHighQuality = false; const QUALITY_LOW = 1; const QUALITY_NORMAL = 2; const QUALITY_HIGH = 3; const SKY_LIGHT_NONE = 0; const SKY_LIGHT_DIM = 1; const SKY_LIGHT_NORMAL = 2; const COLOR = { Red: '#ff0043', Green: '#14fc56', Blue: '#1e7fff', Purple: '#e60aff', Gold: '#ffbf36', White: '#ffffff' }; // Special invisible color (not rendered, and therefore not in COLOR map) const INVISIBLE = '_INVISIBLE_'; const PI_2 = Math.PI * 2; const PI_HALF = Math.PI * 0.5; // Stage.disableHighDPI = true; const trailsStage = new Stage('trails-canvas'); const mainStage = new Stage('main-canvas'); const stages = [ trailsStage, mainStage ]; // Fullscreen helpers, using Fscreen for prefixes. function fullscreenEnabled() { return fscreen.fullscreenEnabled; } // Note that fullscreen state is synced to store, and the store should be the source // of truth for whether the app is in fullscreen mode or not. function isFullscreen() { return !!fscreen.fullscreenElement; } // Attempt to toggle fullscreen mode. function toggleFullscreen() { if (fullscreenEnabled()) { if (isFullscreen()) { fscreen.exitFullscreen(); } else { fscreen.requestFullscreen(document.documentElement); } } } // Sync fullscreen changes with store. An event listener is necessary because the user can // toggle fullscreen mode directly through the browser, and we want to react to that. fscreen.addEventListener('fullscreenchange', () => { store.setState({ fullscreen: isFullscreen() }); }); // Simple state container; the source of truth. const store = { _listeners: new Set(), _dispatch(prevState) { this._listeners.forEach(listener => listener(this.state, prevState)) }, state: { // will be unpaused in init() paused: true, soundEnabled: false, menuOpen: false, openHelpTopic: null, fullscreen: isFullscreen(), // Note that config values used for <select>s must be strings, unless manually converting values to strings // at render time, and parsing on change. config: { quality: String(IS_HIGH_END_DEVICE ? QUALITY_HIGH : QUALITY_NORMAL), // will be mirrored to a global variable named `quality` in `configDidUpdate`, for perf. shell: 'Random', size: IS_DESKTOP ? '3' // Desktop default : IS_HEADER ? '1.2' // Profile header default (doesn't need to be an int) : '2', // Mobile default autoLaunch: true, finale: false, skyLighting: SKY_LIGHT_NORMAL + '', hideControls: IS_HEADER, longExposure: false, scaleFactor: getDefaultScaleFactor() } }, setState(nextState) { const prevState = this.state; this.state = Object.assign({}, this.state, nextState); this._dispatch(prevState); this.persist(); }, subscribe(listener) { this._listeners.add(listener); return () => this._listeners.remove(listener); }, // Load / persist select state to localStorage // Mutates state because `store.load()` should only be called once immediately after store is created, before any subscriptions. load() { const serializedData = localStorage.getItem('cm_fireworks_data'); if (serializedData) { const { schemaVersion, data } = JSON.parse(serializedData); const config = this.state.config; switch(schemaVersion) { case '1.1': config.quality = data.quality; config.size = data.size; config.skyLighting = data.skyLighting; break; case '1.2': config.quality = data.quality; config.size = data.size; config.skyLighting = data.skyLighting; config.scaleFactor = data.scaleFactor; break; default: throw new Error('version switch should be exhaustive'); } console.log(`Loaded config (schema version ${schemaVersion})`); } // Deprecated data format. Checked with care (it's not namespaced). else if (localStorage.getItem('schemaVersion') === '1') { let size; // Attempt to parse data, ignoring if there is an error. try { const sizeRaw = localStorage.getItem('configSize'); size = typeof sizeRaw === 'string' && JSON.parse(sizeRaw); } catch(e) { console.log('Recovered from error parsing saved config:'); console.error(e); return; } // Only restore validated values const sizeInt = parseInt(size, 10); if (sizeInt >= 0 && sizeInt <= 4) { this.state.config.size = String(sizeInt); } } }, persist() { const config = this.state.config; localStorage.setItem('cm_fireworks_data', JSON.stringify({ schemaVersion: '1.2', data: { quality: config.quality, size: config.size, skyLighting: config.skyLighting, scaleFactor: config.scaleFactor } })); } }; if (!IS_HEADER) { store.load(); } // Actions // --------- function togglePause(toggle) { const paused = store.state.paused; let newValue; if (typeof toggle === 'boolean') { newValue = toggle; } else { newValue = !paused; } if (paused !== newValue) { store.setState({ paused: newValue }); } } function toggleSound(toggle) { if (typeof toggle === 'boolean') { store.setState({ soundEnabled: toggle }); } else { store.setState({ soundEnabled: !store.state.soundEnabled }); } } function toggleMenu(toggle) { if (typeof toggle === 'boolean') { store.setState({ menuOpen: toggle }); } else { store.setState({ menuOpen: !store.state.menuOpen }); } } function updateConfig(nextConfig) { nextConfig = nextConfig || getConfigFromDOM(); store.setState({ config: Object.assign({}, store.state.config, nextConfig) }); configDidUpdate(); } // Map config to various properties & apply side effects function configDidUpdate() { const config = store.state.config; quality = qualitySelector(); isLowQuality = quality === QUALITY_LOW; isNormalQuality = quality === QUALITY_NORMAL; isHighQuality = quality === QUALITY_HIGH; if (skyLightingSelector() === SKY_LIGHT_NONE) { appNodes.canvasContainer.style.backgroundColor = '#000'; } Spark.drawWidth = quality === QUALITY_HIGH ? 0.75 : 1; } // Selectors // ----------- const isRunning = (state=store.state) => !state.paused && !state.menuOpen; // Whether user has enabled sound. const soundEnabledSelector = (state=store.state) => state.soundEnabled; // Whether any sounds are allowed, taking into account multiple factors. const canPlaySoundSelector = (state=store.state) => isRunning(state) && soundEnabledSelector(state); // Convert quality to number. const qualitySelector = () => +store.state.config.quality; const shellNameSelector = () => store.state.config.shell; // Convert shell size to number. const shellSizeSelector = () => +store.state.config.size; const finaleSelector = () => store.state.config.finale; const skyLightingSelector = () => +store.state.config.skyLighting; const scaleFactorSelector = () => store.state.config.scaleFactor; // Help Content const helpContent = { shellType: { header: 'Shell Type', body: 'The type of firework that will be launched. Select "Random" for a nice assortment!' }, shellSize: { header: 'Shell Size', body: 'The size of the fireworks. Modeled after real firework shell sizes, larger shells have bigger bursts with more stars, and sometimes more complex effects. However, larger shells also require more processing power and may cause lag.' }, quality: { header: 'Quality', body: 'Overall graphics quality. If the animation is not running smoothly, try lowering the quality. High quality greatly increases the amount of sparks rendered and may cause lag.' }, skyLighting: { header: 'Sky Lighting', body: 'Illuminates the background as fireworks explode. If the background looks too bright on your screen, try setting it to "Dim" or "None".' }, scaleFactor: { header: 'Scale', body: 'Allows scaling the size of all fireworks, essentially moving you closer or farther away. For larger shell sizes, it can be convenient to decrease the scale a bit, especially on phones or tablets.' }, autoLaunch: { header: 'Auto Fire', body: 'Launches sequences of fireworks automatically. Sit back and enjoy the show, or disable to have full control.' }, finaleMode: { header: 'Finale Mode', body: 'Launches intense bursts of fireworks. May cause lag. Requires "Auto Fire" to be enabled.' }, hideControls: { header: 'Hide Controls', body: 'Hides the translucent controls along the top of the screen. Useful for screenshots, or just a more seamless experience. While hidden, you can still tap the top-right corner to re-open this menu.' }, fullscreen: { header: 'Fullscreen', body: 'Toggles fullscreen mode.' }, longExposure: { header: 'Open Shutter', body: 'Experimental effect that preserves long streaks of light, similar to leaving a camera shutter open.' } }; const nodeKeyToHelpKey = { shellTypeLabel: 'shellType', shellSizeLabel: 'shellSize', qualityLabel: 'quality', skyLightingLabel: 'skyLighting', scaleFactorLabel: 'scaleFactor', autoLaunchLabel: 'autoLaunch', finaleModeLabel: 'finaleMode', hideControlsLabel: 'hideControls', fullscreenLabel: 'fullscreen', longExposureLabel: 'longExposure' }; // Render app UI / keep in sync with state const appNodes = { stageContainer: '.stage-container', canvasContainer: '.canvas-container', controls: '.controls', menu: '.menu', menuInnerWrap: '.menu__inner-wrap', pauseBtn: '.pause-btn', pauseBtnSVG: '.pause-btn use', soundBtn: '.sound-btn', soundBtnSVG: '.sound-btn use', shellType: '.shell-type', shellTypeLabel: '.shell-type-label', shellSize: '.shell-size', shellSizeLabel: '.shell-size-label', quality: '.quality-ui', qualityLabel: '.quality-ui-label', skyLighting: '.sky-lighting', skyLightingLabel: '.sky-lighting-label', scaleFactor: '.scaleFactor', scaleFactorLabel: '.scaleFactor-label', autoLaunch: '.auto-launch', autoLaunchLabel: '.auto-launch-label', finaleModeFormOption: '.form-option--finale-mode', finaleMode: '.finale-mode', finaleModeLabel: '.finale-mode-label', hideControls: '.hide-controls', hideControlsLabel: .........完整代码请登录后点击上方下载按钮下载查看
网友评论2