timeline and skill dragin improvments

This commit is contained in:
Akurosia Kamo 2026-05-23 21:03:13 +02:00
parent d0f54049e6
commit 3276e3bfb3
2 changed files with 70 additions and 2 deletions

View File

@ -723,6 +723,12 @@
background: var(--bg1); background: var(--bg1);
max-width: 100%; max-width: 100%;
width: 100%; width: 100%;
cursor: grab;
user-select: none;
}
.timeline-scroll--dragging {
cursor: grabbing;
} }
.timeline-grid { .timeline-grid {

View File

@ -1002,7 +1002,59 @@ function initTimeline(planId) {
const settings = document.getElementById('timeline-settings'); const settings = document.getElementById('timeline-settings');
if (!timeline || !settings) return; if (!timeline || !settings) return;
let timelinePan = null;
let suppressNextTimelineClick = false;
timeline.addEventListener('pointerdown', e => {
if (e.button !== 0) return;
if (!e.target.closest('.timeline-scroll')) return;
if (e.target.closest('.timeline-mitigation, .timeline-boss-action, .timeline-context-menu')) return;
const scroll = e.target.closest('.timeline-scroll');
timelinePan = {
scroll,
pointerId: e.pointerId,
startX: e.clientX,
startScrollLeft: scroll.scrollLeft,
moved: false,
};
scroll.setPointerCapture?.(e.pointerId);
});
timeline.addEventListener('pointermove', e => {
if (!timelinePan || timelinePan.pointerId !== e.pointerId) return;
const dx = e.clientX - timelinePan.startX;
if (Math.abs(dx) > 3) {
timelinePan.moved = true;
timelinePan.scroll.classList.add('timeline-scroll--dragging');
timelinePan.scroll.scrollLeft = timelinePan.startScrollLeft - dx;
e.preventDefault();
}
});
timeline.addEventListener('pointerup', e => {
if (!timelinePan || timelinePan.pointerId !== e.pointerId) return;
timelinePan.scroll.releasePointerCapture?.(e.pointerId);
timelinePan.scroll.classList.remove('timeline-scroll--dragging');
suppressNextTimelineClick = timelinePan.moved;
timelinePan = null;
if (suppressNextTimelineClick) setTimeout(() => { suppressNextTimelineClick = false; }, 0);
});
timeline.addEventListener('pointercancel', e => {
if (!timelinePan || timelinePan.pointerId !== e.pointerId) return;
timelinePan.scroll.releasePointerCapture?.(e.pointerId);
timelinePan.scroll.classList.remove('timeline-scroll--dragging');
timelinePan = null;
});
timeline.addEventListener('click', e => { timeline.addEventListener('click', e => {
if (suppressNextTimelineClick) {
e.preventDefault();
e.stopPropagation();
suppressNextTimelineClick = false;
return;
}
closeTimelineMenu(); closeTimelineMenu();
const boss = e.target.closest('.timeline-boss-action'); const boss = e.target.closest('.timeline-boss-action');
if (boss) { if (boss) {
@ -1063,11 +1115,20 @@ function initTimeline(planId) {
timeline.addEventListener('dragstart', e => { timeline.addEventListener('dragstart', e => {
const block = e.target.closest('.timeline-mitigation'); const block = e.target.closest('.timeline-mitigation');
if (!block) return; if (!block) return;
const plan = getPlan(planId);
const found = findTimelineAssignment(plan, {
mechanicId: block.dataset.mechanicId,
ability: block.dataset.ability,
job: block.dataset.job,
});
if (!plan || !found) return;
e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/plain', JSON.stringify({ e.dataTransfer.setData('text/plain', JSON.stringify({
mechanicId: block.dataset.mechanicId, mechanicId: block.dataset.mechanicId,
ability: block.dataset.ability, ability: block.dataset.ability,
job: block.dataset.job, job: block.dataset.job,
startClientX: e.clientX,
startTimestamp: assignmentStartMs(found.mechanic, found.assignment),
})); }));
}); });
@ -1086,8 +1147,9 @@ function initTimeline(planId) {
const plan = getPlan(planId); const plan = getPlan(planId);
if (!plan) return; if (!plan) return;
const rect = track.getBoundingClientRect(); const rect = track.getBoundingClientRect();
const x = Math.max(0, Math.min(rect.width, e.clientX - rect.left)); const deltaPx = e.clientX - (Number(data.startClientX) || e.clientX);
const timestamp = (x / rect.width) * planDurationMs(plan); const timestampDelta = (deltaPx / rect.width) * planDurationMs(plan);
const timestamp = (Number(data.startTimestamp) || 0) + timestampDelta;
if (row.dataset.ability && data.ability !== row.dataset.ability) return; if (row.dataset.ability && data.ability !== row.dataset.ability) return;
updateTimelineAssignmentPosition(planId, data.mechanicId, data.ability, data.job, row.dataset.job, timestamp); updateTimelineAssignmentPosition(planId, data.mechanicId, data.ability, data.job, row.dataset.job, timestamp);
}); });