Merge pull request #3222 from SillyTavern/bg-fitting Add background image fitting options
Signed| @@ -4713,6 +4713,13 @@ | ||
| 4713 | 4713 | Background Image |
| 4714 | 4714 | </h3> |
| 4715 | 4715 | <input id="bg-filter" data-i18n="[placeholder]Filter" placeholder="Filter" class="text_pole flex1" type="search" /> |
| 4716 | + <select id="background_fitting" class="text_pole" data-i18n="[title]Background Fitting" title="Background Fitting"> | |
| 4717 | + <option value="classic" data-i18n="Classic">Classic</option> | |
| 4718 | + <option value="cover" data-i18n="Cover">Cover</option> | |
| 4719 | + <option value="contain" data-i18n="Contain">Contain</option> | |
| 4720 | + <option value="stretch" data-i18n="Stretch">Stretch</option> | |
| 4721 | + <option value="center" data-i18n="Center">Center</option> | |
| 4722 | + </select> | |
| 4716 | 4723 | <div id="auto_background" class="menu_button menu_button_icon" data-i18n="[title]Automatically select a background based on the chat context" title="Automatically select a background based on the chat context."> |
| 4717 | 4724 | <i class="fa-solid fa-wand-magic"></i> |
| 4718 | 4725 | <span data-i18n="Auto-select">Auto-select</span> |
| @@ -12,6 +12,7 @@ const LIST_METADATA_KEY = 'chat_backgrounds'; | ||
| 12 | 12 | export let background_settings = { |
| 13 | 13 | name: '__transparent.png', |
| 14 | 14 | url: generateUrlParameter('__transparent.png', false), |
| 15 | + fitting: 'classic', | |
| 15 | 16 | }; |
| 16 | 17 | |
| 17 | 18 | export function loadBackgroundSettings(settings) { |
| @@ -19,7 +20,12 @@ export function loadBackgroundSettings(settings) { | ||
| 19 | 20 | if (!backgroundSettings || !backgroundSettings.name || !backgroundSettings.url) { |
| 20 | 21 | backgroundSettings = background_settings; |
| 21 | 22 | } |
| 23 | + if (!backgroundSettings.fitting) { | |
| 24 | + backgroundSettings.fitting = 'classic'; | |
| 25 | + } | |
| 22 | 26 | setBackground(backgroundSettings.name, backgroundSettings.url); |
| 27 | + setFittingClass(backgroundSettings.fitting); | |
| 28 | + $('#background_fitting').val(backgroundSettings.fitting); | |
| 23 | 29 | } |
| 24 | 30 | |
| 25 | 31 | /** |
| @@ -470,6 +476,18 @@ function highlightNewBackground(bg) { | ||
| 470 | 476 | flashHighlight(newBg); |
| 471 | 477 | } |
| 472 | 478 | |
| 479 | +/** | |
| 480 | + * Sets the fitting class for the background element | |
| 481 | + * @param {string} fitting Fitting type | |
| 482 | + */ | |
| 483 | +function setFittingClass(fitting) { | |
| 484 | + const backgrounds = $('#bg1, #bg_custom'); | |
| 485 | + backgrounds.toggleClass('cover', fitting === 'cover'); | |
| 486 | + backgrounds.toggleClass('contain', fitting === 'contain'); | |
| 487 | + backgrounds.toggleClass('stretch', fitting === 'stretch'); | |
| 488 | + backgrounds.toggleClass('center', fitting === 'center'); | |
| 489 | +} | |
| 490 | + | |
| 473 | 491 | function onBackgroundFilterInput() { |
| 474 | 492 | const filterValue = String($(this).val()).toLowerCase(); |
| 475 | 493 | $('#bg_menu_content > div').each(function () { |
| @@ -510,4 +528,9 @@ export function initBackgrounds() { | ||
| 510 | 528 | helpString: 'Automatically changes the background based on the chat context using the AI request prompt', |
| 511 | 529 | })); |
| 512 | 530 | |
| 531 | + $('#background_fitting').on('input', function () { | |
| 532 | + background_settings.fitting = String($(this).val()); | |
| 533 | + setFittingClass(background_settings.fitting); | |
| 534 | + saveSettingsDebounced(); | |
| 535 | + }); | |
| 513 | 536 | } |
| @@ -141,7 +141,7 @@ body { | ||
| 141 | 141 | height: 100dvh; |
| 142 | 142 | /*defaults as 100%, then reassigned via JS as pixels, will work on PC and Android*/ |
| 143 | 143 | /*height: calc(var(--doc-height) - 1px);*/ |
| 144 | 144 | background-color: var(--greyCAIbgSmartThemeBlurTintColor); |
| 145 | 145 | background-repeat: no-repeat; |
| 146 | 146 | background-attachment: fixed; |
| 147 | 147 | background-size: cover; |
| @@ -519,6 +519,40 @@ hr { | ||
| 519 | 519 | transition: background-image 0.5s ease-in-out; |
| 520 | 520 | } |
| 521 | 521 | |
| 522 | +/* Background fitting options */ | |
| 523 | +#background_fitting { | |
| 524 | + max-width: 6em; | |
| 525 | +} | |
| 526 | + | |
| 527 | +/* Fill/Cover - scales to fill width while maintaining aspect ratio */ | |
| 528 | +#bg1.cover, | |
| 529 | +#bg_custom.cover { | |
| 530 | + background-size: cover; | |
| 531 | + background-position: center; | |
| 532 | +} | |
| 533 | + | |
| 534 | +/* Fit/Contain - shows entire image maintaining aspect ratio */ | |
| 535 | +#bg1.contain, | |
| 536 | +#bg_custom.contain { | |
| 537 | + background-size: contain; | |
| 538 | + background-position: center; | |
| 539 | + background-repeat: no-repeat; | |
| 540 | +} | |
| 541 | + | |
| 542 | +/* Stretch - stretches to fill entire space */ | |
| 543 | +#bg1.stretch, | |
| 544 | +#bg_custom.stretch { | |
| 545 | + background-size: 100% 100%; | |
| 546 | +} | |
| 547 | + | |
| 548 | +/* Center - centers without scaling */ | |
| 549 | +#bg1.center, | |
| 550 | +#bg_custom.center { | |
| 551 | + background-size: auto; | |
| 552 | + background-position: center; | |
| 553 | + background-repeat: no-repeat; | |
| 554 | +} | |
| 555 | + | |
| 522 | 556 | body.reduced-motion #bg1, |
| 523 | 557 | body.reduced-motion #bg_custom { |
| 524 | 558 | transition: none; |