fib look and feel tweaks
This commit is contained in:
parent
1c3a852a03
commit
ac2943f248
2 changed files with 60 additions and 2 deletions
|
|
@ -140,7 +140,7 @@ class FibLevelsPrimitive {
|
||||||
color,
|
color,
|
||||||
width,
|
width,
|
||||||
dashed: !major,
|
dashed: !major,
|
||||||
label: `${level.label} ${level.price.toFixed(2)}`,
|
label: `fib ${level.label} ${level.price.toFixed(2)}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -218,6 +218,8 @@ class ConfluenceChart {
|
||||||
this.lineHitTarget = null;
|
this.lineHitTarget = null;
|
||||||
this.lineFocus = null;
|
this.lineFocus = null;
|
||||||
this.lineFocusTimer = null;
|
this.lineFocusTimer = null;
|
||||||
|
this.fibFocus = null;
|
||||||
|
this.fibFocusTimer = null;
|
||||||
this.draggingLine = null;
|
this.draggingLine = null;
|
||||||
this.lineMoveListener = null;
|
this.lineMoveListener = null;
|
||||||
this.lineUpListener = null;
|
this.lineUpListener = null;
|
||||||
|
|
@ -507,6 +509,10 @@ class ConfluenceChart {
|
||||||
this.lineFocus.classList.add('chart-line-focus');
|
this.lineFocus.classList.add('chart-line-focus');
|
||||||
this.lineFocus.setAttribute('hidden', '');
|
this.lineFocus.setAttribute('hidden', '');
|
||||||
handles.appendChild(this.lineFocus);
|
handles.appendChild(this.lineFocus);
|
||||||
|
this.fibFocus = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||||
|
this.fibFocus.classList.add('chart-fib-focus');
|
||||||
|
this.fibFocus.setAttribute('hidden', '');
|
||||||
|
handles.appendChild(this.fibFocus);
|
||||||
this.lineHitTarget = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');
|
this.lineHitTarget = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');
|
||||||
this.lineHitTarget.classList.add('chart-line-hit');
|
this.lineHitTarget.classList.add('chart-line-hit');
|
||||||
this.lineHitTarget.setAttribute('hidden', '');
|
this.lineHitTarget.setAttribute('hidden', '');
|
||||||
|
|
@ -1993,6 +1999,11 @@ class ConfluenceChart {
|
||||||
|
|
||||||
focusLine(id) {
|
focusLine(id) {
|
||||||
this.setSelectedLine(id);
|
this.setSelectedLine(id);
|
||||||
|
const fib = this.fibs.find(item => item.id === id);
|
||||||
|
if (fib) {
|
||||||
|
this.focusFib(fib);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const level = this.levels.find(value => value.id === id && value.kind === 'manual');
|
const level = this.levels.find(value => value.id === id && value.kind === 'manual');
|
||||||
if (!level) return;
|
if (!level) return;
|
||||||
if (ConfluenceChart.isFlat(level)) {
|
if (ConfluenceChart.isFlat(level)) {
|
||||||
|
|
@ -2020,6 +2031,52 @@ class ConfluenceChart {
|
||||||
this.lineFocusTimer = setTimeout(() => this.lineFocus.setAttribute('hidden', ''), 800);
|
this.lineFocusTimer = setTimeout(() => this.lineFocus.setAttribute('hidden', ''), 800);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
focusFib(fib) {
|
||||||
|
if (!this.fibFocus || !this.overlayLayer) return;
|
||||||
|
this.fibFocus.replaceChildren();
|
||||||
|
const width = this.overlayLayer.getBoundingClientRect().width;
|
||||||
|
const originX = this.coordinateAtTime(fib.anchor_t);
|
||||||
|
const start = originX == null ? 0 : Math.max(0, originX);
|
||||||
|
const color = fib.color || '#c8992f';
|
||||||
|
const lineWidth = Math.max(1, Number(fib.line_width) || 2);
|
||||||
|
this.fibFocus.style.setProperty('--line-focus-start-width', `${lineWidth + 10}px`);
|
||||||
|
this.fibFocus.style.setProperty('--line-focus-width', `${lineWidth}px`);
|
||||||
|
const y0 = this.candles.priceToCoordinate(Number(fib.anchor_p));
|
||||||
|
const endP = Number(fib.anchor_p) + Number(fib.slope || 0)
|
||||||
|
* (Number(fib.last_t) - Number(fib.anchor_t));
|
||||||
|
const y1 = this.candles.priceToCoordinate(endP);
|
||||||
|
if (originX != null && y0 != null && y1 != null) {
|
||||||
|
const rail = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||||
|
rail.classList.add('chart-line-focus');
|
||||||
|
rail.setAttribute('x1', originX);
|
||||||
|
rail.setAttribute('x2', originX);
|
||||||
|
rail.setAttribute('y1', y0);
|
||||||
|
rail.setAttribute('y2', y1);
|
||||||
|
rail.setAttribute('stroke', color);
|
||||||
|
this.fibFocus.appendChild(rail);
|
||||||
|
}
|
||||||
|
for (const level of ConfluenceChart.fibPrices(fib)) {
|
||||||
|
const y = this.candles.priceToCoordinate(level.price);
|
||||||
|
if (y == null) continue;
|
||||||
|
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||||
|
line.classList.add('chart-line-focus');
|
||||||
|
line.setAttribute('x1', start);
|
||||||
|
line.setAttribute('x2', width);
|
||||||
|
line.setAttribute('y1', y);
|
||||||
|
line.setAttribute('y2', y);
|
||||||
|
line.setAttribute('stroke', color);
|
||||||
|
this.fibFocus.appendChild(line);
|
||||||
|
}
|
||||||
|
this.fibFocus.removeAttribute('hidden');
|
||||||
|
for (const line of this.fibFocus.querySelectorAll('line')) {
|
||||||
|
line.style.animation = 'none';
|
||||||
|
void line.getBoundingClientRect();
|
||||||
|
line.style.animation = '';
|
||||||
|
}
|
||||||
|
clearTimeout(this.fibFocusTimer);
|
||||||
|
this.fibFocusTimer = setTimeout(() => this.fibFocus.setAttribute('hidden', ''), 800);
|
||||||
|
}
|
||||||
|
|
||||||
focusComment(id) {
|
focusComment(id) {
|
||||||
const node = this.commentNodes.get(id);
|
const node = this.commentNodes.get(id);
|
||||||
if (!node) return;
|
if (!node) return;
|
||||||
|
|
@ -2906,6 +2963,7 @@ class ConfluenceChart {
|
||||||
this.detachPointers('anchor');
|
this.detachPointers('anchor');
|
||||||
this.detachPointers('line');
|
this.detachPointers('line');
|
||||||
clearTimeout(this.lineFocusTimer);
|
clearTimeout(this.lineFocusTimer);
|
||||||
|
clearTimeout(this.fibFocusTimer);
|
||||||
for (const node of this.commentNodes.values()) clearTimeout(node.focusTimer);
|
for (const node of this.commentNodes.values()) clearTimeout(node.focusTimer);
|
||||||
if (this.chartEl && this.clickListener) this.chartEl.removeEventListener('click', this.clickListener);
|
if (this.chartEl && this.clickListener) this.chartEl.removeEventListener('click', this.clickListener);
|
||||||
if (this.chartEl && this.contextListener) this.chartEl.removeEventListener('contextmenu', this.contextListener);
|
if (this.chartEl && this.contextListener) this.chartEl.removeEventListener('contextmenu', this.contextListener);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ main { display:grid; grid-template-columns:minmax(0, 1fr) 300px; gap:16px; }
|
||||||
button { border:1px solid var(--line); background:transparent; color:var(--muted); padding:6px 11px; font:inherit; cursor:pointer; }button.active { color:var(--bg); background:var(--accent); border-color:var(--accent); }
|
button { border:1px solid var(--line); background:transparent; color:var(--muted); padding:6px 11px; font:inherit; cursor:pointer; }button.active { color:var(--bg); background:var(--accent); border-color:var(--accent); }
|
||||||
.timeframes { display:flex; flex-wrap:wrap; justify-content:flex-end; }.timeframes button+button { border-left:0; }
|
.timeframes { display:flex; flex-wrap:wrap; justify-content:flex-end; }.timeframes button+button { border-left:0; }
|
||||||
.drawing-tools { min-height:38px; padding:5px 12px; display:flex; align-items:center; gap:9px; border-bottom:1px solid var(--line); color:var(--muted); font-size:10px; }.drawing-tools button,.drawing-tools select,.drawing-tools .line-name { padding:4px 8px; font-size:10px; }.drawing-tools select,.drawing-tools .line-name { background:var(--panel); color:var(--fg); border:1px solid var(--line); }.drawing-tools .line-name { width:130px; font:inherit; }.drawing-tools label { display:flex; gap:4px; align-items:center; }.drawing-tools input { accent-color:var(--accent); }
|
.drawing-tools { min-height:38px; padding:5px 12px; display:flex; align-items:center; gap:9px; border-bottom:1px solid var(--line); color:var(--muted); font-size:10px; }.drawing-tools button,.drawing-tools select,.drawing-tools .line-name { padding:4px 8px; font-size:10px; }.drawing-tools select,.drawing-tools .line-name { background:var(--panel); color:var(--fg); border:1px solid var(--line); }.drawing-tools .line-name { width:130px; font:inherit; }.drawing-tools label { display:flex; gap:4px; align-items:center; }.drawing-tools input { accent-color:var(--accent); }
|
||||||
#chart { position:relative; height:calc(100vh - 190px); min-height:420px; touch-action:pan-y; }.chart-preview,.chart-line-bridges,.chart-handles { position:absolute; inset:0; width:100%; height:100%; overflow:hidden; pointer-events:none; }.chart-preview,.chart-line-bridges { z-index:4; }.chart-line-bridges line { stroke-linecap:round; }.chart-handles { z-index:6; }.chart-preview line[hidden],.chart-anchor[hidden],.chart-line-hit[hidden],.chart-line-focus[hidden] { display:none; }.chart-line-focus { stroke-linecap:round; pointer-events:none; animation:line-focus .75s ease-out forwards; }.chart-line-hit { fill:none; stroke:transparent; stroke-width:16px; pointer-events:stroke; cursor:move; touch-action:none; }.chart-anchor { stroke:var(--panel); stroke-width:2px; cursor:grab; pointer-events:all; touch-action:none; }.chart-anchor:active { cursor:grabbing; }.chart-tooltip { position:absolute; z-index:5; padding:4px 7px; border:1px solid var(--line); background:var(--panel); color:var(--fg); font-size:10px; white-space:pre-line; pointer-events:none; }.chart-tooltip[hidden] { display:none; }
|
#chart { position:relative; height:calc(100vh - 190px); min-height:420px; touch-action:pan-y; }.chart-preview,.chart-line-bridges,.chart-handles { position:absolute; inset:0; width:100%; height:100%; overflow:hidden; pointer-events:none; }.chart-preview,.chart-line-bridges { z-index:4; }.chart-line-bridges line { stroke-linecap:round; }.chart-handles { z-index:6; }.chart-preview line[hidden],.chart-anchor[hidden],.chart-line-hit[hidden],.chart-line-focus[hidden],.chart-fib-focus[hidden] { display:none; }.chart-line-focus { stroke-linecap:round; pointer-events:none; animation:line-focus .75s ease-out forwards; }.chart-line-hit { fill:none; stroke:transparent; stroke-width:16px; pointer-events:stroke; cursor:move; touch-action:none; }.chart-anchor { stroke:var(--panel); stroke-width:2px; cursor:grab; pointer-events:all; touch-action:none; }.chart-anchor:active { cursor:grabbing; }.chart-tooltip { position:absolute; z-index:5; padding:4px 7px; border:1px solid var(--line); background:var(--panel); color:var(--fg); font-size:10px; white-space:pre-line; pointer-events:none; }.chart-tooltip[hidden] { display:none; }
|
||||||
.current-price-pulse { position:absolute; left:0; right:0; z-index:5; height:3px; transform:translateY(-1.5px); overflow:hidden; opacity:0; background:repeating-linear-gradient(110deg,transparent 0 8px,color-mix(in srgb,var(--accent) 55%,white) 8px 13px,transparent 13px 19px); mask-image:linear-gradient(90deg,transparent 0,#000 8%,#000 100%); pointer-events:none; }.current-price-pulse::after { content:''; position:absolute; top:-2px; bottom:-2px; left:-24%; width:24%; background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--accent) 35%,white),transparent); opacity:.8; }.current-price-pulse.active { opacity:.9; animation:current-price-flow 1.5s linear infinite; }.current-price-pulse.active::after { animation:current-price-scan 2.8s linear infinite; }@keyframes current-price-flow { to { background-position-x:57px; } }@keyframes current-price-scan { to { transform:translateX(520%); } }
|
.current-price-pulse { position:absolute; left:0; right:0; z-index:5; height:3px; transform:translateY(-1.5px); overflow:hidden; opacity:0; background:repeating-linear-gradient(110deg,transparent 0 8px,color-mix(in srgb,var(--accent) 55%,white) 8px 13px,transparent 13px 19px); mask-image:linear-gradient(90deg,transparent 0,#000 8%,#000 100%); pointer-events:none; }.current-price-pulse::after { content:''; position:absolute; top:-2px; bottom:-2px; left:-24%; width:24%; background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--accent) 35%,white),transparent); opacity:.8; }.current-price-pulse.active { opacity:.9; animation:current-price-flow 1.5s linear infinite; }.current-price-pulse.active::after { animation:current-price-scan 2.8s linear infinite; }@keyframes current-price-flow { to { background-position-x:57px; } }@keyframes current-price-scan { to { transform:translateX(520%); } }
|
||||||
.chart-ohlc { position:absolute; top:6px; left:8px; z-index:5; padding:2px 6px; border:1px solid var(--line); background:color-mix(in srgb,var(--panel) 90%,transparent); color:var(--fg); font-size:10px; font-variant-numeric:tabular-nums; pointer-events:none; white-space:nowrap; }.chart-ohlc.up { color:var(--green); }.chart-ohlc.down { color:var(--red); }.chart-ohlc[hidden] { display:none; }
|
.chart-ohlc { position:absolute; top:6px; left:8px; z-index:5; padding:2px 6px; border:1px solid var(--line); background:color-mix(in srgb,var(--panel) 90%,transparent); color:var(--fg); font-size:10px; font-variant-numeric:tabular-nums; pointer-events:none; white-space:nowrap; }.chart-ohlc.up { color:var(--green); }.chart-ohlc.down { color:var(--red); }.chart-ohlc[hidden] { display:none; }
|
||||||
.projection-diagnostic { position:absolute; top:8px; left:8px; z-index:9; margin:0; padding:5px 7px; border:1px solid var(--line); background:color-mix(in srgb,var(--panel) 92%,transparent); color:var(--fg); font:9px/1.35 "IBM Plex Mono", monospace; white-space:pre; }
|
.projection-diagnostic { position:absolute; top:8px; left:8px; z-index:9; margin:0; padding:5px 7px; border:1px solid var(--line); background:color-mix(in srgb,var(--panel) 92%,transparent); color:var(--fg); font:9px/1.35 "IBM Plex Mono", monospace; white-space:pre; }
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue