mirror of
https://github.com/Azornes/Comfyui-LayerForge.git
synced 2026-03-26 06:45:44 -03:00
moved all CSS from src/CustomShapeMenu.ts to a new file
moved all CSS from src/CustomShapeMenu.ts to a new file src/css/custom_shape_menu.css and updated the TypeScript file to use the external stylesheet. This improves code organization and maintainability.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
||||||
|
import { addStylesheet, getUrl } from "./utils/ResourceManager.js";
|
||||||
const log = createModuleLogger('CustomShapeMenu');
|
const log = createModuleLogger('CustomShapeMenu');
|
||||||
export class CustomShapeMenu {
|
export class CustomShapeMenu {
|
||||||
constructor(canvas) {
|
constructor(canvas) {
|
||||||
@@ -42,27 +43,9 @@ export class CustomShapeMenu {
|
|||||||
_createUI() {
|
_createUI() {
|
||||||
if (this.uiInitialized)
|
if (this.uiInitialized)
|
||||||
return;
|
return;
|
||||||
|
addStylesheet(getUrl('./css/custom_shape_menu.css'));
|
||||||
this.element = document.createElement('div');
|
this.element = document.createElement('div');
|
||||||
this.element.id = 'layerforge-custom-shape-menu';
|
this.element.id = 'layerforge-custom-shape-menu';
|
||||||
this.element.style.cssText = `
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
background-color: #333;
|
|
||||||
color: white;
|
|
||||||
padding: 8px 15px;
|
|
||||||
border-radius: 10px;
|
|
||||||
box-shadow: 0 4px 15px rgba(0,0,0,0.5);
|
|
||||||
display: none;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
font-family: sans-serif;
|
|
||||||
font-size: 12px;
|
|
||||||
z-index: 1001;
|
|
||||||
border: 1px solid #555;
|
|
||||||
user-select: none;
|
|
||||||
min-width: 200px;
|
|
||||||
`;
|
|
||||||
// Create menu content
|
// Create menu content
|
||||||
const lines = [
|
const lines = [
|
||||||
"🎯 Custom Output Area Active"
|
"🎯 Custom Output Area Active"
|
||||||
@@ -70,22 +53,13 @@ export class CustomShapeMenu {
|
|||||||
lines.forEach(line => {
|
lines.forEach(line => {
|
||||||
const lineElement = document.createElement('div');
|
const lineElement = document.createElement('div');
|
||||||
lineElement.textContent = line;
|
lineElement.textContent = line;
|
||||||
lineElement.style.cssText = `
|
lineElement.className = 'menu-line';
|
||||||
margin: 2px 0;
|
|
||||||
line-height: 18px;
|
|
||||||
`;
|
|
||||||
this.element.appendChild(lineElement);
|
this.element.appendChild(lineElement);
|
||||||
});
|
});
|
||||||
// Create a container for the entire shape mask feature set
|
// Create a container for the entire shape mask feature set
|
||||||
const featureContainer = document.createElement('div');
|
const featureContainer = document.createElement('div');
|
||||||
featureContainer.id = 'shape-mask-feature-container';
|
featureContainer.id = 'shape-mask-feature-container';
|
||||||
featureContainer.style.cssText = `
|
featureContainer.className = 'feature-container';
|
||||||
background-color: #282828;
|
|
||||||
border-radius: 6px;
|
|
||||||
margin-top: 6px;
|
|
||||||
padding: 4px 0;
|
|
||||||
border: 1px solid #444;
|
|
||||||
`;
|
|
||||||
// Add main auto-apply checkbox to the new container
|
// Add main auto-apply checkbox to the new container
|
||||||
const checkboxContainer = this._createCheckbox(() => `${this.canvas.autoApplyShapeMask ? "☑" : "☐"} Auto-apply shape mask`, () => {
|
const checkboxContainer = this._createCheckbox(() => `${this.canvas.autoApplyShapeMask ? "☑" : "☐"} Auto-apply shape mask`, () => {
|
||||||
// Always hide any active shape preview lines first to prevent them from getting stuck
|
// Always hide any active shape preview lines first to prevent them from getting stuck
|
||||||
@@ -120,37 +94,17 @@ export class CustomShapeMenu {
|
|||||||
// Add expansion slider container
|
// Add expansion slider container
|
||||||
const expansionSliderContainer = document.createElement('div');
|
const expansionSliderContainer = document.createElement('div');
|
||||||
expansionSliderContainer.id = 'expansion-slider-container';
|
expansionSliderContainer.id = 'expansion-slider-container';
|
||||||
expansionSliderContainer.style.cssText = `
|
expansionSliderContainer.className = 'slider-container';
|
||||||
margin: 0 8px 6px 8px;
|
|
||||||
padding: 4px 8px;
|
|
||||||
display: none;
|
|
||||||
`;
|
|
||||||
const expansionSliderLabel = document.createElement('div');
|
const expansionSliderLabel = document.createElement('div');
|
||||||
expansionSliderLabel.textContent = 'Expansion amount:';
|
expansionSliderLabel.textContent = 'Expansion amount:';
|
||||||
expansionSliderLabel.style.cssText = `
|
expansionSliderLabel.className = 'slider-label';
|
||||||
font-size: 11px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
color: #ccc;
|
|
||||||
`;
|
|
||||||
const expansionSlider = document.createElement('input');
|
const expansionSlider = document.createElement('input');
|
||||||
expansionSlider.type = 'range';
|
expansionSlider.type = 'range';
|
||||||
expansionSlider.min = '-300';
|
expansionSlider.min = '-300';
|
||||||
expansionSlider.max = '300';
|
expansionSlider.max = '300';
|
||||||
expansionSlider.value = String(this.canvas.shapeMaskExpansionValue);
|
expansionSlider.value = String(this.canvas.shapeMaskExpansionValue);
|
||||||
expansionSlider.style.cssText = `
|
|
||||||
width: 100%;
|
|
||||||
height: 4px;
|
|
||||||
background: #555;
|
|
||||||
outline: none;
|
|
||||||
border-radius: 2px;
|
|
||||||
`;
|
|
||||||
const expansionValueDisplay = document.createElement('div');
|
const expansionValueDisplay = document.createElement('div');
|
||||||
expansionValueDisplay.style.cssText = `
|
expansionValueDisplay.className = 'slider-value-display';
|
||||||
font-size: 10px;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 2px;
|
|
||||||
color: #aaa;
|
|
||||||
`;
|
|
||||||
let expansionValueBeforeDrag = this.canvas.shapeMaskExpansionValue;
|
let expansionValueBeforeDrag = this.canvas.shapeMaskExpansionValue;
|
||||||
const updateExpansionSliderDisplay = () => {
|
const updateExpansionSliderDisplay = () => {
|
||||||
const value = parseInt(expansionSlider.value);
|
const value = parseInt(expansionSlider.value);
|
||||||
@@ -214,37 +168,17 @@ export class CustomShapeMenu {
|
|||||||
// Add feather slider container
|
// Add feather slider container
|
||||||
const featherSliderContainer = document.createElement('div');
|
const featherSliderContainer = document.createElement('div');
|
||||||
featherSliderContainer.id = 'feather-slider-container';
|
featherSliderContainer.id = 'feather-slider-container';
|
||||||
featherSliderContainer.style.cssText = `
|
featherSliderContainer.className = 'slider-container';
|
||||||
margin: 0 8px 6px 8px;
|
|
||||||
padding: 4px 8px;
|
|
||||||
display: none;
|
|
||||||
`;
|
|
||||||
const featherSliderLabel = document.createElement('div');
|
const featherSliderLabel = document.createElement('div');
|
||||||
featherSliderLabel.textContent = 'Feather amount:';
|
featherSliderLabel.textContent = 'Feather amount:';
|
||||||
featherSliderLabel.style.cssText = `
|
featherSliderLabel.className = 'slider-label';
|
||||||
font-size: 11px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
color: #ccc;
|
|
||||||
`;
|
|
||||||
const featherSlider = document.createElement('input');
|
const featherSlider = document.createElement('input');
|
||||||
featherSlider.type = 'range';
|
featherSlider.type = 'range';
|
||||||
featherSlider.min = '0';
|
featherSlider.min = '0';
|
||||||
featherSlider.max = '300';
|
featherSlider.max = '300';
|
||||||
featherSlider.value = String(this.canvas.shapeMaskFeatherValue);
|
featherSlider.value = String(this.canvas.shapeMaskFeatherValue);
|
||||||
featherSlider.style.cssText = `
|
|
||||||
width: 100%;
|
|
||||||
height: 4px;
|
|
||||||
background: #555;
|
|
||||||
outline: none;
|
|
||||||
border-radius: 2px;
|
|
||||||
`;
|
|
||||||
const featherValueDisplay = document.createElement('div');
|
const featherValueDisplay = document.createElement('div');
|
||||||
featherValueDisplay.style.cssText = `
|
featherValueDisplay.className = 'slider-value-display';
|
||||||
font-size: 10px;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 2px;
|
|
||||||
color: #aaa;
|
|
||||||
`;
|
|
||||||
const updateFeatherSliderDisplay = () => {
|
const updateFeatherSliderDisplay = () => {
|
||||||
const value = parseInt(featherSlider.value);
|
const value = parseInt(featherSlider.value);
|
||||||
this.canvas.shapeMaskFeatherValue = value;
|
this.canvas.shapeMaskFeatherValue = value;
|
||||||
@@ -283,13 +217,7 @@ export class CustomShapeMenu {
|
|||||||
// Create output area extension container
|
// Create output area extension container
|
||||||
const extensionContainer = document.createElement('div');
|
const extensionContainer = document.createElement('div');
|
||||||
extensionContainer.id = 'output-area-extension-container';
|
extensionContainer.id = 'output-area-extension-container';
|
||||||
extensionContainer.style.cssText = `
|
extensionContainer.className = 'feature-container';
|
||||||
background-color: #282828;
|
|
||||||
border-radius: 6px;
|
|
||||||
margin-top: 6px;
|
|
||||||
padding: 4px 0;
|
|
||||||
border: 1px solid #444;
|
|
||||||
`;
|
|
||||||
// Add main extension checkbox
|
// Add main extension checkbox
|
||||||
const extensionCheckboxContainer = this._createCheckbox(() => `${this.canvas.outputAreaExtensionEnabled ? "☑" : "☐"} Extend output area`, () => {
|
const extensionCheckboxContainer = this._createCheckbox(() => `${this.canvas.outputAreaExtensionEnabled ? "☑" : "☐"} Extend output area`, () => {
|
||||||
this.canvas.outputAreaExtensionEnabled = !this.canvas.outputAreaExtensionEnabled;
|
this.canvas.outputAreaExtensionEnabled = !this.canvas.outputAreaExtensionEnabled;
|
||||||
@@ -320,43 +248,21 @@ export class CustomShapeMenu {
|
|||||||
// Create sliders container
|
// Create sliders container
|
||||||
const slidersContainer = document.createElement('div');
|
const slidersContainer = document.createElement('div');
|
||||||
slidersContainer.id = 'extension-sliders-container';
|
slidersContainer.id = 'extension-sliders-container';
|
||||||
slidersContainer.style.cssText = `
|
slidersContainer.className = 'slider-container';
|
||||||
margin: 0 8px 6px 8px;
|
|
||||||
padding: 4px 8px;
|
|
||||||
display: none;
|
|
||||||
`;
|
|
||||||
// Helper function to create a slider with preview system
|
// Helper function to create a slider with preview system
|
||||||
const createExtensionSlider = (label, direction) => {
|
const createExtensionSlider = (label, direction) => {
|
||||||
const sliderContainer = document.createElement('div');
|
const sliderContainer = document.createElement('div');
|
||||||
sliderContainer.style.cssText = `
|
sliderContainer.className = 'extension-slider-container';
|
||||||
margin: 6px 0;
|
|
||||||
`;
|
|
||||||
const sliderLabel = document.createElement('div');
|
const sliderLabel = document.createElement('div');
|
||||||
sliderLabel.textContent = label;
|
sliderLabel.textContent = label;
|
||||||
sliderLabel.style.cssText = `
|
sliderLabel.className = 'slider-label';
|
||||||
font-size: 11px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
color: #ccc;
|
|
||||||
`;
|
|
||||||
const slider = document.createElement('input');
|
const slider = document.createElement('input');
|
||||||
slider.type = 'range';
|
slider.type = 'range';
|
||||||
slider.min = '0';
|
slider.min = '0';
|
||||||
slider.max = '500';
|
slider.max = '500';
|
||||||
slider.value = String(this.canvas.outputAreaExtensions[direction]);
|
slider.value = String(this.canvas.outputAreaExtensions[direction]);
|
||||||
slider.style.cssText = `
|
|
||||||
width: 100%;
|
|
||||||
height: 4px;
|
|
||||||
background: #555;
|
|
||||||
outline: none;
|
|
||||||
border-radius: 2px;
|
|
||||||
`;
|
|
||||||
const valueDisplay = document.createElement('div');
|
const valueDisplay = document.createElement('div');
|
||||||
valueDisplay.style.cssText = `
|
valueDisplay.className = 'slider-value-display';
|
||||||
font-size: 10px;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 2px;
|
|
||||||
color: #aaa;
|
|
||||||
`;
|
|
||||||
const updateDisplay = () => {
|
const updateDisplay = () => {
|
||||||
const value = parseInt(slider.value);
|
const value = parseInt(slider.value);
|
||||||
valueDisplay.textContent = `${value}px`;
|
valueDisplay.textContent = `${value}px`;
|
||||||
@@ -429,14 +335,7 @@ export class CustomShapeMenu {
|
|||||||
}
|
}
|
||||||
_createCheckbox(textFn, clickHandler, tooltipText) {
|
_createCheckbox(textFn, clickHandler, tooltipText) {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.style.cssText = `
|
container.className = 'checkbox-container';
|
||||||
margin: 6px 0 2px 0;
|
|
||||||
padding: 4px 8px;
|
|
||||||
border-radius: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color 0.2s;
|
|
||||||
line-height: 18px;
|
|
||||||
`;
|
|
||||||
container.onmouseover = () => {
|
container.onmouseover = () => {
|
||||||
container.style.backgroundColor = '#555';
|
container.style.backgroundColor = '#555';
|
||||||
};
|
};
|
||||||
@@ -577,24 +476,7 @@ export class CustomShapeMenu {
|
|||||||
this.hideTooltip(); // Hide any existing tooltip
|
this.hideTooltip(); // Hide any existing tooltip
|
||||||
this.tooltip = document.createElement('div');
|
this.tooltip = document.createElement('div');
|
||||||
this.tooltip.textContent = text;
|
this.tooltip.textContent = text;
|
||||||
this.tooltip.style.cssText = `
|
this.tooltip.className = 'layerforge-tooltip';
|
||||||
position: fixed;
|
|
||||||
background-color: #1a1a1a;
|
|
||||||
color: #ffffff;
|
|
||||||
padding: 8px 12px;
|
|
||||||
border-radius: 6px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-family: sans-serif;
|
|
||||||
line-height: 1.4;
|
|
||||||
max-width: 250px;
|
|
||||||
word-wrap: break-word;
|
|
||||||
box-shadow: 0 4px 12px rgba(0,0,0,0.6);
|
|
||||||
border: 1px solid #444;
|
|
||||||
z-index: 10000;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.2s ease-in-out;
|
|
||||||
`;
|
|
||||||
document.body.appendChild(this.tooltip);
|
document.body.appendChild(this.tooltip);
|
||||||
this.updateTooltipPosition(event);
|
this.updateTooltipPosition(event);
|
||||||
// Fade in the tooltip
|
// Fade in the tooltip
|
||||||
|
|||||||
95
js/css/custom_shape_menu.css
Normal file
95
js/css/custom_shape_menu.css
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#layerforge-custom-shape-menu {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background-color: #333;
|
||||||
|
color: white;
|
||||||
|
padding: 8px 15px;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 4px 15px rgba(0,0,0,0.5);
|
||||||
|
display: none;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
z-index: 1001;
|
||||||
|
border: 1px solid #555;
|
||||||
|
user-select: none;
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .menu-line {
|
||||||
|
margin: 2px 0;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .feature-container {
|
||||||
|
background-color: #282828;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-top: 6px;
|
||||||
|
padding: 4px 0;
|
||||||
|
border: 1px solid #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .slider-container {
|
||||||
|
margin: 0 8px 6px 8px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .slider-label {
|
||||||
|
font-size: 11px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu input[type="range"] {
|
||||||
|
width: 100%;
|
||||||
|
height: 4px;
|
||||||
|
background: #555;
|
||||||
|
outline: none;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .slider-value-display {
|
||||||
|
font-size: 10px;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 2px;
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .extension-slider-container {
|
||||||
|
margin: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .checkbox-container {
|
||||||
|
margin: 6px 0 2px 0;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .checkbox-container:hover {
|
||||||
|
background-color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layerforge-tooltip {
|
||||||
|
position: fixed;
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
line-height: 1.4;
|
||||||
|
max-width: 250px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.6);
|
||||||
|
border: 1px solid #444;
|
||||||
|
z-index: 10000;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s ease-in-out;
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import {createModuleLogger} from "./utils/LoggerUtils.js";
|
import {createModuleLogger} from "./utils/LoggerUtils.js";
|
||||||
|
import { addStylesheet, getUrl } from "./utils/ResourceManager.js";
|
||||||
import type { Canvas } from './Canvas';
|
import type { Canvas } from './Canvas';
|
||||||
|
|
||||||
const log = createModuleLogger('CustomShapeMenu');
|
const log = createModuleLogger('CustomShapeMenu');
|
||||||
@@ -61,27 +62,10 @@ export class CustomShapeMenu {
|
|||||||
private _createUI(): void {
|
private _createUI(): void {
|
||||||
if (this.uiInitialized) return;
|
if (this.uiInitialized) return;
|
||||||
|
|
||||||
|
addStylesheet(getUrl('./css/custom_shape_menu.css'));
|
||||||
|
|
||||||
this.element = document.createElement('div');
|
this.element = document.createElement('div');
|
||||||
this.element.id = 'layerforge-custom-shape-menu';
|
this.element.id = 'layerforge-custom-shape-menu';
|
||||||
this.element.style.cssText = `
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
background-color: #333;
|
|
||||||
color: white;
|
|
||||||
padding: 8px 15px;
|
|
||||||
border-radius: 10px;
|
|
||||||
box-shadow: 0 4px 15px rgba(0,0,0,0.5);
|
|
||||||
display: none;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
font-family: sans-serif;
|
|
||||||
font-size: 12px;
|
|
||||||
z-index: 1001;
|
|
||||||
border: 1px solid #555;
|
|
||||||
user-select: none;
|
|
||||||
min-width: 200px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Create menu content
|
// Create menu content
|
||||||
const lines = [
|
const lines = [
|
||||||
@@ -91,23 +75,14 @@ export class CustomShapeMenu {
|
|||||||
lines.forEach(line => {
|
lines.forEach(line => {
|
||||||
const lineElement = document.createElement('div');
|
const lineElement = document.createElement('div');
|
||||||
lineElement.textContent = line;
|
lineElement.textContent = line;
|
||||||
lineElement.style.cssText = `
|
lineElement.className = 'menu-line';
|
||||||
margin: 2px 0;
|
|
||||||
line-height: 18px;
|
|
||||||
`;
|
|
||||||
this.element!.appendChild(lineElement);
|
this.element!.appendChild(lineElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a container for the entire shape mask feature set
|
// Create a container for the entire shape mask feature set
|
||||||
const featureContainer = document.createElement('div');
|
const featureContainer = document.createElement('div');
|
||||||
featureContainer.id = 'shape-mask-feature-container';
|
featureContainer.id = 'shape-mask-feature-container';
|
||||||
featureContainer.style.cssText = `
|
featureContainer.className = 'feature-container';
|
||||||
background-color: #282828;
|
|
||||||
border-radius: 6px;
|
|
||||||
margin-top: 6px;
|
|
||||||
padding: 4px 0;
|
|
||||||
border: 1px solid #444;
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Add main auto-apply checkbox to the new container
|
// Add main auto-apply checkbox to the new container
|
||||||
const checkboxContainer = this._createCheckbox(
|
const checkboxContainer = this._createCheckbox(
|
||||||
@@ -156,40 +131,20 @@ export class CustomShapeMenu {
|
|||||||
// Add expansion slider container
|
// Add expansion slider container
|
||||||
const expansionSliderContainer = document.createElement('div');
|
const expansionSliderContainer = document.createElement('div');
|
||||||
expansionSliderContainer.id = 'expansion-slider-container';
|
expansionSliderContainer.id = 'expansion-slider-container';
|
||||||
expansionSliderContainer.style.cssText = `
|
expansionSliderContainer.className = 'slider-container';
|
||||||
margin: 0 8px 6px 8px;
|
|
||||||
padding: 4px 8px;
|
|
||||||
display: none;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const expansionSliderLabel = document.createElement('div');
|
const expansionSliderLabel = document.createElement('div');
|
||||||
expansionSliderLabel.textContent = 'Expansion amount:';
|
expansionSliderLabel.textContent = 'Expansion amount:';
|
||||||
expansionSliderLabel.style.cssText = `
|
expansionSliderLabel.className = 'slider-label';
|
||||||
font-size: 11px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
color: #ccc;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const expansionSlider = document.createElement('input');
|
const expansionSlider = document.createElement('input');
|
||||||
expansionSlider.type = 'range';
|
expansionSlider.type = 'range';
|
||||||
expansionSlider.min = '-300';
|
expansionSlider.min = '-300';
|
||||||
expansionSlider.max = '300';
|
expansionSlider.max = '300';
|
||||||
expansionSlider.value = String(this.canvas.shapeMaskExpansionValue);
|
expansionSlider.value = String(this.canvas.shapeMaskExpansionValue);
|
||||||
expansionSlider.style.cssText = `
|
|
||||||
width: 100%;
|
|
||||||
height: 4px;
|
|
||||||
background: #555;
|
|
||||||
outline: none;
|
|
||||||
border-radius: 2px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const expansionValueDisplay = document.createElement('div');
|
const expansionValueDisplay = document.createElement('div');
|
||||||
expansionValueDisplay.style.cssText = `
|
expansionValueDisplay.className = 'slider-value-display';
|
||||||
font-size: 10px;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 2px;
|
|
||||||
color: #aaa;
|
|
||||||
`;
|
|
||||||
|
|
||||||
let expansionValueBeforeDrag = this.canvas.shapeMaskExpansionValue;
|
let expansionValueBeforeDrag = this.canvas.shapeMaskExpansionValue;
|
||||||
|
|
||||||
@@ -269,40 +224,20 @@ export class CustomShapeMenu {
|
|||||||
// Add feather slider container
|
// Add feather slider container
|
||||||
const featherSliderContainer = document.createElement('div');
|
const featherSliderContainer = document.createElement('div');
|
||||||
featherSliderContainer.id = 'feather-slider-container';
|
featherSliderContainer.id = 'feather-slider-container';
|
||||||
featherSliderContainer.style.cssText = `
|
featherSliderContainer.className = 'slider-container';
|
||||||
margin: 0 8px 6px 8px;
|
|
||||||
padding: 4px 8px;
|
|
||||||
display: none;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const featherSliderLabel = document.createElement('div');
|
const featherSliderLabel = document.createElement('div');
|
||||||
featherSliderLabel.textContent = 'Feather amount:';
|
featherSliderLabel.textContent = 'Feather amount:';
|
||||||
featherSliderLabel.style.cssText = `
|
featherSliderLabel.className = 'slider-label';
|
||||||
font-size: 11px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
color: #ccc;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const featherSlider = document.createElement('input');
|
const featherSlider = document.createElement('input');
|
||||||
featherSlider.type = 'range';
|
featherSlider.type = 'range';
|
||||||
featherSlider.min = '0';
|
featherSlider.min = '0';
|
||||||
featherSlider.max = '300';
|
featherSlider.max = '300';
|
||||||
featherSlider.value = String(this.canvas.shapeMaskFeatherValue);
|
featherSlider.value = String(this.canvas.shapeMaskFeatherValue);
|
||||||
featherSlider.style.cssText = `
|
|
||||||
width: 100%;
|
|
||||||
height: 4px;
|
|
||||||
background: #555;
|
|
||||||
outline: none;
|
|
||||||
border-radius: 2px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const featherValueDisplay = document.createElement('div');
|
const featherValueDisplay = document.createElement('div');
|
||||||
featherValueDisplay.style.cssText = `
|
featherValueDisplay.className = 'slider-value-display';
|
||||||
font-size: 10px;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 2px;
|
|
||||||
color: #aaa;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const updateFeatherSliderDisplay = () => {
|
const updateFeatherSliderDisplay = () => {
|
||||||
const value = parseInt(featherSlider.value);
|
const value = parseInt(featherSlider.value);
|
||||||
@@ -349,13 +284,7 @@ export class CustomShapeMenu {
|
|||||||
// Create output area extension container
|
// Create output area extension container
|
||||||
const extensionContainer = document.createElement('div');
|
const extensionContainer = document.createElement('div');
|
||||||
extensionContainer.id = 'output-area-extension-container';
|
extensionContainer.id = 'output-area-extension-container';
|
||||||
extensionContainer.style.cssText = `
|
extensionContainer.className = 'feature-container';
|
||||||
background-color: #282828;
|
|
||||||
border-radius: 6px;
|
|
||||||
margin-top: 6px;
|
|
||||||
padding: 4px 0;
|
|
||||||
border: 1px solid #444;
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Add main extension checkbox
|
// Add main extension checkbox
|
||||||
const extensionCheckboxContainer = this._createCheckbox(
|
const extensionCheckboxContainer = this._createCheckbox(
|
||||||
@@ -393,47 +322,25 @@ export class CustomShapeMenu {
|
|||||||
// Create sliders container
|
// Create sliders container
|
||||||
const slidersContainer = document.createElement('div');
|
const slidersContainer = document.createElement('div');
|
||||||
slidersContainer.id = 'extension-sliders-container';
|
slidersContainer.id = 'extension-sliders-container';
|
||||||
slidersContainer.style.cssText = `
|
slidersContainer.className = 'slider-container';
|
||||||
margin: 0 8px 6px 8px;
|
|
||||||
padding: 4px 8px;
|
|
||||||
display: none;
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Helper function to create a slider with preview system
|
// Helper function to create a slider with preview system
|
||||||
const createExtensionSlider = (label: string, direction: 'top' | 'bottom' | 'left' | 'right') => {
|
const createExtensionSlider = (label: string, direction: 'top' | 'bottom' | 'left' | 'right') => {
|
||||||
const sliderContainer = document.createElement('div');
|
const sliderContainer = document.createElement('div');
|
||||||
sliderContainer.style.cssText = `
|
sliderContainer.className = 'extension-slider-container';
|
||||||
margin: 6px 0;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const sliderLabel = document.createElement('div');
|
const sliderLabel = document.createElement('div');
|
||||||
sliderLabel.textContent = label;
|
sliderLabel.textContent = label;
|
||||||
sliderLabel.style.cssText = `
|
sliderLabel.className = 'slider-label';
|
||||||
font-size: 11px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
color: #ccc;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const slider = document.createElement('input');
|
const slider = document.createElement('input');
|
||||||
slider.type = 'range';
|
slider.type = 'range';
|
||||||
slider.min = '0';
|
slider.min = '0';
|
||||||
slider.max = '500';
|
slider.max = '500';
|
||||||
slider.value = String(this.canvas.outputAreaExtensions[direction]);
|
slider.value = String(this.canvas.outputAreaExtensions[direction]);
|
||||||
slider.style.cssText = `
|
|
||||||
width: 100%;
|
|
||||||
height: 4px;
|
|
||||||
background: #555;
|
|
||||||
outline: none;
|
|
||||||
border-radius: 2px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const valueDisplay = document.createElement('div');
|
const valueDisplay = document.createElement('div');
|
||||||
valueDisplay.style.cssText = `
|
valueDisplay.className = 'slider-value-display';
|
||||||
font-size: 10px;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 2px;
|
|
||||||
color: #aaa;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const updateDisplay = () => {
|
const updateDisplay = () => {
|
||||||
const value = parseInt(slider.value);
|
const value = parseInt(slider.value);
|
||||||
@@ -519,14 +426,7 @@ export class CustomShapeMenu {
|
|||||||
|
|
||||||
private _createCheckbox(textFn: () => string, clickHandler: () => void, tooltipText?: string): HTMLDivElement {
|
private _createCheckbox(textFn: () => string, clickHandler: () => void, tooltipText?: string): HTMLDivElement {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.style.cssText = `
|
container.className = 'checkbox-container';
|
||||||
margin: 6px 0 2px 0;
|
|
||||||
padding: 4px 8px;
|
|
||||||
border-radius: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color 0.2s;
|
|
||||||
line-height: 18px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
container.onmouseover = () => {
|
container.onmouseover = () => {
|
||||||
container.style.backgroundColor = '#555';
|
container.style.backgroundColor = '#555';
|
||||||
@@ -690,24 +590,7 @@ export class CustomShapeMenu {
|
|||||||
|
|
||||||
this.tooltip = document.createElement('div');
|
this.tooltip = document.createElement('div');
|
||||||
this.tooltip.textContent = text;
|
this.tooltip.textContent = text;
|
||||||
this.tooltip.style.cssText = `
|
this.tooltip.className = 'layerforge-tooltip';
|
||||||
position: fixed;
|
|
||||||
background-color: #1a1a1a;
|
|
||||||
color: #ffffff;
|
|
||||||
padding: 8px 12px;
|
|
||||||
border-radius: 6px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-family: sans-serif;
|
|
||||||
line-height: 1.4;
|
|
||||||
max-width: 250px;
|
|
||||||
word-wrap: break-word;
|
|
||||||
box-shadow: 0 4px 12px rgba(0,0,0,0.6);
|
|
||||||
border: 1px solid #444;
|
|
||||||
z-index: 10000;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.2s ease-in-out;
|
|
||||||
`;
|
|
||||||
|
|
||||||
document.body.appendChild(this.tooltip);
|
document.body.appendChild(this.tooltip);
|
||||||
this.updateTooltipPosition(event);
|
this.updateTooltipPosition(event);
|
||||||
|
|||||||
95
src/css/custom_shape_menu.css
Normal file
95
src/css/custom_shape_menu.css
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#layerforge-custom-shape-menu {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background-color: #333;
|
||||||
|
color: white;
|
||||||
|
padding: 8px 15px;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 4px 15px rgba(0,0,0,0.5);
|
||||||
|
display: none;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
z-index: 1001;
|
||||||
|
border: 1px solid #555;
|
||||||
|
user-select: none;
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .menu-line {
|
||||||
|
margin: 2px 0;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .feature-container {
|
||||||
|
background-color: #282828;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-top: 6px;
|
||||||
|
padding: 4px 0;
|
||||||
|
border: 1px solid #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .slider-container {
|
||||||
|
margin: 0 8px 6px 8px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .slider-label {
|
||||||
|
font-size: 11px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu input[type="range"] {
|
||||||
|
width: 100%;
|
||||||
|
height: 4px;
|
||||||
|
background: #555;
|
||||||
|
outline: none;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .slider-value-display {
|
||||||
|
font-size: 10px;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 2px;
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .extension-slider-container {
|
||||||
|
margin: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .checkbox-container {
|
||||||
|
margin: 6px 0 2px 0;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layerforge-custom-shape-menu .checkbox-container:hover {
|
||||||
|
background-color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layerforge-tooltip {
|
||||||
|
position: fixed;
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
line-height: 1.4;
|
||||||
|
max-width: 250px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.6);
|
||||||
|
border: 1px solid #444;
|
||||||
|
z-index: 10000;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s ease-in-out;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user