Add chart navigation controls with keyboard shortcuts
- Navigation buttons (<, >, >>) appear when mouse within 30px of bottom - Left/Right arrows shift timeline 0.8 window width - Up arrow jumps to most recent candle - Buttons: < move left, > move right, >> go to recent
This commit is contained in:
@ -567,6 +567,51 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Navigation Controls */
|
||||
.nav-controls {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 10px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 4px;
|
||||
z-index: 10;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.chart-wrapper.show-nav .nav-controls {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.nav-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: rgba(42, 46, 57, 0.9);
|
||||
border: 1px solid #363c4e;
|
||||
color: #d1d4dc;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nav-btn:hover {
|
||||
background: #363c4e;
|
||||
border-color: #4a4f5e;
|
||||
}
|
||||
|
||||
.nav-btn:active {
|
||||
background: #2962ff;
|
||||
border-color: #2962ff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ha-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@ -995,12 +1040,17 @@
|
||||
|
||||
<div class="main-container">
|
||||
<div class="chart-area">
|
||||
<div class="chart-wrapper">
|
||||
<div class="chart-wrapper" id="chartWrapper">
|
||||
<div id="chart"></div>
|
||||
<div class="price-scale-controls" id="priceScaleControls">
|
||||
<button class="ps-control-btn auto-scale active" id="btnAutoScale" title="Auto Scale (A)">A</button>
|
||||
<button class="ps-control-btn log-scale" id="btnLogScale" title="Logarithmic Scale">L</button>
|
||||
</div>
|
||||
<div class="nav-controls" id="navControls">
|
||||
<button class="nav-btn" id="navLeft" title="Navigate Left (←)">‹</button>
|
||||
<button class="nav-btn" id="navRight" title="Navigate Right (→)">›</button>
|
||||
<button class="nav-btn" id="navRecent" title="Go to Recent (↑)">»</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ta-panel" id="taPanel">
|
||||
|
||||
@ -105,6 +105,7 @@ export class TradingDashboard {
|
||||
});
|
||||
|
||||
this.initPriceScaleControls();
|
||||
this.initNavigationControls();
|
||||
|
||||
this.chart.timeScale().subscribeVisibleLogicalRangeChange(this.onVisibleRangeChange.bind(this));
|
||||
|
||||
@ -204,6 +205,57 @@ export class TradingDashboard {
|
||||
});
|
||||
}
|
||||
|
||||
initNavigationControls() {
|
||||
const chartWrapper = document.getElementById('chartWrapper');
|
||||
const navLeft = document.getElementById('navLeft');
|
||||
const navRight = document.getElementById('navRight');
|
||||
const navRecent = document.getElementById('navRecent');
|
||||
|
||||
if (!chartWrapper || !navLeft || !navRight || !navRecent) return;
|
||||
|
||||
chartWrapper.addEventListener('mousemove', (e) => {
|
||||
const rect = chartWrapper.getBoundingClientRect();
|
||||
const distanceFromBottom = rect.bottom - e.clientY;
|
||||
chartWrapper.classList.toggle('show-nav', distanceFromBottom < 30);
|
||||
});
|
||||
|
||||
chartWrapper.addEventListener('mouseleave', () => {
|
||||
chartWrapper.classList.remove('show-nav');
|
||||
});
|
||||
|
||||
navLeft.addEventListener('click', () => this.navigateLeft());
|
||||
navRight.addEventListener('click', () => this.navigateRight());
|
||||
navRecent.addEventListener('click', () => this.navigateToRecent());
|
||||
}
|
||||
|
||||
navigateLeft() {
|
||||
const visibleRange = this.chart.timeScale().getVisibleLogicalRange();
|
||||
if (!visibleRange) return;
|
||||
|
||||
const visibleBars = visibleRange.to - visibleRange.from;
|
||||
const shift = visibleBars * 0.8;
|
||||
const newFrom = visibleRange.from - shift;
|
||||
const newTo = visibleRange.to - shift;
|
||||
|
||||
this.chart.timeScale().setVisibleLogicalRange({ from: newFrom, to: newTo });
|
||||
}
|
||||
|
||||
navigateRight() {
|
||||
const visibleRange = this.chart.timeScale().getVisibleLogicalRange();
|
||||
if (!visibleRange) return;
|
||||
|
||||
const visibleBars = visibleRange.to - visibleRange.from;
|
||||
const shift = visibleBars * 0.8;
|
||||
const newFrom = visibleRange.from + shift;
|
||||
const newTo = visibleRange.to + shift;
|
||||
|
||||
this.chart.timeScale().setVisibleLogicalRange({ from: newFrom, to: newTo });
|
||||
}
|
||||
|
||||
navigateToRecent() {
|
||||
this.chart.timeScale().scrollToRealTime();
|
||||
}
|
||||
|
||||
initEventListeners() {
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.target.tagName === 'INPUT' || e.target.tagName === 'BUTTON') return;
|
||||
@ -217,6 +269,14 @@ export class TradingDashboard {
|
||||
if (shortcuts[e.key]) {
|
||||
this.switchTimeframe(shortcuts[e.key]);
|
||||
}
|
||||
|
||||
if (e.key === 'ArrowLeft') {
|
||||
this.navigateLeft();
|
||||
} else if (e.key === 'ArrowRight') {
|
||||
this.navigateRight();
|
||||
} else if (e.key === 'ArrowUp') {
|
||||
this.navigateToRecent();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user