59 lines
1.7 KiB
JavaScript
59 lines
1.7 KiB
JavaScript
/** 轻量蜡烛图(无外部依赖),用于复盘四周期预览 */
|
|
(function () {
|
|
function drawCandleChart(canvas, bars) {
|
|
if (!canvas || !bars || !bars.length) return;
|
|
const dpr = window.devicePixelRatio || 1;
|
|
const cssW = canvas.clientWidth || 400;
|
|
const cssH = canvas.clientHeight || 180;
|
|
canvas.width = cssW * dpr;
|
|
canvas.height = cssH * dpr;
|
|
const ctx = canvas.getContext("2d");
|
|
ctx.scale(dpr, dpr);
|
|
|
|
const pad = 8;
|
|
let min = Infinity, max = -Infinity;
|
|
bars.forEach((b) => {
|
|
min = Math.min(min, b.low);
|
|
max = Math.max(max, b.high);
|
|
});
|
|
if (!(max > min)) {
|
|
max = min + 1;
|
|
}
|
|
const w = cssW - pad * 2;
|
|
const h = cssH - pad * 2;
|
|
const n = bars.length;
|
|
const slot = w / n;
|
|
|
|
ctx.clearRect(0, 0, cssW, cssH);
|
|
ctx.fillStyle = "#0e0e18";
|
|
ctx.fillRect(0, 0, cssW, cssH);
|
|
|
|
const yOf = (p) => pad + ((max - p) / (max - min)) * h;
|
|
|
|
bars.forEach((b, i) => {
|
|
const x = pad + i * slot + slot * 0.5;
|
|
const up = b.close >= b.open;
|
|
ctx.strokeStyle = up ? "#0ecb81" : "#f6465d";
|
|
ctx.fillStyle = ctx.strokeStyle;
|
|
ctx.beginPath();
|
|
ctx.moveTo(x, yOf(b.high));
|
|
ctx.lineTo(x, yOf(b.low));
|
|
ctx.stroke();
|
|
const y1 = yOf(b.open);
|
|
const y2 = yOf(b.close);
|
|
const top = Math.min(y1, y2);
|
|
const bh = Math.max(1, Math.abs(y2 - y1));
|
|
ctx.fillRect(x - Math.max(1, slot * 0.3), top, Math.max(2, slot * 0.6), bh);
|
|
});
|
|
}
|
|
|
|
document.querySelectorAll("canvas.chart-canvas").forEach((el) => {
|
|
try {
|
|
const bars = JSON.parse(el.dataset.bars || "[]");
|
|
drawCandleChart(el, bars);
|
|
} catch (e) {
|
|
console.warn(e);
|
|
}
|
|
});
|
|
})();
|