mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 09:41:40 -05:00
color scale editor
This commit is contained in:
parent
227d3b1f0c
commit
2ca003f39e
3 changed files with 160 additions and 16 deletions
|
|
@ -9,7 +9,9 @@ import {
|
|||
createPolylinesLayer,
|
||||
updatePolylinesOpacity,
|
||||
updatePolylinesColors,
|
||||
colorFormatEncode
|
||||
colorFormatEncode,
|
||||
colorFormatDecode,
|
||||
colorStopsFallback
|
||||
} from "../maps/polylines";
|
||||
|
||||
import { fetchAndDrawAreas, handleAreaCreated } from "../maps/areas";
|
||||
|
|
@ -37,14 +39,6 @@ export default class extends BaseController {
|
|||
super.connect();
|
||||
console.log("Map controller connected");
|
||||
|
||||
const speedColorScaleDefault = [
|
||||
{ speed: 0, color: '#00ff00' },
|
||||
{ speed: 15, color: '#00ffff' },
|
||||
{ speed: 30, color: '#ff00ff' },
|
||||
{ speed: 50, color: '#ffff00' },
|
||||
{ speed: 100, color: '#ff3300' }
|
||||
];
|
||||
|
||||
this.apiKey = this.element.dataset.api_key;
|
||||
this.markers = JSON.parse(this.element.dataset.coordinates);
|
||||
this.timezone = this.element.dataset.timezone;
|
||||
|
|
@ -783,9 +777,11 @@ export default class extends BaseController {
|
|||
<input type="text" class="join-item input input-ghost focus:input-ghost input-xs input-bordered w-full max-w-xs" id="speed_color_scale" name="speed_color_scale" min="5" max="100" step="1" value="${this.speedColorScale}">
|
||||
<label for="speed_color_scale_info" class="btn-xs join-item">?</label>
|
||||
</div>
|
||||
<button type="button" id="edit-gradient-btn" class="btn btn-xs mt-2">Edit Scale</button>
|
||||
|
||||
<hr>
|
||||
|
||||
<button type="submit">Update</button>
|
||||
<button type="submit" class="btn btn-xs mt-2">Update</button>
|
||||
</form>
|
||||
`;
|
||||
|
||||
|
|
@ -798,6 +794,12 @@ export default class extends BaseController {
|
|||
// Prevent map interactions when interacting with the form
|
||||
L.DomEvent.disableClickPropagation(div);
|
||||
|
||||
// Attach event listener to the "Edit Gradient" button:
|
||||
const editBtn = div.querySelector("#edit-gradient-btn");
|
||||
if (editBtn) {
|
||||
editBtn.addEventListener("click", this.showGradientEditor.bind(this));
|
||||
}
|
||||
|
||||
// Add event listener to the form submission
|
||||
div.querySelector('#settings-form').addEventListener(
|
||||
'submit', this.updateSettings.bind(this)
|
||||
|
|
@ -1381,4 +1383,143 @@ export default class extends BaseController {
|
|||
|
||||
container.innerHTML = html;
|
||||
}
|
||||
|
||||
showGradientEditor() {
|
||||
const modal = document.createElement("div");
|
||||
modal.id = "gradient-editor-modal";
|
||||
Object.assign(modal.style, {
|
||||
position: "fixed",
|
||||
top: "0",
|
||||
left: "0",
|
||||
right: "0",
|
||||
bottom: "0",
|
||||
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
zIndex: "100",
|
||||
});
|
||||
|
||||
const content = document.createElement("div");
|
||||
Object.assign(content.style, {
|
||||
backgroundColor: "#fff",
|
||||
padding: "20px",
|
||||
borderRadius: "5px",
|
||||
minWidth: "300px",
|
||||
maxHeight: "80vh",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
});
|
||||
|
||||
const title = document.createElement("h2");
|
||||
title.textContent = "Edit Speed Color Scale";
|
||||
content.appendChild(title);
|
||||
|
||||
const gradientContainer = document.createElement("div");
|
||||
gradientContainer.id = "gradient-editor-container";
|
||||
Object.assign(gradientContainer.style, {
|
||||
marginTop: "15px",
|
||||
overflowY: "auto",
|
||||
flex: "1",
|
||||
border: "1px solid #ccc",
|
||||
padding: "5px",
|
||||
});
|
||||
|
||||
const createRow = (stop = { speed: 0, color: "#000000" }) => {
|
||||
const row = document.createElement("div");
|
||||
row.style.display = "flex";
|
||||
row.style.alignItems = "center";
|
||||
row.style.gap = "10px";
|
||||
row.style.marginBottom = "8px";
|
||||
|
||||
const speedInput = document.createElement("input");
|
||||
speedInput.type = "number";
|
||||
speedInput.value = stop.speed;
|
||||
speedInput.style.width = "70px";
|
||||
|
||||
const colorInput = document.createElement("input");
|
||||
colorInput.type = "color";
|
||||
colorInput.value = stop.color;
|
||||
colorInput.style.width = "70px";
|
||||
|
||||
const removeBtn = document.createElement("button");
|
||||
removeBtn.textContent = "x";
|
||||
removeBtn.style.color = "#cc3311";
|
||||
removeBtn.style.flexShrink = "0";
|
||||
removeBtn.addEventListener("click", () => {
|
||||
if (gradientContainer.childElementCount > 1) {
|
||||
gradientContainer.removeChild(row);
|
||||
} else {
|
||||
showFlashMessage('error', 'At least one gradient stop is required.');
|
||||
}
|
||||
});
|
||||
|
||||
row.appendChild(speedInput);
|
||||
row.appendChild(colorInput);
|
||||
row.appendChild(removeBtn);
|
||||
return row;
|
||||
};
|
||||
|
||||
let stops;
|
||||
try {
|
||||
stops = colorFormatDecode(this.speedColorScale);
|
||||
} catch (error) {
|
||||
stops = colorStopsFallback;
|
||||
}
|
||||
stops.forEach(stop => {
|
||||
const row = createRow(stop);
|
||||
gradientContainer.appendChild(row);
|
||||
});
|
||||
|
||||
content.appendChild(gradientContainer);
|
||||
|
||||
const addRowBtn = document.createElement("button");
|
||||
addRowBtn.textContent = "Add Row";
|
||||
addRowBtn.style.marginTop = "10px";
|
||||
addRowBtn.addEventListener("click", () => {
|
||||
const newRow = createRow({ speed: 0, color: "#000000" });
|
||||
gradientContainer.appendChild(newRow);
|
||||
});
|
||||
content.appendChild(addRowBtn);
|
||||
|
||||
const btnContainer = document.createElement("div");
|
||||
btnContainer.style.display = "flex";
|
||||
btnContainer.style.justifyContent = "flex-end";
|
||||
btnContainer.style.gap = "10px";
|
||||
btnContainer.style.marginTop = "15px";
|
||||
|
||||
const cancelBtn = document.createElement("button");
|
||||
cancelBtn.textContent = "Cancel";
|
||||
cancelBtn.addEventListener("click", () => {
|
||||
document.body.removeChild(modal);
|
||||
});
|
||||
|
||||
const saveBtn = document.createElement("button");
|
||||
saveBtn.textContent = "Save";
|
||||
saveBtn.addEventListener("click", () => {
|
||||
const newStops = [];
|
||||
gradientContainer.querySelectorAll("div").forEach(row => {
|
||||
const inputs = row.querySelectorAll("input");
|
||||
const speed = Number(inputs[0].value);
|
||||
const color = inputs[1].value;
|
||||
newStops.push({ speed, color });
|
||||
});
|
||||
|
||||
const newGradient = colorFormatEncode(newStops);
|
||||
|
||||
this.speedColorScale = newGradient;
|
||||
const speedColorScaleInput = document.getElementById("speed_color_scale");
|
||||
if (speedColorScaleInput) {
|
||||
speedColorScaleInput.value = newGradient;
|
||||
}
|
||||
|
||||
document.body.removeChild(modal);
|
||||
});
|
||||
|
||||
btnContainer.appendChild(cancelBtn);
|
||||
btnContainer.appendChild(saveBtn);
|
||||
content.appendChild(btnContainer);
|
||||
modal.appendChild(content);
|
||||
document.body.appendChild(modal);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,16 +25,13 @@ export function calculateSpeed(point1, point2) {
|
|||
}
|
||||
|
||||
// Optimize getSpeedColor by pre-calculating color stops
|
||||
const colorStopsFallback = [
|
||||
export const colorStopsFallback = [
|
||||
{ speed: 0, color: '#00ff00' }, // Stationary/very slow (green)
|
||||
{ speed: 15, color: '#00ffff' }, // Walking/jogging (cyan)
|
||||
{ speed: 30, color: '#ff00ff' }, // Cycling/slow driving (magenta)
|
||||
{ speed: 50, color: '#ffff00' }, // Urban driving (yellow)
|
||||
{ speed: 100, color: '#ff3300' } // Highway driving (red)
|
||||
].map(stop => ({
|
||||
...stop,
|
||||
rgb: hexToRGB(stop.color)
|
||||
}));
|
||||
];
|
||||
|
||||
export function colorFormatEncode(arr) {
|
||||
return arr.map(item => `${item.speed}:${item.color}`).join('|');
|
||||
|
|
@ -60,7 +57,10 @@ export function getSpeedColor(speedKmh, useSpeedColors, speedColorScale) {
|
|||
rgb: hexToRGB(stop.color)
|
||||
}));;
|
||||
} catch (error) { // If user has given invalid values
|
||||
colorStops = colorStopsFallback;
|
||||
colorStops = colorStopsFallback.map(stop => ({
|
||||
...stop,
|
||||
rgb: hexToRGB(stop.color)
|
||||
}));;
|
||||
}
|
||||
|
||||
// Find the appropriate color segment
|
||||
|
|
|
|||
|
|
@ -152,6 +152,9 @@
|
|||
<p class="py-4">
|
||||
Here you can set a custom color scale for speed colored routes. It uses color stops at specified km/h values and creates a gradient from it. The default value is <code>0:#00ff00|15:#00ffff|30:#ff00ff|50:#ffff00|100:#ff3300</code>
|
||||
</p>
|
||||
<p class="py-4">
|
||||
You can also use the 'Edit Scale' button to edit it using an UI.
|
||||
</p>
|
||||
</div>
|
||||
<label class="modal-backdrop" for="speed_color_scale_info">Close</label>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue