fix: blend the canvas background over black
The opacity slider is documented as a blend over black, and the preview image does that. The editor composited the image over #1a1a1a instead.
This commit is contained in:
@@ -2,6 +2,7 @@ import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
|
||||
import {
|
||||
backgroundPlateShown,
|
||||
captionText,
|
||||
cleanPalette,
|
||||
elementToRegion,
|
||||
@@ -236,6 +237,16 @@ describe("overlapping regions", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("background image plate", () => {
|
||||
it("is black only while a reference image is actually drawn", () => {
|
||||
assert.equal(backgroundPlateShown("/view?filename=bg.png", 0.5), true);
|
||||
assert.equal(backgroundPlateShown("/view?filename=bg.png", 1), true);
|
||||
assert.equal(backgroundPlateShown("/view?filename=bg.png", 0), false);
|
||||
assert.equal(backgroundPlateShown("", 0.5), false);
|
||||
assert.equal(backgroundPlateShown(null, 0.5), false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("color palettes", () => {
|
||||
it("uppercases #RRGGBB, expands #RGB, and drops values Ideogram rejects", () => {
|
||||
assert.deepEqual(
|
||||
|
||||
@@ -228,6 +228,15 @@ export function cleanPalette(colors, limit) {
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* The reference image is drawn with CSS opacity. The black plate is what
|
||||
* that opacity blends over, matching the preview. Hidden when there is no
|
||||
* image, so the empty canvas stays the editor gray.
|
||||
*/
|
||||
export function backgroundPlateShown(url, opacity) {
|
||||
return Boolean(url) && Number(opacity) > 0;
|
||||
}
|
||||
|
||||
/** Lowercase #rrggbb for input[type=color]. Anything else is unusable there. */
|
||||
export function swatchHex(color) {
|
||||
const hex = normalizeHex(color);
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
normalizeStoreName, savedPresetCollision,
|
||||
} from "./ideogram4_shared.js";
|
||||
import {
|
||||
backgroundPlateShown,
|
||||
captionText, cleanPalette, dimsFromAspect, elementToRegion, ideogramResolutionWarning,
|
||||
parseCaptionText,
|
||||
snapLayoutDim,
|
||||
@@ -129,6 +130,7 @@ function injectStyle() {
|
||||
s.textContent = `
|
||||
.byae-ideo-wrap { display:flex; flex-direction:column; overflow:hidden; position:relative; pointer-events:auto; gap:4px; width:100%; box-sizing:border-box; }
|
||||
.byae-ideo-canvas-wrap { position:relative; flex:0 0 auto; width:100%; border-radius:4px; overflow:hidden; background:#1a1a1a; }
|
||||
.byae-ideo-bg-plate { position:absolute; inset:0; background:#000; pointer-events:none; display:none; }
|
||||
.byae-ideo-bg { position:absolute; inset:0; width:100%; height:100%; object-fit:fill; pointer-events:none; display:none; }
|
||||
.byae-ideo-canvas { cursor:crosshair; display:block; width:100%; height:auto; position:relative; z-index:1; background:transparent; border-radius:4px; outline:none; }
|
||||
.byae-ideo-bar { display:flex; align-items:center; gap:6px; font:11px sans-serif; color:#aaa; user-select:none; padding:0 2px; flex:0 0 auto; flex-wrap:wrap; width:100%; box-sizing:border-box; }
|
||||
@@ -753,6 +755,8 @@ app.registerExtension({
|
||||
|
||||
const canvasWrap = document.createElement("div");
|
||||
canvasWrap.className = "byae-ideo-canvas-wrap";
|
||||
const bgPlate = document.createElement("div");
|
||||
bgPlate.className = "byae-ideo-bg-plate";
|
||||
const bgImgEl = document.createElement("img");
|
||||
bgImgEl.className = "byae-ideo-bg";
|
||||
bgImgEl.alt = "";
|
||||
@@ -766,6 +770,7 @@ app.registerExtension({
|
||||
const canvasEl = document.createElement("canvas");
|
||||
canvasEl.className = "byae-ideo-canvas";
|
||||
canvasEl.tabIndex = 0;
|
||||
canvasWrap.appendChild(bgPlate);
|
||||
canvasWrap.appendChild(bgImgEl);
|
||||
canvasWrap.appendChild(canvasEl);
|
||||
let ctx = canvasEl.getContext("2d");
|
||||
@@ -2233,11 +2238,16 @@ app.registerExtension({
|
||||
}
|
||||
|
||||
function syncBgDisplay() {
|
||||
const host = getEditorHost();
|
||||
const { bgImgEl: bg } = getLiveCanvas();
|
||||
const plate = host?.querySelector?.(".byae-ideo-bg-plate");
|
||||
const url = node._bgDisplayUrl || "";
|
||||
const op = getBgOpacity();
|
||||
if (!bg) return;
|
||||
if (url && op > 0) {
|
||||
// Opacity blends the image with whatever is painted behind it. The
|
||||
// plate is black so that matches the preview, which composites onto black.
|
||||
const show = backgroundPlateShown(url, op);
|
||||
if (show) {
|
||||
if (bg.dataset.byaeSrc !== url) {
|
||||
bg.dataset.byaeSrc = url;
|
||||
bg.src = url;
|
||||
@@ -2249,6 +2259,7 @@ app.registerExtension({
|
||||
bg.removeAttribute("src");
|
||||
bg.style.display = "none";
|
||||
}
|
||||
if (plate) plate.style.display = show ? "block" : "none";
|
||||
}
|
||||
|
||||
function applyBgDisplay(displayUrl) {
|
||||
|
||||
Reference in New Issue
Block a user