hyperprop-charting-library 0.1.101 → 0.1.103
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hyperprop-charting-library.cjs +47 -34
- package/dist/hyperprop-charting-library.js +47 -34
- package/dist/index.cjs +47 -34
- package/dist/index.js +47 -34
- package/package.json +1 -1
|
@@ -2913,52 +2913,65 @@ function createChart(element, options = {}) {
|
|
|
2913
2913
|
}
|
|
2914
2914
|
return lo;
|
|
2915
2915
|
};
|
|
2916
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2917
|
+
for (const marker of tradeMarkers) {
|
|
2918
|
+
const ms = typeof marker.time === "number" ? marker.time : Date.parse(String(marker.time));
|
|
2919
|
+
if (!Number.isFinite(ms)) continue;
|
|
2920
|
+
const index = indexForTime(ms);
|
|
2921
|
+
if (index === null || index < visibleStart || index > visibleEnd) continue;
|
|
2922
|
+
const side = marker.side === "buy" ? "buy" : "sell";
|
|
2923
|
+
const qty = Math.max(0, marker.qty ?? 0);
|
|
2924
|
+
const weight = qty > 0 ? qty : 1;
|
|
2925
|
+
const key = `${index}:${side}`;
|
|
2926
|
+
const existing = groups.get(key);
|
|
2927
|
+
if (existing) {
|
|
2928
|
+
existing.qty += qty;
|
|
2929
|
+
existing.priceQty += marker.price * weight;
|
|
2930
|
+
} else {
|
|
2931
|
+
groups.set(key, {
|
|
2932
|
+
index,
|
|
2933
|
+
side,
|
|
2934
|
+
qty,
|
|
2935
|
+
priceQty: marker.price * weight,
|
|
2936
|
+
...marker.color === void 0 ? {} : { color: marker.color },
|
|
2937
|
+
...marker.textColor === void 0 ? {} : { textColor: marker.textColor },
|
|
2938
|
+
...marker.text === void 0 ? {} : { text: marker.text }
|
|
2939
|
+
});
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2916
2942
|
const prevFont = ctx.font;
|
|
2917
2943
|
const prevAlign = ctx.textAlign;
|
|
2918
2944
|
const prevBaseline = ctx.textBaseline;
|
|
2919
2945
|
ctx.font = `500 10px ${mergedOptions.fontFamily}`;
|
|
2920
2946
|
ctx.textAlign = "center";
|
|
2947
|
+
ctx.textBaseline = "middle";
|
|
2921
2948
|
const arrowHalf = 5;
|
|
2922
2949
|
const arrowH = 8;
|
|
2923
2950
|
const gap = 5;
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
const index = indexForTime(ms);
|
|
2928
|
-
if (index === null || index < visibleStart || index > visibleEnd) continue;
|
|
2929
|
-
const bar = data[index];
|
|
2951
|
+
const labelOffset = arrowH + 8;
|
|
2952
|
+
for (const group of groups.values()) {
|
|
2953
|
+
const bar = data[group.index];
|
|
2930
2954
|
if (!bar) continue;
|
|
2931
|
-
const x = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
2955
|
+
const x = chartLeft + (group.index + 0.5 - xStart) / xSpan * chartWidth;
|
|
2932
2956
|
if (x < chartLeft - 20 || x > chartRight + 20) continue;
|
|
2933
|
-
const isBuy =
|
|
2934
|
-
const arrowColor =
|
|
2935
|
-
const textColor =
|
|
2936
|
-
const
|
|
2957
|
+
const isBuy = group.side === "buy";
|
|
2958
|
+
const arrowColor = group.color ?? (isBuy ? "#2962ff" : "#f23645");
|
|
2959
|
+
const textColor = group.textColor ?? "#d1d4dc";
|
|
2960
|
+
const weightTotal = group.qty > 0 ? group.qty : 1;
|
|
2961
|
+
const avgPrice = group.priceQty / weightTotal;
|
|
2962
|
+
const label = group.text ?? `${group.qty > 0 ? `${group.qty} @ ` : ""}${formatPrice(avgPrice)}`.trim();
|
|
2937
2963
|
ctx.save();
|
|
2938
2964
|
ctx.fillStyle = arrowColor;
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
ctx.fillText(label, x, tipY + arrowH + 2);
|
|
2950
|
-
} else {
|
|
2951
|
-
const tipY = yFromPrice(bar.h) - gap;
|
|
2952
|
-
ctx.beginPath();
|
|
2953
|
-
ctx.moveTo(x, tipY);
|
|
2954
|
-
ctx.lineTo(x - arrowHalf, tipY - arrowH);
|
|
2955
|
-
ctx.lineTo(x + arrowHalf, tipY - arrowH);
|
|
2956
|
-
ctx.closePath();
|
|
2957
|
-
ctx.fill();
|
|
2958
|
-
ctx.fillStyle = textColor;
|
|
2959
|
-
ctx.textBaseline = "bottom";
|
|
2960
|
-
ctx.fillText(label, x, tipY - arrowH - 2);
|
|
2961
|
-
}
|
|
2965
|
+
const tipY = isBuy ? yFromPrice(bar.l) + gap : yFromPrice(bar.h) - gap;
|
|
2966
|
+
const dir = isBuy ? 1 : -1;
|
|
2967
|
+
ctx.beginPath();
|
|
2968
|
+
ctx.moveTo(x, tipY);
|
|
2969
|
+
ctx.lineTo(x - arrowHalf, tipY + arrowH * dir);
|
|
2970
|
+
ctx.lineTo(x + arrowHalf, tipY + arrowH * dir);
|
|
2971
|
+
ctx.closePath();
|
|
2972
|
+
ctx.fill();
|
|
2973
|
+
ctx.fillStyle = textColor;
|
|
2974
|
+
ctx.fillText(label, Math.round(x), Math.round(tipY + labelOffset * dir));
|
|
2962
2975
|
ctx.restore();
|
|
2963
2976
|
}
|
|
2964
2977
|
ctx.font = prevFont;
|
|
@@ -2887,52 +2887,65 @@ function createChart(element, options = {}) {
|
|
|
2887
2887
|
}
|
|
2888
2888
|
return lo;
|
|
2889
2889
|
};
|
|
2890
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2891
|
+
for (const marker of tradeMarkers) {
|
|
2892
|
+
const ms = typeof marker.time === "number" ? marker.time : Date.parse(String(marker.time));
|
|
2893
|
+
if (!Number.isFinite(ms)) continue;
|
|
2894
|
+
const index = indexForTime(ms);
|
|
2895
|
+
if (index === null || index < visibleStart || index > visibleEnd) continue;
|
|
2896
|
+
const side = marker.side === "buy" ? "buy" : "sell";
|
|
2897
|
+
const qty = Math.max(0, marker.qty ?? 0);
|
|
2898
|
+
const weight = qty > 0 ? qty : 1;
|
|
2899
|
+
const key = `${index}:${side}`;
|
|
2900
|
+
const existing = groups.get(key);
|
|
2901
|
+
if (existing) {
|
|
2902
|
+
existing.qty += qty;
|
|
2903
|
+
existing.priceQty += marker.price * weight;
|
|
2904
|
+
} else {
|
|
2905
|
+
groups.set(key, {
|
|
2906
|
+
index,
|
|
2907
|
+
side,
|
|
2908
|
+
qty,
|
|
2909
|
+
priceQty: marker.price * weight,
|
|
2910
|
+
...marker.color === void 0 ? {} : { color: marker.color },
|
|
2911
|
+
...marker.textColor === void 0 ? {} : { textColor: marker.textColor },
|
|
2912
|
+
...marker.text === void 0 ? {} : { text: marker.text }
|
|
2913
|
+
});
|
|
2914
|
+
}
|
|
2915
|
+
}
|
|
2890
2916
|
const prevFont = ctx.font;
|
|
2891
2917
|
const prevAlign = ctx.textAlign;
|
|
2892
2918
|
const prevBaseline = ctx.textBaseline;
|
|
2893
2919
|
ctx.font = `500 10px ${mergedOptions.fontFamily}`;
|
|
2894
2920
|
ctx.textAlign = "center";
|
|
2921
|
+
ctx.textBaseline = "middle";
|
|
2895
2922
|
const arrowHalf = 5;
|
|
2896
2923
|
const arrowH = 8;
|
|
2897
2924
|
const gap = 5;
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
const index = indexForTime(ms);
|
|
2902
|
-
if (index === null || index < visibleStart || index > visibleEnd) continue;
|
|
2903
|
-
const bar = data[index];
|
|
2925
|
+
const labelOffset = arrowH + 8;
|
|
2926
|
+
for (const group of groups.values()) {
|
|
2927
|
+
const bar = data[group.index];
|
|
2904
2928
|
if (!bar) continue;
|
|
2905
|
-
const x = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
2929
|
+
const x = chartLeft + (group.index + 0.5 - xStart) / xSpan * chartWidth;
|
|
2906
2930
|
if (x < chartLeft - 20 || x > chartRight + 20) continue;
|
|
2907
|
-
const isBuy =
|
|
2908
|
-
const arrowColor =
|
|
2909
|
-
const textColor =
|
|
2910
|
-
const
|
|
2931
|
+
const isBuy = group.side === "buy";
|
|
2932
|
+
const arrowColor = group.color ?? (isBuy ? "#2962ff" : "#f23645");
|
|
2933
|
+
const textColor = group.textColor ?? "#d1d4dc";
|
|
2934
|
+
const weightTotal = group.qty > 0 ? group.qty : 1;
|
|
2935
|
+
const avgPrice = group.priceQty / weightTotal;
|
|
2936
|
+
const label = group.text ?? `${group.qty > 0 ? `${group.qty} @ ` : ""}${formatPrice(avgPrice)}`.trim();
|
|
2911
2937
|
ctx.save();
|
|
2912
2938
|
ctx.fillStyle = arrowColor;
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
ctx.fillText(label, x, tipY + arrowH + 2);
|
|
2924
|
-
} else {
|
|
2925
|
-
const tipY = yFromPrice(bar.h) - gap;
|
|
2926
|
-
ctx.beginPath();
|
|
2927
|
-
ctx.moveTo(x, tipY);
|
|
2928
|
-
ctx.lineTo(x - arrowHalf, tipY - arrowH);
|
|
2929
|
-
ctx.lineTo(x + arrowHalf, tipY - arrowH);
|
|
2930
|
-
ctx.closePath();
|
|
2931
|
-
ctx.fill();
|
|
2932
|
-
ctx.fillStyle = textColor;
|
|
2933
|
-
ctx.textBaseline = "bottom";
|
|
2934
|
-
ctx.fillText(label, x, tipY - arrowH - 2);
|
|
2935
|
-
}
|
|
2939
|
+
const tipY = isBuy ? yFromPrice(bar.l) + gap : yFromPrice(bar.h) - gap;
|
|
2940
|
+
const dir = isBuy ? 1 : -1;
|
|
2941
|
+
ctx.beginPath();
|
|
2942
|
+
ctx.moveTo(x, tipY);
|
|
2943
|
+
ctx.lineTo(x - arrowHalf, tipY + arrowH * dir);
|
|
2944
|
+
ctx.lineTo(x + arrowHalf, tipY + arrowH * dir);
|
|
2945
|
+
ctx.closePath();
|
|
2946
|
+
ctx.fill();
|
|
2947
|
+
ctx.fillStyle = textColor;
|
|
2948
|
+
ctx.fillText(label, Math.round(x), Math.round(tipY + labelOffset * dir));
|
|
2936
2949
|
ctx.restore();
|
|
2937
2950
|
}
|
|
2938
2951
|
ctx.font = prevFont;
|
package/dist/index.cjs
CHANGED
|
@@ -2913,52 +2913,65 @@ function createChart(element, options = {}) {
|
|
|
2913
2913
|
}
|
|
2914
2914
|
return lo;
|
|
2915
2915
|
};
|
|
2916
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2917
|
+
for (const marker of tradeMarkers) {
|
|
2918
|
+
const ms = typeof marker.time === "number" ? marker.time : Date.parse(String(marker.time));
|
|
2919
|
+
if (!Number.isFinite(ms)) continue;
|
|
2920
|
+
const index = indexForTime(ms);
|
|
2921
|
+
if (index === null || index < visibleStart || index > visibleEnd) continue;
|
|
2922
|
+
const side = marker.side === "buy" ? "buy" : "sell";
|
|
2923
|
+
const qty = Math.max(0, marker.qty ?? 0);
|
|
2924
|
+
const weight = qty > 0 ? qty : 1;
|
|
2925
|
+
const key = `${index}:${side}`;
|
|
2926
|
+
const existing = groups.get(key);
|
|
2927
|
+
if (existing) {
|
|
2928
|
+
existing.qty += qty;
|
|
2929
|
+
existing.priceQty += marker.price * weight;
|
|
2930
|
+
} else {
|
|
2931
|
+
groups.set(key, {
|
|
2932
|
+
index,
|
|
2933
|
+
side,
|
|
2934
|
+
qty,
|
|
2935
|
+
priceQty: marker.price * weight,
|
|
2936
|
+
...marker.color === void 0 ? {} : { color: marker.color },
|
|
2937
|
+
...marker.textColor === void 0 ? {} : { textColor: marker.textColor },
|
|
2938
|
+
...marker.text === void 0 ? {} : { text: marker.text }
|
|
2939
|
+
});
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2916
2942
|
const prevFont = ctx.font;
|
|
2917
2943
|
const prevAlign = ctx.textAlign;
|
|
2918
2944
|
const prevBaseline = ctx.textBaseline;
|
|
2919
2945
|
ctx.font = `500 10px ${mergedOptions.fontFamily}`;
|
|
2920
2946
|
ctx.textAlign = "center";
|
|
2947
|
+
ctx.textBaseline = "middle";
|
|
2921
2948
|
const arrowHalf = 5;
|
|
2922
2949
|
const arrowH = 8;
|
|
2923
2950
|
const gap = 5;
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
const index = indexForTime(ms);
|
|
2928
|
-
if (index === null || index < visibleStart || index > visibleEnd) continue;
|
|
2929
|
-
const bar = data[index];
|
|
2951
|
+
const labelOffset = arrowH + 8;
|
|
2952
|
+
for (const group of groups.values()) {
|
|
2953
|
+
const bar = data[group.index];
|
|
2930
2954
|
if (!bar) continue;
|
|
2931
|
-
const x = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
2955
|
+
const x = chartLeft + (group.index + 0.5 - xStart) / xSpan * chartWidth;
|
|
2932
2956
|
if (x < chartLeft - 20 || x > chartRight + 20) continue;
|
|
2933
|
-
const isBuy =
|
|
2934
|
-
const arrowColor =
|
|
2935
|
-
const textColor =
|
|
2936
|
-
const
|
|
2957
|
+
const isBuy = group.side === "buy";
|
|
2958
|
+
const arrowColor = group.color ?? (isBuy ? "#2962ff" : "#f23645");
|
|
2959
|
+
const textColor = group.textColor ?? "#d1d4dc";
|
|
2960
|
+
const weightTotal = group.qty > 0 ? group.qty : 1;
|
|
2961
|
+
const avgPrice = group.priceQty / weightTotal;
|
|
2962
|
+
const label = group.text ?? `${group.qty > 0 ? `${group.qty} @ ` : ""}${formatPrice(avgPrice)}`.trim();
|
|
2937
2963
|
ctx.save();
|
|
2938
2964
|
ctx.fillStyle = arrowColor;
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
ctx.fillText(label, x, tipY + arrowH + 2);
|
|
2950
|
-
} else {
|
|
2951
|
-
const tipY = yFromPrice(bar.h) - gap;
|
|
2952
|
-
ctx.beginPath();
|
|
2953
|
-
ctx.moveTo(x, tipY);
|
|
2954
|
-
ctx.lineTo(x - arrowHalf, tipY - arrowH);
|
|
2955
|
-
ctx.lineTo(x + arrowHalf, tipY - arrowH);
|
|
2956
|
-
ctx.closePath();
|
|
2957
|
-
ctx.fill();
|
|
2958
|
-
ctx.fillStyle = textColor;
|
|
2959
|
-
ctx.textBaseline = "bottom";
|
|
2960
|
-
ctx.fillText(label, x, tipY - arrowH - 2);
|
|
2961
|
-
}
|
|
2965
|
+
const tipY = isBuy ? yFromPrice(bar.l) + gap : yFromPrice(bar.h) - gap;
|
|
2966
|
+
const dir = isBuy ? 1 : -1;
|
|
2967
|
+
ctx.beginPath();
|
|
2968
|
+
ctx.moveTo(x, tipY);
|
|
2969
|
+
ctx.lineTo(x - arrowHalf, tipY + arrowH * dir);
|
|
2970
|
+
ctx.lineTo(x + arrowHalf, tipY + arrowH * dir);
|
|
2971
|
+
ctx.closePath();
|
|
2972
|
+
ctx.fill();
|
|
2973
|
+
ctx.fillStyle = textColor;
|
|
2974
|
+
ctx.fillText(label, Math.round(x), Math.round(tipY + labelOffset * dir));
|
|
2962
2975
|
ctx.restore();
|
|
2963
2976
|
}
|
|
2964
2977
|
ctx.font = prevFont;
|
package/dist/index.js
CHANGED
|
@@ -2887,52 +2887,65 @@ function createChart(element, options = {}) {
|
|
|
2887
2887
|
}
|
|
2888
2888
|
return lo;
|
|
2889
2889
|
};
|
|
2890
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2891
|
+
for (const marker of tradeMarkers) {
|
|
2892
|
+
const ms = typeof marker.time === "number" ? marker.time : Date.parse(String(marker.time));
|
|
2893
|
+
if (!Number.isFinite(ms)) continue;
|
|
2894
|
+
const index = indexForTime(ms);
|
|
2895
|
+
if (index === null || index < visibleStart || index > visibleEnd) continue;
|
|
2896
|
+
const side = marker.side === "buy" ? "buy" : "sell";
|
|
2897
|
+
const qty = Math.max(0, marker.qty ?? 0);
|
|
2898
|
+
const weight = qty > 0 ? qty : 1;
|
|
2899
|
+
const key = `${index}:${side}`;
|
|
2900
|
+
const existing = groups.get(key);
|
|
2901
|
+
if (existing) {
|
|
2902
|
+
existing.qty += qty;
|
|
2903
|
+
existing.priceQty += marker.price * weight;
|
|
2904
|
+
} else {
|
|
2905
|
+
groups.set(key, {
|
|
2906
|
+
index,
|
|
2907
|
+
side,
|
|
2908
|
+
qty,
|
|
2909
|
+
priceQty: marker.price * weight,
|
|
2910
|
+
...marker.color === void 0 ? {} : { color: marker.color },
|
|
2911
|
+
...marker.textColor === void 0 ? {} : { textColor: marker.textColor },
|
|
2912
|
+
...marker.text === void 0 ? {} : { text: marker.text }
|
|
2913
|
+
});
|
|
2914
|
+
}
|
|
2915
|
+
}
|
|
2890
2916
|
const prevFont = ctx.font;
|
|
2891
2917
|
const prevAlign = ctx.textAlign;
|
|
2892
2918
|
const prevBaseline = ctx.textBaseline;
|
|
2893
2919
|
ctx.font = `500 10px ${mergedOptions.fontFamily}`;
|
|
2894
2920
|
ctx.textAlign = "center";
|
|
2921
|
+
ctx.textBaseline = "middle";
|
|
2895
2922
|
const arrowHalf = 5;
|
|
2896
2923
|
const arrowH = 8;
|
|
2897
2924
|
const gap = 5;
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
const index = indexForTime(ms);
|
|
2902
|
-
if (index === null || index < visibleStart || index > visibleEnd) continue;
|
|
2903
|
-
const bar = data[index];
|
|
2925
|
+
const labelOffset = arrowH + 8;
|
|
2926
|
+
for (const group of groups.values()) {
|
|
2927
|
+
const bar = data[group.index];
|
|
2904
2928
|
if (!bar) continue;
|
|
2905
|
-
const x = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
2929
|
+
const x = chartLeft + (group.index + 0.5 - xStart) / xSpan * chartWidth;
|
|
2906
2930
|
if (x < chartLeft - 20 || x > chartRight + 20) continue;
|
|
2907
|
-
const isBuy =
|
|
2908
|
-
const arrowColor =
|
|
2909
|
-
const textColor =
|
|
2910
|
-
const
|
|
2931
|
+
const isBuy = group.side === "buy";
|
|
2932
|
+
const arrowColor = group.color ?? (isBuy ? "#2962ff" : "#f23645");
|
|
2933
|
+
const textColor = group.textColor ?? "#d1d4dc";
|
|
2934
|
+
const weightTotal = group.qty > 0 ? group.qty : 1;
|
|
2935
|
+
const avgPrice = group.priceQty / weightTotal;
|
|
2936
|
+
const label = group.text ?? `${group.qty > 0 ? `${group.qty} @ ` : ""}${formatPrice(avgPrice)}`.trim();
|
|
2911
2937
|
ctx.save();
|
|
2912
2938
|
ctx.fillStyle = arrowColor;
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
ctx.fillText(label, x, tipY + arrowH + 2);
|
|
2924
|
-
} else {
|
|
2925
|
-
const tipY = yFromPrice(bar.h) - gap;
|
|
2926
|
-
ctx.beginPath();
|
|
2927
|
-
ctx.moveTo(x, tipY);
|
|
2928
|
-
ctx.lineTo(x - arrowHalf, tipY - arrowH);
|
|
2929
|
-
ctx.lineTo(x + arrowHalf, tipY - arrowH);
|
|
2930
|
-
ctx.closePath();
|
|
2931
|
-
ctx.fill();
|
|
2932
|
-
ctx.fillStyle = textColor;
|
|
2933
|
-
ctx.textBaseline = "bottom";
|
|
2934
|
-
ctx.fillText(label, x, tipY - arrowH - 2);
|
|
2935
|
-
}
|
|
2939
|
+
const tipY = isBuy ? yFromPrice(bar.l) + gap : yFromPrice(bar.h) - gap;
|
|
2940
|
+
const dir = isBuy ? 1 : -1;
|
|
2941
|
+
ctx.beginPath();
|
|
2942
|
+
ctx.moveTo(x, tipY);
|
|
2943
|
+
ctx.lineTo(x - arrowHalf, tipY + arrowH * dir);
|
|
2944
|
+
ctx.lineTo(x + arrowHalf, tipY + arrowH * dir);
|
|
2945
|
+
ctx.closePath();
|
|
2946
|
+
ctx.fill();
|
|
2947
|
+
ctx.fillStyle = textColor;
|
|
2948
|
+
ctx.fillText(label, Math.round(x), Math.round(tipY + labelOffset * dir));
|
|
2936
2949
|
ctx.restore();
|
|
2937
2950
|
}
|
|
2938
2951
|
ctx.font = prevFont;
|