Add onboarding weather and template gradients
This commit is contained in:
1 parent
aa07a78912
commit
3960931ebe
80 files changed
+12750
-519
No files matched your search
@@ -33,6 +33,18 @@
|
||||
var canvasHeightInput = document.getElementById('canvas-height');
|
||||
var backgroundInput = document.getElementById('background-image');
|
||||
var backgroundColorInput = document.getElementById('background-color');
|
||||
var backgroundGradientEnabled = document.getElementById('background-gradient-enabled');
|
||||
var backgroundGradientInput = document.getElementById('background-gradient');
|
||||
var backgroundGradientOptions = document.getElementById('background-gradient-options');
|
||||
var backgroundGradientAngle = document.getElementById('background-gradient-angle');
|
||||
var backgroundGradientAngleOutput = document.getElementById('background-gradient-angle-output');
|
||||
var backgroundGradientBar = document.getElementById('background-gradient-bar');
|
||||
var backgroundGradientBarHandles = document.getElementById('background-gradient-bar-handles');
|
||||
var backgroundGradientStops = document.getElementById('background-gradient-stops');
|
||||
var backgroundGradientAddStop = document.getElementById('background-gradient-add-stop');
|
||||
var draggedGradientStopIndex = -1;
|
||||
var draggedGradientStopRow = null;
|
||||
var draggedGradientStopHandle = null;
|
||||
var backgroundPreview = document.getElementById('background-preview');
|
||||
var backgroundEmpty = document.getElementById('background-empty');
|
||||
var removeBackgroundButton = document.getElementById('remove-background-image');
|
||||
@@ -1117,6 +1129,65 @@
|
||||
return;
|
||||
}
|
||||
stage.style.backgroundColor = backgroundColorInput && backgroundColorInput.value ? backgroundColorInput.value : '#111111';
|
||||
if (backgroundGradientEnabled && backgroundGradientEnabled.checked) {
|
||||
var gradientStops = Array.prototype.map.call(backgroundGradientStops.querySelectorAll('[data-gradient-stop]'), function (stop) {
|
||||
return { color: stop.querySelector('[data-gradient-stop-color]').value, position: Number(stop.querySelector('[data-gradient-stop-position]').value || 0) };
|
||||
});
|
||||
var gradient = { type: 'linear', stops: gradientStops, angle: Number(backgroundGradientAngle.value || 90) };
|
||||
backgroundGradientInput.value = JSON.stringify(gradient);
|
||||
stage.style.backgroundImage = 'linear-gradient(' + gradient.angle + 'deg,' + gradient.stops.map(function (stop) { return stop.color + ' ' + stop.position + '%'; }).join(',') + ')';
|
||||
var gradientBarTrack = backgroundGradientBar && backgroundGradientBar.querySelector('.gradient-stop-bar-track');
|
||||
if (gradientBarTrack) gradientBarTrack.style.background = stage.style.backgroundImage;
|
||||
backgroundGradientOptions.hidden = false;
|
||||
} else {
|
||||
backgroundGradientInput.value = '';
|
||||
stage.style.backgroundImage = 'none';
|
||||
var emptyGradientBarTrack = backgroundGradientBar && backgroundGradientBar.querySelector('.gradient-stop-bar-track');
|
||||
if (emptyGradientBarTrack) emptyGradientBarTrack.style.background = 'var(--bs-secondary-bg)';
|
||||
backgroundGradientOptions.hidden = true;
|
||||
}
|
||||
if (backgroundGradientAngleOutput) backgroundGradientAngleOutput.value = String(backgroundGradientAngle.value || 90);
|
||||
}
|
||||
|
||||
function renderBackgroundGradientStops(stops) {
|
||||
if (!backgroundGradientStops) return;
|
||||
var normalizedStops = Array.isArray(stops) && stops.length >= 2 ? stops : [{ color: '#111111', position: 0 }, { color: '#334455', position: 100 }];
|
||||
if (backgroundGradientBarHandles) {
|
||||
backgroundGradientBarHandles.innerHTML = normalizedStops.map(function (stop, index) {
|
||||
return '<button type="button" class="gradient-stop-handle" data-gradient-bar-index="' + index + '" style="left:' + Math.max(0, Math.min(100, Number(stop.position) || 0)) + '%;background:' + escapeHtml(stop.color || '#111111') + ';" aria-label="Gradient stop ' + (index + 1) + '"></button>';
|
||||
}).join('');
|
||||
if (backgroundGradientBar) backgroundGradientBar.style.background = 'transparent';
|
||||
}
|
||||
backgroundGradientStops.innerHTML = normalizedStops.map(function (stop) {
|
||||
return '<div class="d-flex align-items-end gap-2" data-gradient-stop><label class="flex-grow-1">Colour<input type="color" class="form-control form-control-color w-100" data-gradient-stop-color value="' + escapeHtml(stop.color || '#111111') + '" /></label><label style="width:6rem">Position<input type="number" class="form-control" data-gradient-stop-position min="0" max="100" value="' + Math.max(0, Math.min(100, Number(stop.position) || 0)) + '" /></label><button type="button" class="btn btn-outline-danger" data-gradient-stop-remove aria-label="Remove colour stop">×</button></div>';
|
||||
}).join('');
|
||||
updateGradientStopRemoveButtons();
|
||||
}
|
||||
|
||||
function updateGradientStopRemoveButtons() {
|
||||
if (!backgroundGradientStops) return;
|
||||
var stops = backgroundGradientStops.querySelectorAll('[data-gradient-stop]');
|
||||
Array.prototype.forEach.call(stops, function (stop) { stop.querySelector('[data-gradient-stop-remove]').disabled = stops.length <= 2; });
|
||||
}
|
||||
|
||||
function syncBackgroundGradientBar() {
|
||||
if (!backgroundGradientStops || !backgroundGradientBarHandles) return;
|
||||
var rows = backgroundGradientStops.querySelectorAll('[data-gradient-stop]');
|
||||
if (backgroundGradientBarHandles.children.length !== rows.length) {
|
||||
backgroundGradientBarHandles.innerHTML = Array.prototype.map.call(rows, function (row, index) {
|
||||
var color = row.querySelector('[data-gradient-stop-color]').value || '#111111';
|
||||
var position = Math.max(0, Math.min(100, Number(row.querySelector('[data-gradient-stop-position]').value) || 0));
|
||||
return '<button type="button" class="gradient-stop-handle" data-gradient-bar-index="' + index + '" style="left:' + position + '%;background:' + escapeHtml(color) + ';" aria-label="Gradient stop ' + (index + 1) + '"></button>';
|
||||
}).join('');
|
||||
return;
|
||||
}
|
||||
Array.prototype.forEach.call(rows, function (row, index) {
|
||||
var handle = backgroundGradientBarHandles.children[index];
|
||||
if (!handle) return;
|
||||
handle.style.background = row.querySelector('[data-gradient-stop-color]').value || '#111111';
|
||||
handle.style.left = Math.max(0, Math.min(100, Number(row.querySelector('[data-gradient-stop-position]').value) || 0)) + '%';
|
||||
handle.setAttribute('data-gradient-bar-index', index);
|
||||
});
|
||||
}
|
||||
|
||||
function updateRegionLockBadge(card) {
|
||||
@@ -1757,6 +1828,79 @@
|
||||
if (backgroundColorInput) {
|
||||
backgroundColorInput.addEventListener('input', updateStageBackgroundColor);
|
||||
}
|
||||
if (backgroundGradientEnabled) backgroundGradientEnabled.addEventListener('change', updateStageBackgroundColor);
|
||||
if (backgroundGradientAddStop) backgroundGradientAddStop.addEventListener('click', function () {
|
||||
var stops = Array.prototype.map.call(backgroundGradientStops.querySelectorAll('[data-gradient-stop]'), function (stop) {
|
||||
return { color: stop.querySelector('[data-gradient-stop-color]').value, position: Number(stop.querySelector('[data-gradient-stop-position]').value || 0) };
|
||||
});
|
||||
stops.push({ color: '#ffffff', position: 100 });
|
||||
renderBackgroundGradientStops(stops);
|
||||
updateStageBackgroundColor();
|
||||
});
|
||||
if (backgroundGradientStops) backgroundGradientStops.addEventListener('input', function () {
|
||||
syncBackgroundGradientBar();
|
||||
updateStageBackgroundColor();
|
||||
});
|
||||
if (backgroundGradientStops) backgroundGradientStops.addEventListener('click', function (event) {
|
||||
var removeButton = event.target.closest('[data-gradient-stop-remove]');
|
||||
if (!removeButton || removeButton.disabled) return;
|
||||
removeButton.closest('[data-gradient-stop]').remove();
|
||||
updateGradientStopRemoveButtons();
|
||||
syncBackgroundGradientBar();
|
||||
updateStageBackgroundColor();
|
||||
});
|
||||
if (backgroundGradientBar) backgroundGradientBar.addEventListener('click', function (event) {
|
||||
if (event.target.closest('[data-gradient-bar-index]')) return;
|
||||
var rect = backgroundGradientBar.getBoundingClientRect();
|
||||
var position = Math.max(0, Math.min(100, Math.round(((event.clientX - rect.left) / rect.width) * 100)));
|
||||
var stops = Array.prototype.map.call(backgroundGradientStops.querySelectorAll('[data-gradient-stop]'), function (stop) { return { color: stop.querySelector('[data-gradient-stop-color]').value, position: Number(stop.querySelector('[data-gradient-stop-position]').value || 0) }; });
|
||||
stops.push({ color: '#ffffff', position: position });
|
||||
stops.sort(function (left, right) { return left.position - right.position; });
|
||||
renderBackgroundGradientStops(stops);
|
||||
updateStageBackgroundColor();
|
||||
});
|
||||
if (backgroundGradientBarHandles) backgroundGradientBarHandles.addEventListener('pointerdown', function (event) {
|
||||
var handle = event.target.closest('[data-gradient-bar-index]');
|
||||
if (!handle) return;
|
||||
draggedGradientStopIndex = Number(handle.getAttribute('data-gradient-bar-index'));
|
||||
draggedGradientStopRow = backgroundGradientStops.querySelectorAll('[data-gradient-stop]')[draggedGradientStopIndex] || null;
|
||||
draggedGradientStopHandle = handle;
|
||||
handle.classList.add('is-dragging');
|
||||
handle.setPointerCapture(event.pointerId);
|
||||
event.preventDefault();
|
||||
});
|
||||
document.addEventListener('pointermove', function (event) {
|
||||
if (draggedGradientStopIndex < 0) return;
|
||||
var rect = backgroundGradientBar.getBoundingClientRect();
|
||||
var position = Math.max(0, Math.min(100, Math.round(((event.clientX - rect.left) / rect.width) * 100)));
|
||||
if (draggedGradientStopRow) draggedGradientStopRow.querySelector('[data-gradient-stop-position]').value = position;
|
||||
if (draggedGradientStopHandle) draggedGradientStopHandle.style.left = position + '%';
|
||||
var entries = Array.prototype.map.call(backgroundGradientStops.querySelectorAll('[data-gradient-stop]'), function (row, index) {
|
||||
return { row: row, handle: backgroundGradientBarHandles.children[index], position: Number(row.querySelector('[data-gradient-stop-position]').value || 0), index: index };
|
||||
});
|
||||
entries.sort(function (left, right) { return left.position - right.position || left.index - right.index; });
|
||||
entries.forEach(function (entry, index) {
|
||||
backgroundGradientStops.appendChild(entry.row);
|
||||
backgroundGradientBarHandles.appendChild(entry.handle);
|
||||
entry.handle.setAttribute('data-gradient-bar-index', index);
|
||||
});
|
||||
draggedGradientStopIndex = entries.findIndex(function (entry) { return entry.row === draggedGradientStopRow; });
|
||||
updateStageBackgroundColor();
|
||||
});
|
||||
document.addEventListener('pointerup', function () {
|
||||
if (draggedGradientStopHandle) draggedGradientStopHandle.classList.remove('is-dragging');
|
||||
draggedGradientStopIndex = -1;
|
||||
draggedGradientStopRow = null;
|
||||
draggedGradientStopHandle = null;
|
||||
});
|
||||
document.addEventListener('pointercancel', function () {
|
||||
draggedGradientStopIndex = -1;
|
||||
draggedGradientStopRow = null;
|
||||
draggedGradientStopHandle = null;
|
||||
});
|
||||
[backgroundGradientAngle].forEach(function (input) {
|
||||
if (input) input.addEventListener('input', updateStageBackgroundColor);
|
||||
});
|
||||
canvasSizeSelect.addEventListener('change', function () { syncCanvasSizeSelection(); render(); });
|
||||
canvasWidthInput.addEventListener('input', render);
|
||||
canvasHeightInput.addEventListener('input', render);
|
||||
@@ -1858,6 +2002,19 @@
|
||||
});
|
||||
}
|
||||
|
||||
if (backgroundGradientInput && backgroundGradientInput.value) {
|
||||
try {
|
||||
var initialGradient = JSON.parse(backgroundGradientInput.value);
|
||||
if (initialGradient) {
|
||||
var initialStops = Array.isArray(initialGradient.stops) ? initialGradient.stops : (initialGradient.colors || []).map(function (color, index, colors) { return { color: color, position: colors.length > 1 ? Math.round(index * 100 / (colors.length - 1)) : 0 }; });
|
||||
renderBackgroundGradientStops(initialStops);
|
||||
if (backgroundGradientAngle && Number.isFinite(Number(initialGradient.angle))) backgroundGradientAngle.value = String(Math.max(0, Math.min(360, Number(initialGradient.angle))));
|
||||
}
|
||||
} catch (_error) {
|
||||
backgroundGradientInput.value = '';
|
||||
}
|
||||
}
|
||||
if (backgroundGradientStops && !backgroundGradientStops.children.length) renderBackgroundGradientStops();
|
||||
renderRegionList(existingRegions);
|
||||
syncCanvasSizeSelection();
|
||||
updateStageBackgroundColor();
|
||||
|
||||
Reference in new issue
Block a user