From 5d483bf307c766aee97caec857d414946fad47db Mon Sep 17 00:00:00 2001 From: Gerschel Date: Mon, 6 Feb 2023 08:18:04 -0800 Subject: aspect ratio for dim's; sliders adjust by ratio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Default choices added to settings in user interface section Choices are editable by user User selects from dropdown. When you move one slider, the other adjusts according to the ratio chosen. Vice versa for the other slider. Number fields for changes work as well. For disabling ratio, an unlock pad "🔓" is available as a default. This string can be changed to anything to serve as a disable, as long as there is no colon ":". Ratios are entered in this format, floats or ints with a colon "1:1". The string is split at the colon, parses left and right as floats to perform the math. --- javascript/aspectRatioSliders.js | 41 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 javascript/aspectRatioSliders.js (limited to 'javascript/aspectRatioSliders.js') diff --git a/javascript/aspectRatioSliders.js b/javascript/aspectRatioSliders.js new file mode 100644 index 00000000..f577750a --- /dev/null +++ b/javascript/aspectRatioSliders.js @@ -0,0 +1,41 @@ +class AspectRatioSliderController { + constructor(widthSlider, heightSlider, ratioSource) { + this.widthSlider = new SliderComponentController(widthSlider); + this.heightSlider = new SliderComponentController(heightSlider); + this.ratioSource = new DropdownComponentController(ratioSource); + this.widthSlider.childRangeField.addEventListener("change", () => this.resize("width")); + this.widthSlider.childNumField.addEventListener("change", () => this.resize("width")); + this.heightSlider.childRangeField.addEventListener("change", () => this.resize("height")); + this.heightSlider.childNumField.addEventListener("change", () => this.resize("height")); + } + resize(dimension) { + let val = this.ratioSource.getVal(); + if (!val.includes(":")) { + return; + } + let [width, height] = val.split(":").map(Number); + let ratio = width / height; + if (dimension == 'width') { + this.heightSlider.setVal(Math.round(parseFloat(this.widthSlider.getVal()) / ratio).toString()); + } + else if (dimension == "height") { + this.widthSlider.setVal(Math.round(parseFloat(this.heightSlider.getVal()) * ratio).toString()); + } + } + static observeStartup(widthSliderId, heightSliderId, ratioSourceId) { + let observer = new MutationObserver(() => { + let widthSlider = document.querySelector("gradio-app").shadowRoot.getElementById(widthSliderId); + let heightSlider = document.querySelector("gradio-app").shadowRoot.getElementById(heightSliderId); + let ratioSource = document.querySelector("gradio-app").shadowRoot.getElementById(ratioSourceId); + if (widthSlider && heightSlider && ratioSource) { + observer.disconnect(); + new AspectRatioSliderController(widthSlider, heightSlider, ratioSource); + } + }); + observer.observe(gradioApp(), { childList: true, subtree: true }); + } +} +document.addEventListener("DOMContentLoaded", () => { + AspectRatioSliderController.observeStartup("txt2img_width", "txt2img_height", "txt2img_ratio"); + AspectRatioSliderController.observeStartup("img2img_width", "img2img_height", "img2img_ratio"); +}); -- cgit v1.2.3 From 374fe636b80169c78b4b5f92013681d75fa2fad6 Mon Sep 17 00:00:00 2001 From: Gerschel Date: Wed, 8 Feb 2023 18:57:32 -0800 Subject: Squashed commit of the following: commit b030b67ad005bfe29bcda692238a00042dcae816 Author: Gerschel Date: Wed Feb 8 16:38:56 2023 -0800 styling adjustements commit 80a2acb0230dd77489b0eb466f2efe827a053f6d Author: Gerschel Date: Wed Feb 8 10:49:47 2023 -0800 badge indicator toggles visibility by selection commit 898922e025a6422ac947fb45c1fa4f1109882f0a Merge: 745382a0 31bbfa72 Author: Gerschel <9631031+Gerschel@users.noreply.github.com> Date: Wed Feb 8 08:35:26 2023 -0800 Merge pull request #1 from w-e-w/Rounding-Method Rounding Method commit 31bbfa729a15ef35fa1f905345d3ba2b17b26ab9 Author: w-e-w <40751091+w-e-w@users.noreply.github.com> Date: Wed Feb 8 19:41:45 2023 +0900 use switch commit 85dbe511c33521d3ac62224bf0e0f3a48194ce63 Author: w-e-w <40751091+w-e-w@users.noreply.github.com> Date: Wed Feb 8 16:47:52 2023 +0900 Rounding Method commit 745382a0f4b8d16241545a3460d5206915959255 Author: Gerschel Date: Tue Feb 7 21:19:20 2023 -0800 default set to round commit 728579c618af30ec98a5af0991bd3f28bdaca399 Author: Gerschel Date: Tue Feb 7 21:17:03 2023 -0800 cleaned some commented code out; added indicator commit 5b288c24a1edd8a5c2f35214b9634316d05b8dae Author: Gerschel Date: Tue Feb 7 18:19:00 2023 -0800 needs cleaning; attempt at rounding commit d9f18ae92b929576b0b8c5f1ef8b3b38e441e381 Author: Gerschel Date: Tue Feb 7 15:46:25 2023 -0800 add rounding option in setting for aspect ratio commit af22106802c9e42205649e4c71c23fcf5b8c62f6 Author: Gerschel Date: Tue Feb 7 13:18:45 2023 -0800 added some ratios, sorted ratios by commonality commit 11e2fba73cffe8cdbf4cd0860641b94428ca0e74 Author: Gerschel Date: Tue Feb 7 10:46:53 2023 -0800 snaps to mulitples of 8 and along ratio commit fa00387e07460b10ee82671a1bfa8687e00ee60b Author: Gerschel Date: Mon Feb 6 14:54:59 2023 -0800 updated slidercomponentcontroller commit 8059bc111c3e2d1edb3314e05ab21b65120fa1dd Author: Gerschel Date: Mon Feb 6 14:29:11 2023 -0800 added step size adjustment on number field commit 641157b9f27a874a24ee7b0a854a092e9eac3eec Author: Gerschel Date: Mon Feb 6 14:12:03 2023 -0800 added return step size to default when ratio is disabled commit 5fb75ad28f2476f36100ec93922a8199adbd2a68 Author: Gerschel Date: Mon Feb 6 14:09:34 2023 -0800 added step size adjustment commit e33532883bc4709cd41c3775cbb646d1d5ab0584 Author: Gerschel Date: Mon Feb 6 11:56:15 2023 -0800 adjusted dropdown size, padding, text-align commit 81937329cee77f466c5a5b23c268d0c810128f84 Author: Gerschel Date: Mon Feb 6 11:39:57 2023 -0800 added positioning and styling commit 86eb4583782d92880a9a113a54ffbac9d92f3753 Author: Gerschel Date: Mon Feb 6 08:54:45 2023 -0800 fix typo in defaults; added preventDefault in event --- javascript/aspectRatioSliders.js | 164 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 152 insertions(+), 12 deletions(-) (limited to 'javascript/aspectRatioSliders.js') diff --git a/javascript/aspectRatioSliders.js b/javascript/aspectRatioSliders.js index f577750a..d9c4f675 100644 --- a/javascript/aspectRatioSliders.js +++ b/javascript/aspectRatioSliders.js @@ -1,14 +1,61 @@ class AspectRatioSliderController { - constructor(widthSlider, heightSlider, ratioSource) { + constructor(widthSlider, heightSlider, ratioSource, roundingSource, roundingMethod) { + //References this.widthSlider = new SliderComponentController(widthSlider); this.heightSlider = new SliderComponentController(heightSlider); this.ratioSource = new DropdownComponentController(ratioSource); - this.widthSlider.childRangeField.addEventListener("change", () => this.resize("width")); - this.widthSlider.childNumField.addEventListener("change", () => this.resize("width")); - this.heightSlider.childRangeField.addEventListener("change", () => this.resize("height")); - this.heightSlider.childNumField.addEventListener("change", () => this.resize("height")); + this.roundingSource = new CheckboxComponentController(roundingSource); + this.roundingMethod = new RadioComponentController(roundingMethod); + this.roundingIndicatorBadge = document.createElement("div"); + // Badge implementation + this.roundingIndicatorBadge.innerText = "📐"; + this.roundingIndicatorBadge.classList.add("rounding-badge"); + this.ratioSource.element.appendChild(this.roundingIndicatorBadge); + // Check initial value of ratioSource to set badge visbility + let initialRatio = this.ratioSource.getVal(); + if (!initialRatio.includes(":")) { + this.roundingIndicatorBadge.style.display = "none"; + } + //Adjust badge icon if rounding is on + if (this.roundingSource.getVal()) { + this.roundingIndicatorBadge.classList.add("active"); + this.roundingIndicatorBadge.innerText = "⚠️"; + } + //Make badge clickable to toggle setting + this.roundingIndicatorBadge.addEventListener("click", () => { + this.roundingSource.setVal(!this.roundingSource.getVal()); + }); + //Make rounding setting toggle badge text and style if setting changes + this.roundingSource.child.addEventListener("change", () => { + if (this.roundingSource.getVal()) { + this.roundingIndicatorBadge.classList.add("active"); + this.roundingIndicatorBadge.innerText = "⚠️"; + } + else { + this.roundingIndicatorBadge.classList.remove("active"); + this.roundingIndicatorBadge.innerText = "📐"; + } + this.adjustStepSize(); + }); + //Other event listeners + this.widthSlider.childRangeField.addEventListener("change", (e) => { e.preventDefault(); this.resize("width"); }); + this.widthSlider.childNumField.addEventListener("change", (e) => { e.preventDefault(); this.resize("width"); }); + this.heightSlider.childRangeField.addEventListener("change", (e) => { e.preventDefault(); this.resize("height"); }); + this.heightSlider.childNumField.addEventListener("change", (e) => { e.preventDefault(); this.resize("height"); }); + this.ratioSource.childSelector.addEventListener("change", (e) => { + e.preventDefault(); + //Check and toggle display of badge conditionally on dropdown selection + if (!this.ratioSource.getVal().includes(":")) { + this.roundingIndicatorBadge.style.display = 'none'; + } + else { + this.roundingIndicatorBadge.style.display = 'block'; + } + this.adjustStepSize(); + }); } resize(dimension) { + //For moving slider or number field let val = this.ratioSource.getVal(); if (!val.includes(":")) { return; @@ -16,26 +63,119 @@ class AspectRatioSliderController { let [width, height] = val.split(":").map(Number); let ratio = width / height; if (dimension == 'width') { - this.heightSlider.setVal(Math.round(parseFloat(this.widthSlider.getVal()) / ratio).toString()); + let newHeight = parseInt(this.widthSlider.getVal()) / ratio; + if (this.roundingSource.getVal()) { + switch (this.roundingMethod.getVal()) { + case 'Round': + newHeight = Math.round(newHeight / 8) * 8; + break; + case 'Ceiling': + newHeight = Math.ceil(newHeight / 8) * 8; + break; + case 'Floor': + newHeight = Math.floor(newHeight / 8) * 8; + break; + } + } + this.heightSlider.setVal(newHeight.toString()); } else if (dimension == "height") { - this.widthSlider.setVal(Math.round(parseFloat(this.heightSlider.getVal()) * ratio).toString()); + let newWidth = parseInt(this.heightSlider.getVal()) * ratio; + if (this.roundingSource.getVal()) { + switch (this.roundingMethod.getVal()) { + case 'Round': + newWidth = Math.round(newWidth / 8) * 8; + break; + case 'Ceiling': + newWidth = Math.ceil(newWidth / 8) * 8; + break; + case 'Floor': + newWidth = Math.floor(newWidth / 8) * 8; + break; + } + } + this.widthSlider.setVal(newWidth.toString()); + } + } + adjustStepSize() { + /* Sets scales/precision/rounding steps;*/ + let val = this.ratioSource.getVal(); + if (!val.includes(":")) { + //If ratio unlocked + this.widthSlider.childRangeField.step = "8"; + this.widthSlider.childRangeField.min = "64"; + this.widthSlider.childNumField.step = "8"; + this.widthSlider.childNumField.min = "64"; + this.heightSlider.childRangeField.step = "8"; + this.heightSlider.childRangeField.min = "64"; + this.heightSlider.childNumField.step = "8"; + this.heightSlider.childNumField.min = "64"; + return; + } + //Format string and calculate step sizes + let [width, height] = val.split(":").map(Number); + let decimalPlaces = (width.toString().split(".")[1] || []).length; + //keep upto 6 decimal points of precision of ratio + //euclidean gcd does not support floats, so we scale it up + decimalPlaces = decimalPlaces > 6 ? 6 : decimalPlaces; + let gcd = this.gcd(width * 10 ** decimalPlaces, height * 10 ** decimalPlaces) / 10 ** decimalPlaces; + let stepSize = 8 * height / gcd; + let stepSizeOther = 8 * width / gcd; + if (this.roundingSource.getVal()) { + //If rounding is on set/keep default stepsizes + this.widthSlider.childRangeField.step = "8"; + this.widthSlider.childRangeField.min = "64"; + this.widthSlider.childNumField.step = "8"; + this.widthSlider.childNumField.min = "64"; + this.heightSlider.childRangeField.step = "8"; + this.heightSlider.childRangeField.min = "64"; + this.heightSlider.childNumField.step = "8"; + this.heightSlider.childNumField.min = "64"; + } + else { + //if rounding is off, set step sizes so they enforce snapping + //min is changed, because it offsets snap positions + this.widthSlider.childRangeField.step = stepSizeOther.toString(); + this.widthSlider.childRangeField.min = stepSizeOther.toString(); + this.widthSlider.childNumField.step = stepSizeOther.toString(); + this.widthSlider.childNumField.min = stepSizeOther.toString(); + this.heightSlider.childRangeField.step = stepSize.toString(); + this.heightSlider.childRangeField.min = stepSize.toString(); + this.heightSlider.childNumField.step = stepSize.toString(); + this.heightSlider.childNumField.min = stepSize.toString(); + } + let currentWidth = parseInt(this.widthSlider.getVal()); + //Rounding treated kinda like pythons divmod + let stepsTaken = Math.round(currentWidth / stepSizeOther); + //this snaps it to closest rule matches (rules being html step points, and ratio) + let newWidth = stepsTaken * stepSizeOther; + this.widthSlider.setVal(newWidth.toString()); + this.heightSlider.setVal(Math.round(newWidth / (width / height)).toString()); + } + gcd(a, b) { + //euclidean gcd + if (b === 0) { + return a; } + return this.gcd(b, a % b); } - static observeStartup(widthSliderId, heightSliderId, ratioSourceId) { + static observeStartup(widthSliderId, heightSliderId, ratioSourceId, roundingSourceId, roundingMethodId) { let observer = new MutationObserver(() => { let widthSlider = document.querySelector("gradio-app").shadowRoot.getElementById(widthSliderId); let heightSlider = document.querySelector("gradio-app").shadowRoot.getElementById(heightSliderId); let ratioSource = document.querySelector("gradio-app").shadowRoot.getElementById(ratioSourceId); - if (widthSlider && heightSlider && ratioSource) { + let roundingSource = document.querySelector("gradio-app").shadowRoot.getElementById(roundingSourceId); + let roundingMethod = document.querySelector("gradio-app").shadowRoot.getElementById(roundingMethodId); + if (widthSlider && heightSlider && ratioSource && roundingSource && roundingMethod) { observer.disconnect(); - new AspectRatioSliderController(widthSlider, heightSlider, ratioSource); + new AspectRatioSliderController(widthSlider, heightSlider, ratioSource, roundingSource, roundingMethod); } }); observer.observe(gradioApp(), { childList: true, subtree: true }); } } document.addEventListener("DOMContentLoaded", () => { - AspectRatioSliderController.observeStartup("txt2img_width", "txt2img_height", "txt2img_ratio"); - AspectRatioSliderController.observeStartup("img2img_width", "img2img_height", "img2img_ratio"); + //Register mutation observer for self start-up; + AspectRatioSliderController.observeStartup("txt2img_width", "txt2img_height", "txt2img_ratio", "setting_aspect_ratios_rounding", "setting_aspect_ratios_rounding_method"); + AspectRatioSliderController.observeStartup("img2img_width", "img2img_height", "img2img_ratio", "setting_aspect_ratios_rounding", "setting_aspect_ratios_rounding_method"); }); -- cgit v1.2.3 From b313221ca6d12e441f2f5041490e2fc665ff5f60 Mon Sep 17 00:00:00 2001 From: w-e-w <40751091+w-e-w@users.noreply.github.com> Date: Fri, 10 Feb 2023 08:34:21 +0900 Subject: =?UTF-8?q?remove=20Badge=20color=20and=20=E2=9A=A0=EF=B8=8F=20->?= =?UTF-8?q?=F0=9F=93=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- javascript/aspectRatioSliders.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'javascript/aspectRatioSliders.js') diff --git a/javascript/aspectRatioSliders.js b/javascript/aspectRatioSliders.js index d9c4f675..3def5158 100644 --- a/javascript/aspectRatioSliders.js +++ b/javascript/aspectRatioSliders.js @@ -18,8 +18,8 @@ class AspectRatioSliderController { } //Adjust badge icon if rounding is on if (this.roundingSource.getVal()) { - this.roundingIndicatorBadge.classList.add("active"); - this.roundingIndicatorBadge.innerText = "⚠️"; + //this.roundingIndicatorBadge.classList.add("active"); + this.roundingIndicatorBadge.innerText = "📏"; } //Make badge clickable to toggle setting this.roundingIndicatorBadge.addEventListener("click", () => { @@ -28,11 +28,11 @@ class AspectRatioSliderController { //Make rounding setting toggle badge text and style if setting changes this.roundingSource.child.addEventListener("change", () => { if (this.roundingSource.getVal()) { - this.roundingIndicatorBadge.classList.add("active"); - this.roundingIndicatorBadge.innerText = "⚠️"; + //this.roundingIndicatorBadge.classList.add("active"); + this.roundingIndicatorBadge.innerText = "📏"; } else { - this.roundingIndicatorBadge.classList.remove("active"); + //this.roundingIndicatorBadge.classList.remove("active"); this.roundingIndicatorBadge.innerText = "📐"; } this.adjustStepSize(); -- cgit v1.2.3