UNPKG

mandelbrot-set

Version:

Web components and a web worker for painting Julia and Mandelbrot sets on a web page.

190 lines (171 loc) 5.56 kB
import { initializeElement, ensureUniqueFieldIds } from './element-utils.js' const template = document.createElement('template') template.innerHTML = `<style> [data-id=palette] > label { min-width: 5em; display: inline-block; } </style> <form> <fieldset data-id="palette"> <legend>Colour palette</legend> <input data-id="palette-grayscale" type="radio" name="palette" checked> <label>Grayscale</label> <input data-id="palette-jewels" type="radio" name="palette"> <label>Jewels</label> <input data-id="palette-fiery" type="radio" name="palette"> <label>Fiery</label> <input data-id="palette-rainbow" type="radio" name="palette"> <label>Rainbow</label> <input data-id="palette-sharp" type="radio" name="palette"> <label>Sharp</label> <br> <input data-id="palette-onion" type="radio" name="palette"> <label>Onion</label> <input data-id="palette-ocean" type="radio" name="palette"> <label>Ocean</label> <input data-id="palette-poison" type="radio" name="palette"> <label>Poison</label> <input data-id="palette-garden" type="radio" name="palette"> <label>Garden</label> <input data-id="palette-sky" type="radio" name="palette"> <label>Sky</label> </fieldset> <fieldset> <legend>Resolution</legend> <label>Maximum iterations:</label> <input data-id="iteration-threshold" type="number" value="20"> <label>Scale:</label> <input data-id="scale" type="number" value="1" step="any"> </fieldset> <fieldset> <legend>Canvas size [px]</legend> <label>Width:</label> <input data-id="width" type="number" value="400"> <label>Height:</label> <input data-id="height" type="number" value="400"> </fieldset> <fieldset> <legend>Offset from the top-left corner [px]</legend> <label>X:</label> <input data-id="offset-x" type="number" value="0" step="any"> <label>Y:</label> <input data-id="offset-y" type="number" value="0" step="any"> </fieldset> <button type="submit" class="button">Apply</button> </form>` function applySettings (event) { event.preventDefault() if (this.graph) { this.saveParameters() event = new CustomEvent('submitted') } else { event = new CustomEvent('submit') } this.dispatchEvent(event) } function addFormListener (element) { const applyThisSettings = applySettings.bind(element) element.applyThisSettings = applyThisSettings element.form.addEventListener('submit', applyThisSettings) } function removeFormListener (element) { element.form.removeEventListener('submit', element.applyThisSettings) } function addGraphObserver (element) { const observer = new MutationObserver(function () { element.loadParameters() }) observer.observe(element.graph, { attributes: true }) element.observer = observer } function removeGraphObserver (element) { element.observer.disconnect() } function bindGraph (element, graph) { graph = document.getElementById(graph) element.bindGraph(graph) } const fields = [ 'iteration-threshold', 'scale', 'width', 'height', 'offset-x', 'offset-y', 'palette-grayscale', 'palette-jewels', 'palette-fiery', 'palette-rainbow', 'palette-sharp', 'palette-onion', 'palette-ocean', 'palette-poison', 'palette-garden', 'palette-sky' ] class SetFormElement extends HTMLElement { constructor () { super() const parent = initializeElement(this, template) this.parent = parent const form = parent.lastElementChild this.form = form this.fields = ensureUniqueFieldIds(form, fields) const graph = this.getAttribute('for') if (graph) { bindGraph(this, graph) } } connectedCallback () { addFormListener(this) if (this.graph) { addGraphObserver(this) } } disconnectedCallback () { removeFormListener(this) if (this.graph) { removeGraphObserver(this) } } attributeChangedCallback (name, oldValue, newValue) { if (name === 'for') { bindGraph(this, newValue) } } bindGraph (graph) { this.graph = graph if (this.applyThisSettings) { if (this.observer) { removeGraphObserver(this) } addGraphObserver(this) } } loadParameters () { const parameters = this.graph.getParameters() this.setParameters(parameters) } saveParameters () { const parameters = this.getParameters() const graph = this.graph graph.suppressUpdates() graph.setParameters(parameters) graph.resumeUpdates() } getParameters () { const form = this.form const fields = this.fields const palette = form .querySelector('input[name="palette"]:checked') .getAttribute('data-id') .substr(8) const iterationThreshold = +fields['iteration-threshold'].value const scale = +fields.scale.value const width = +fields.width.value const height = +fields.height.value const offsetX = +fields['offset-x'].value const offsetY = +fields['offset-y'].value return { palette, iterationThreshold, scale, width, height, offsetX, offsetY } } setParameters ({ palette, iterationThreshold, scale, width, height, offsetX, offsetY }) { const form = this.form const fields = this.fields form.querySelector(`[data-id=palette-${palette}]`).checked = true fields['iteration-threshold'].value = iterationThreshold fields.scale.value = scale fields.width.value = width fields.height.value = height fields['offset-x'].value = offsetX fields['offset-y'].value = offsetY } } export { SetFormElement }