class KnobElement extends HTMLElement { static observedAttributes = ["min", "max", "value", "step"]; _min = -1; rawValue = 0; _value = 0; step = 1; _max = 1; constructor() { super(); } connectedCallback() { // if ("min" in this.attributes) { // this._min = parseFloat(this.attributes["min"].value); // } // if ("max" in this.attributes) { // this._max = parseFloat(this.attributes["max"].value); // } if ("value" in this.attributes) { this.value = parseFloat(this.attributes["value"].value); } // if ("step" in this.attributes) { // this.step = parseFloat(this.attributes["step"].value); // } var shadow = this.attachShadow({ "mode": "open" }); var style = document.createElement("style"); style.textContent = ` #wrapper { background-color: rgba(24, 24, 24, 1.0); width: 40px; height: 40px; border-radius: 100%; } #cursor { position: relative; background-color: rgba(232, 232, 232, 1.0); width: 4px; height: 16px; left: calc(50% - 2px); } `; var wrapper = document.createElement("div"); wrapper.id = "wrapper"; wrapper.onmousedown = (function (event) { window.onmousemove = (function (event) { this.rawValue += event.movementX / 2; if (this.rawValue < -128) { this.rawValue = -128; } if (this.rawValue > 127) { this.rawValue = 127; } var range = this._max - this._min; var theoreticalValue = (((this.rawValue + Math.abs(-128)) * range) / 255) + this._min; var invertedStep = 1 / this.step; this._value = Math.round(theoreticalValue * invertedStep) / invertedStep; this.wrapper.style.rotate = String((this.rawValue * 135) / 128) + "deg"; var inputEvent = new InputEvent("input"); this.dispatchEvent(inputEvent); }).bind(this); window.onmouseup = function (event) { window.onmousemove = null; window.onmouseup = null; }; }).bind(this); var cursor = document.createElement("div"); cursor.id = "cursor"; wrapper.appendChild(cursor); shadow.appendChild(style); shadow.appendChild(wrapper); this.wrapper = wrapper; } attributeChangedCallback(name, oldValue, newValue) { this[name] = parseFloat(newValue); } get min() { return this._min; } set min(value) { if (isNaN(value)) return; this._min = value; if (this._value < this._min) { this._value = this._min; } this.rawValue = (((this._value + Math.abs(this._min)) * 255) / (this._max - this._min)) + -128; if ("wrapper" in this) this.wrapper.style.rotate = String((this.rawValue * 135) / 128) + "deg"; } get value() { return this._value; } set value(value) { if (isNaN(value)) return; if (value < this._min) { this._value = this._min; } else if (value > this._max) { this._value = this._max; } else { this._value = value; } this.rawValue = (((this._value + Math.abs(this._min)) * 255) / (this._max - this._min)) + -128; if ("wrapper" in this) this.wrapper.style.rotate = String((this.rawValue * 135) / 128) + "deg"; } get max() { return this._max; } set max(value) { if (isNaN(value)) return; this._max = value; if (this._value > this._max) { this._value = this._max; } this.rawValue = (((this._value + Math.abs(this._min)) * 255) / (this._max - this._min)) + -128; if ("wrapper" in this) this.wrapper.style.rotate = String((this.rawValue * 135) / 128) + "deg"; } } customElements.define("knob-input", KnobElement);