beam: add zoom speed control
This commit is contained in:
parent
1569ed9c23
commit
6d65b2ba41
|
|
@ -604,24 +604,32 @@ header {
|
||||||
|
|
||||||
.inspector-controls {
|
.inspector-controls {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inspector-control-row {
|
.inspector-control-row {
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-columns: minmax(0, 0.86fr) minmax(0, 1.14fr);
|
min-width: 0;
|
||||||
gap: 10px;
|
flex-direction: column;
|
||||||
align-items: center;
|
gap: 6px;
|
||||||
min-height: 42px;
|
}
|
||||||
|
|
||||||
|
.inspector-control-row--full {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inspector-control-row--slider {
|
||||||
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inspector-control-label {
|
.inspector-control-label {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
font-size: 12px;
|
font-size: 11px;
|
||||||
font-weight: 760;
|
font-weight: 760;
|
||||||
line-height: 1.15;
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inspector-select-host {
|
.inspector-select-host {
|
||||||
|
|
@ -636,7 +644,7 @@ header {
|
||||||
|
|
||||||
.nodedc-select__control {
|
.nodedc-select__control {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1fr) 42px;
|
grid-template-columns: minmax(0, 1fr) 40px;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
@ -644,7 +652,7 @@ header {
|
||||||
|
|
||||||
.nodedc-select__value,
|
.nodedc-select__value,
|
||||||
.nodedc-select__toggle {
|
.nodedc-select__toggle {
|
||||||
height: 42px;
|
height: 40px;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
background: var(--nodedc-glass-control-bg);
|
background: var(--nodedc-glass-control-bg);
|
||||||
|
|
@ -668,6 +676,20 @@ header {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inspector-control-row--half .nodedc-select__control {
|
||||||
|
grid-template-columns: minmax(0, 1fr) 36px;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inspector-control-row--half .nodedc-select__value,
|
||||||
|
.inspector-control-row--half .nodedc-select__toggle {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inspector-control-row--half .nodedc-select__value {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.nodedc-select__toggle {
|
.nodedc-select__toggle {
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
|
|
@ -1106,6 +1128,13 @@ header {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.slider-value {
|
||||||
|
color: var(--text);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 760;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.slider-input {
|
.slider-input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
|
@ -1137,6 +1166,61 @@ header {
|
||||||
box-shadow: 0 0 6px rgba(0, 0, 0, 0.25);
|
box-shadow: 0 0 6px rgba(0, 0, 0, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inspector-slider.slider-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
|
grid-template-areas:
|
||||||
|
"label value"
|
||||||
|
"input input";
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inspector-slider .slider-label {
|
||||||
|
grid-area: label;
|
||||||
|
min-width: 0;
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 760;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inspector-slider .slider-value {
|
||||||
|
grid-area: value;
|
||||||
|
min-width: 38px;
|
||||||
|
color: rgba(245, 245, 250, 0.82);
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inspector-slider .slider-input {
|
||||||
|
grid-area: input;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 14px;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
var(--modal-btn-primary, var(--accent)) var(--slider-percent, 0%),
|
||||||
|
var(--nodedc-glass-control-bg) var(--slider-percent, 0%)
|
||||||
|
);
|
||||||
|
box-shadow: var(--nodedc-glass-control-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.inspector-slider .slider-input::-webkit-slider-thumb {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background: var(--modal-btn-primary, var(--accent));
|
||||||
|
border: 0;
|
||||||
|
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.32);
|
||||||
|
}
|
||||||
|
|
||||||
|
.inspector-slider .slider-input::-moz-range-thumb {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background: var(--modal-btn-primary, var(--accent));
|
||||||
|
border: 0;
|
||||||
|
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.32);
|
||||||
|
}
|
||||||
|
|
||||||
.settings-panel input[type="color"] {
|
.settings-panel input[type="color"] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 26px;
|
height: 26px;
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { createTemplatesMenu } from "./src/ui/templatesMenu.js";
|
||||||
import { createSettingsMenu } from "./src/ui/settingsMenu.js";
|
import { createSettingsMenu } from "./src/ui/settingsMenu.js";
|
||||||
import { createMeasurementModal } from "./src/ui/measurementModal.js";
|
import { createMeasurementModal } from "./src/ui/measurementModal.js";
|
||||||
import { createGlassSelect } from "./src/ui/glassSelect.js";
|
import { createGlassSelect } from "./src/ui/glassSelect.js";
|
||||||
|
import { createSliderControl } from "./src/ui/controls/slider.js";
|
||||||
import "./theme.js";
|
import "./theme.js";
|
||||||
import { TransformGizmo } from "./transformGizmo.js";
|
import { TransformGizmo } from "./transformGizmo.js";
|
||||||
import { createObjectModal } from "./src/ui/objectModal.js";
|
import { createObjectModal } from "./src/ui/objectModal.js";
|
||||||
|
|
@ -42,6 +43,7 @@ const lightingModeControl = document.getElementById("lightingModeControl");
|
||||||
const lightingModeSelectHost = document.getElementById("lightingModeSelect");
|
const lightingModeSelectHost = document.getElementById("lightingModeSelect");
|
||||||
const navigationAxisControl = document.getElementById("navigationAxisControl");
|
const navigationAxisControl = document.getElementById("navigationAxisControl");
|
||||||
const navigationAxisSelectHost = document.getElementById("navigationAxisSelect");
|
const navigationAxisSelectHost = document.getElementById("navigationAxisSelect");
|
||||||
|
const zoomSpeedControl = document.getElementById("zoomSpeedControl");
|
||||||
const logList = document.getElementById("logList");
|
const logList = document.getElementById("logList");
|
||||||
const loaderEl = document.getElementById("loader");
|
const loaderEl = document.getElementById("loader");
|
||||||
const navCubeCanvas = document.getElementById("navCube");
|
const navCubeCanvas = document.getElementById("navCube");
|
||||||
|
|
@ -216,9 +218,11 @@ const sceneModels = {}; // modelId -> SceneModel
|
||||||
let activeDisplayMode = "source";
|
let activeDisplayMode = "source";
|
||||||
let activeLightingMode = "ambient";
|
let activeLightingMode = "ambient";
|
||||||
let activeNavigationAxis = "auto";
|
let activeNavigationAxis = "auto";
|
||||||
|
let activeZoomSpeed = 20;
|
||||||
let displayModeSelect = null;
|
let displayModeSelect = null;
|
||||||
let lightingModeSelect = null;
|
let lightingModeSelect = null;
|
||||||
let navigationAxisSelect = null;
|
let navigationAxisSelect = null;
|
||||||
|
let zoomSpeedSlider = null;
|
||||||
let defaultCameraWorldAxis = null;
|
let defaultCameraWorldAxis = null;
|
||||||
let defaultCameraUp = null;
|
let defaultCameraUp = null;
|
||||||
let currentSelection = null; // { modelId, objectId }
|
let currentSelection = null; // { modelId, objectId }
|
||||||
|
|
@ -244,27 +248,42 @@ const treeModelIds = new Set();
|
||||||
|
|
||||||
const CAMERA_CONTROL_SETTINGS = {
|
const CAMERA_CONTROL_SETTINGS = {
|
||||||
keyboardDollyRate: 45,
|
keyboardDollyRate: 45,
|
||||||
mouseWheelDollyRate: 20,
|
|
||||||
dollyInertia: 0,
|
dollyInertia: 0,
|
||||||
dollyMinSpeed: 0.008,
|
dollyMinSpeed: 0.008,
|
||||||
dollyProximityThreshold: 90,
|
dollyProximityThreshold: 90,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const normalizeZoomSpeed = (value) => {
|
||||||
|
const numeric = Number(value);
|
||||||
|
if (!Number.isFinite(numeric)) return 20;
|
||||||
|
return Math.min(100, Math.max(5, Math.round(numeric)));
|
||||||
|
};
|
||||||
|
|
||||||
const configureCameraControl = () => {
|
const configureCameraControl = () => {
|
||||||
const control = viewer?.cameraControl;
|
const control = viewer?.cameraControl;
|
||||||
if (!control) return;
|
if (!control) return;
|
||||||
|
activeZoomSpeed = normalizeZoomSpeed(activeZoomSpeed);
|
||||||
control.panRightClick = false;
|
control.panRightClick = false;
|
||||||
control.followPointer = true;
|
control.followPointer = true;
|
||||||
control.doublePickFlyTo = false;
|
control.doublePickFlyTo = false;
|
||||||
control.smartPivot = true;
|
control.smartPivot = true;
|
||||||
control.zoomOnMouseWheel = true;
|
control.zoomOnMouseWheel = true;
|
||||||
control.keyboardDollyRate = CAMERA_CONTROL_SETTINGS.keyboardDollyRate;
|
control.keyboardDollyRate = CAMERA_CONTROL_SETTINGS.keyboardDollyRate;
|
||||||
control.mouseWheelDollyRate = CAMERA_CONTROL_SETTINGS.mouseWheelDollyRate;
|
control.mouseWheelDollyRate = activeZoomSpeed;
|
||||||
control.dollyInertia = CAMERA_CONTROL_SETTINGS.dollyInertia;
|
control.dollyInertia = CAMERA_CONTROL_SETTINGS.dollyInertia;
|
||||||
control.dollyMinSpeed = CAMERA_CONTROL_SETTINGS.dollyMinSpeed;
|
control.dollyMinSpeed = CAMERA_CONTROL_SETTINGS.dollyMinSpeed;
|
||||||
control.dollyProximityThreshold = CAMERA_CONTROL_SETTINGS.dollyProximityThreshold;
|
control.dollyProximityThreshold = CAMERA_CONTROL_SETTINGS.dollyProximityThreshold;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setZoomSpeed = (value, { announce = false } = {}) => {
|
||||||
|
activeZoomSpeed = normalizeZoomSpeed(value);
|
||||||
|
zoomSpeedSlider?.setValue?.(activeZoomSpeed);
|
||||||
|
configureCameraControl();
|
||||||
|
if (announce) {
|
||||||
|
setStatus(`Скорость зума: ${activeZoomSpeed}%`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const ensureCameraControlActive = () => {
|
const ensureCameraControlActive = () => {
|
||||||
if (!viewer || !viewer.cameraControl) return;
|
if (!viewer || !viewer.cameraControl) return;
|
||||||
configureCameraControl();
|
configureCameraControl();
|
||||||
|
|
@ -2205,6 +2224,7 @@ const buildProjectSnapshot = async (name) => {
|
||||||
displayMode: activeDisplayMode,
|
displayMode: activeDisplayMode,
|
||||||
lightingMode: activeLightingMode,
|
lightingMode: activeLightingMode,
|
||||||
navigationAxis: activeNavigationAxis,
|
navigationAxis: activeNavigationAxis,
|
||||||
|
zoomSpeed: activeZoomSpeed,
|
||||||
selection: {
|
selection: {
|
||||||
ids: lastSelection.ids || [],
|
ids: lastSelection.ids || [],
|
||||||
modelId: lastSelection.modelId || null,
|
modelId: lastSelection.modelId || null,
|
||||||
|
|
@ -2267,7 +2287,8 @@ const buildModelViewerSettings = () => ({
|
||||||
edges: !!toggleEdges?.checked,
|
edges: !!toggleEdges?.checked,
|
||||||
displayMode: activeDisplayMode,
|
displayMode: activeDisplayMode,
|
||||||
lightingMode: activeLightingMode,
|
lightingMode: activeLightingMode,
|
||||||
navigationAxis: activeNavigationAxis
|
navigationAxis: activeNavigationAxis,
|
||||||
|
zoomSpeed: activeZoomSpeed
|
||||||
} : {},
|
} : {},
|
||||||
design: settingsMenu?.getState ? settingsMenu.getState() : {}
|
design: settingsMenu?.getState ? settingsMenu.getState() : {}
|
||||||
});
|
});
|
||||||
|
|
@ -2307,6 +2328,9 @@ const applyModelViewerSettings = (settings, { applyCamera = true, applyDesign =
|
||||||
activeNavigationAxis = viewerState.navigationAxis;
|
activeNavigationAxis = viewerState.navigationAxis;
|
||||||
applyNavigationAxis({ resetAuto: false });
|
applyNavigationAxis({ resetAuto: false });
|
||||||
}
|
}
|
||||||
|
if (viewerState.zoomSpeed !== undefined) {
|
||||||
|
setZoomSpeed(viewerState.zoomSpeed);
|
||||||
|
}
|
||||||
if (applyCamera) {
|
if (applyCamera) {
|
||||||
applyCameraSnapshot(viewerState.camera);
|
applyCameraSnapshot(viewerState.camera);
|
||||||
}
|
}
|
||||||
|
|
@ -2391,6 +2415,9 @@ const applyViewerState = (state) => {
|
||||||
activeNavigationAxis = state.navigationAxis;
|
activeNavigationAxis = state.navigationAxis;
|
||||||
applyNavigationAxis({ resetAuto: false });
|
applyNavigationAxis({ resetAuto: false });
|
||||||
}
|
}
|
||||||
|
if (state.zoomSpeed !== undefined) {
|
||||||
|
setZoomSpeed(state.zoomSpeed);
|
||||||
|
}
|
||||||
if (state.transforms && typeof state.transforms === "object") {
|
if (state.transforms && typeof state.transforms === "object") {
|
||||||
Object.keys(transformStore).forEach((k) => delete transformStore[k]);
|
Object.keys(transformStore).forEach((k) => delete transformStore[k]);
|
||||||
Object.assign(transformStore, safeClone(state.transforms));
|
Object.assign(transformStore, safeClone(state.transforms));
|
||||||
|
|
@ -2971,6 +2998,9 @@ const initViewer = async () => {
|
||||||
activeNavigationAxis = params.get("navigationAxis") || params.get("axis") || "auto";
|
activeNavigationAxis = params.get("navigationAxis") || params.get("axis") || "auto";
|
||||||
applyNavigationAxis({ resetAuto: false });
|
applyNavigationAxis({ resetAuto: false });
|
||||||
}
|
}
|
||||||
|
if (params.has("zoomSpeed")) {
|
||||||
|
setZoomSpeed(params.get("zoomSpeed"));
|
||||||
|
}
|
||||||
|
|
||||||
if (modelSettings?.viewerState) {
|
if (modelSettings?.viewerState) {
|
||||||
modelSettings = {
|
modelSettings = {
|
||||||
|
|
@ -2980,6 +3010,7 @@ const initViewer = async () => {
|
||||||
displayMode: activeDisplayMode,
|
displayMode: activeDisplayMode,
|
||||||
lightingMode: activeLightingMode,
|
lightingMode: activeLightingMode,
|
||||||
navigationAxis: activeNavigationAxis,
|
navigationAxis: activeNavigationAxis,
|
||||||
|
zoomSpeed: activeZoomSpeed,
|
||||||
edges: params.has("edges") ? params.get("edges") !== "false" : modelSettings.viewerState.edges
|
edges: params.has("edges") ? params.get("edges") !== "false" : modelSettings.viewerState.edges
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -3327,6 +3358,22 @@ const loadProjectSnapshot = async (project) => {
|
||||||
});
|
});
|
||||||
setNavigationAxisControlState();
|
setNavigationAxisControlState();
|
||||||
}
|
}
|
||||||
|
if (zoomSpeedControl) {
|
||||||
|
zoomSpeedSlider = createSliderControl({
|
||||||
|
label: "Скорость зума",
|
||||||
|
value: activeZoomSpeed,
|
||||||
|
min: 5,
|
||||||
|
max: 100,
|
||||||
|
step: 1,
|
||||||
|
className: "inspector-slider",
|
||||||
|
showValue: true,
|
||||||
|
formatValue: (value) => `${Math.round(value)}%`,
|
||||||
|
onChange: (value) => {
|
||||||
|
setZoomSpeed(value);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
zoomSpeedControl.replaceChildren(zoomSpeedSlider);
|
||||||
|
}
|
||||||
loadProjectsList().catch(() => {
|
loadProjectsList().catch(() => {
|
||||||
templatesMenu?.setData({ templates: templateFallbacks, projects: [], error: "API недоступно" });
|
templatesMenu?.setData({ templates: templateFallbacks, projects: [], error: "API недоступно" });
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@500;600;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@500;600;700&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="./dcViewer.css?v=6">
|
<link rel="stylesheet" href="./dcViewer.css?v=7">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
|
|
@ -129,18 +129,19 @@
|
||||||
<h3>Инспектор</h3>
|
<h3>Инспектор</h3>
|
||||||
<div id="treeContainer" class="tree"></div>
|
<div id="treeContainer" class="tree"></div>
|
||||||
<div class="inspector-controls">
|
<div class="inspector-controls">
|
||||||
<div class="inspector-control-row" id="displayModeControl">
|
<div class="inspector-control-row inspector-control-row--half" id="displayModeControl">
|
||||||
<div class="inspector-control-label">Режим отображения</div>
|
<div class="inspector-control-label">Режим отображения</div>
|
||||||
<div class="inspector-select-host" id="displayModeSelect"></div>
|
<div class="inspector-select-host" id="displayModeSelect"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="inspector-control-row" id="lightingModeControl">
|
<div class="inspector-control-row inspector-control-row--half" id="lightingModeControl">
|
||||||
<div class="inspector-control-label">Свет</div>
|
<div class="inspector-control-label">Свет</div>
|
||||||
<div class="inspector-select-host" id="lightingModeSelect"></div>
|
<div class="inspector-select-host" id="lightingModeSelect"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="inspector-control-row" id="navigationAxisControl">
|
<div class="inspector-control-row inspector-control-row--full" id="navigationAxisControl">
|
||||||
<div class="inspector-control-label">Ось навигации</div>
|
<div class="inspector-control-label">Ось навигации</div>
|
||||||
<div class="inspector-select-host" id="navigationAxisSelect"></div>
|
<div class="inspector-select-host" id="navigationAxisSelect"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="inspector-control-row inspector-control-row--full inspector-control-row--slider" id="zoomSpeedControl"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-section" id="projectNameSection">
|
<div class="panel-section" id="projectNameSection">
|
||||||
|
|
@ -238,6 +239,6 @@
|
||||||
<input id="fileInput" class="hidden" type="file"
|
<input id="fileInput" class="hidden" type="file"
|
||||||
accept=".xkt,.glb,.gltf,.bim,.las,.laz,.obj,.stl">
|
accept=".xkt,.glb,.gltf,.bim,.las,.laz,.obj,.stl">
|
||||||
|
|
||||||
<script type="module" src="./dcViewer.js?v=6"></script>
|
<script type="module" src="./dcViewer.js?v=7"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,16 @@
|
||||||
export function createSliderControl({ label = "", value = 0, min = 0, max = 100, step = 1, onChange }) {
|
export function createSliderControl({
|
||||||
|
label = "",
|
||||||
|
value = 0,
|
||||||
|
min = 0,
|
||||||
|
max = 100,
|
||||||
|
step = 1,
|
||||||
|
className = "",
|
||||||
|
showValue = false,
|
||||||
|
formatValue = (val) => String(val),
|
||||||
|
onChange
|
||||||
|
}) {
|
||||||
const row = document.createElement("div");
|
const row = document.createElement("div");
|
||||||
row.className = "slider-row";
|
row.className = ["slider-row", className].filter(Boolean).join(" ");
|
||||||
|
|
||||||
const lbl = document.createElement("label");
|
const lbl = document.createElement("label");
|
||||||
lbl.textContent = label;
|
lbl.textContent = label;
|
||||||
|
|
@ -14,9 +24,15 @@ export function createSliderControl({ label = "", value = 0, min = 0, max = 100,
|
||||||
input.step = step;
|
input.step = step;
|
||||||
input.value = value;
|
input.value = value;
|
||||||
|
|
||||||
|
const valueEl = document.createElement("div");
|
||||||
|
valueEl.className = "slider-value";
|
||||||
|
|
||||||
const updateFill = () => {
|
const updateFill = () => {
|
||||||
const percent = ((input.value - input.min) / (input.max - input.min)) * 100;
|
const percent = ((input.value - input.min) / (input.max - input.min)) * 100;
|
||||||
input.style.setProperty("--slider-percent", `${percent}%`);
|
input.style.setProperty("--slider-percent", `${percent}%`);
|
||||||
|
if (showValue) {
|
||||||
|
valueEl.textContent = formatValue(Number(input.value));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
input.addEventListener("input", () => {
|
input.addEventListener("input", () => {
|
||||||
|
|
@ -29,5 +45,13 @@ export function createSliderControl({ label = "", value = 0, min = 0, max = 100,
|
||||||
|
|
||||||
row.appendChild(lbl);
|
row.appendChild(lbl);
|
||||||
row.appendChild(input);
|
row.appendChild(input);
|
||||||
|
if (showValue) {
|
||||||
|
row.appendChild(valueEl);
|
||||||
|
}
|
||||||
|
row.setValue = (nextValue) => {
|
||||||
|
input.value = nextValue;
|
||||||
|
updateFill();
|
||||||
|
};
|
||||||
|
row.getValue = () => Number(input.value);
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue