hyperprop-charting-library 0.1.55 → 0.1.57
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.
|
@@ -959,6 +959,7 @@ function createChart(element, options = {}) {
|
|
|
959
959
|
let drawings = (options.drawings ?? []).map((drawing) => normalizeDrawingState(drawing));
|
|
960
960
|
let activeDrawingTool = null;
|
|
961
961
|
let draftDrawing = null;
|
|
962
|
+
let drawingDragState = null;
|
|
962
963
|
let drawingsChangeHandler = null;
|
|
963
964
|
let drawingSelectHandler = null;
|
|
964
965
|
const emitDrawingsChange = () => {
|
|
@@ -2043,10 +2044,12 @@ function createChart(element, options = {}) {
|
|
|
2043
2044
|
const point = drawing.points[0];
|
|
2044
2045
|
if (point) {
|
|
2045
2046
|
const y = clamp(yFromPrice(point.price), chartTop + 1, chartBottom - 1);
|
|
2047
|
+
const handleX = chartRight - 64;
|
|
2046
2048
|
ctx.beginPath();
|
|
2047
2049
|
ctx.moveTo(crisp(chartLeft), crisp(y));
|
|
2048
2050
|
ctx.lineTo(crisp(chartRight), crisp(y));
|
|
2049
2051
|
ctx.stroke();
|
|
2052
|
+
drawDrawingHandle(handleX, y, drawing.color);
|
|
2050
2053
|
}
|
|
2051
2054
|
} else if (drawing.type === "trendline") {
|
|
2052
2055
|
const first = drawing.points[0];
|
|
@@ -3091,6 +3094,15 @@ function createChart(element, options = {}) {
|
|
|
3091
3094
|
...time ? { time: time.toISOString() } : {}
|
|
3092
3095
|
};
|
|
3093
3096
|
};
|
|
3097
|
+
const normalizeDrawingPoint = (index, price) => {
|
|
3098
|
+
const roundedIndex = Math.round(index);
|
|
3099
|
+
const time = getTimeForIndex(roundedIndex);
|
|
3100
|
+
return {
|
|
3101
|
+
index,
|
|
3102
|
+
price: roundToPricePrecision(price),
|
|
3103
|
+
...time ? { time: time.toISOString() } : {}
|
|
3104
|
+
};
|
|
3105
|
+
};
|
|
3094
3106
|
const canvasXFromDrawingPoint = (point) => {
|
|
3095
3107
|
if (!drawState) return 0;
|
|
3096
3108
|
return drawState.chartLeft + (point.index + 0.5 - drawState.xStart) / drawState.xSpan * drawState.chartWidth;
|
|
@@ -3116,6 +3128,10 @@ function createChart(element, options = {}) {
|
|
|
3116
3128
|
const point = drawing.points[0];
|
|
3117
3129
|
if (!point) continue;
|
|
3118
3130
|
const lineY = canvasYFromDrawingPrice(point.price);
|
|
3131
|
+
const handleX = drawState ? drawState.chartRight - 64 : 0;
|
|
3132
|
+
if (Math.hypot(x - handleX, y - lineY) <= 8) {
|
|
3133
|
+
return { drawing, target: "handle", pointIndex: 0 };
|
|
3134
|
+
}
|
|
3119
3135
|
if (Math.abs(y - lineY) <= 7) {
|
|
3120
3136
|
return { drawing, target: "line" };
|
|
3121
3137
|
}
|
|
@@ -3127,8 +3143,11 @@ function createChart(element, options = {}) {
|
|
|
3127
3143
|
const y1 = canvasYFromDrawingPrice(first.price);
|
|
3128
3144
|
const x2 = canvasXFromDrawingPoint(second);
|
|
3129
3145
|
const y2 = canvasYFromDrawingPrice(second.price);
|
|
3130
|
-
if (Math.hypot(x - x1, y - y1) <= 8
|
|
3131
|
-
return { drawing, target: "handle" };
|
|
3146
|
+
if (Math.hypot(x - x1, y - y1) <= 8) {
|
|
3147
|
+
return { drawing, target: "handle", pointIndex: 0 };
|
|
3148
|
+
}
|
|
3149
|
+
if (Math.hypot(x - x2, y - y2) <= 8) {
|
|
3150
|
+
return { drawing, target: "handle", pointIndex: 1 };
|
|
3132
3151
|
}
|
|
3133
3152
|
if (distanceToSegment(x, y, x1, y1, x2, y2) <= 6) {
|
|
3134
3153
|
return { drawing, target: "line" };
|
|
@@ -3236,6 +3255,39 @@ function createChart(element, options = {}) {
|
|
|
3236
3255
|
}
|
|
3237
3256
|
return false;
|
|
3238
3257
|
};
|
|
3258
|
+
const updateDrawingDrag = (x, y) => {
|
|
3259
|
+
if (!drawingDragState) {
|
|
3260
|
+
return false;
|
|
3261
|
+
}
|
|
3262
|
+
const currentPoint = drawingPointFromCanvas(x, y);
|
|
3263
|
+
if (!currentPoint) {
|
|
3264
|
+
return true;
|
|
3265
|
+
}
|
|
3266
|
+
const deltaIndex = currentPoint.index - drawingDragState.startCanvasPoint.index;
|
|
3267
|
+
const deltaPrice = currentPoint.price - drawingDragState.startCanvasPoint.price;
|
|
3268
|
+
drawings = drawings.map((drawing) => {
|
|
3269
|
+
if (drawing.id !== drawingDragState?.drawingId || drawing.locked) {
|
|
3270
|
+
return drawing;
|
|
3271
|
+
}
|
|
3272
|
+
if (drawingDragState.target === "handle") {
|
|
3273
|
+
return {
|
|
3274
|
+
...drawing,
|
|
3275
|
+
points: drawing.points.map(
|
|
3276
|
+
(point, index) => index === (drawingDragState?.pointIndex ?? 0) ? normalizeDrawingPoint(currentPoint.index, currentPoint.price) : point
|
|
3277
|
+
)
|
|
3278
|
+
};
|
|
3279
|
+
}
|
|
3280
|
+
return {
|
|
3281
|
+
...drawing,
|
|
3282
|
+
points: drawingDragState.startPoints.map(
|
|
3283
|
+
(point) => normalizeDrawingPoint(point.index + deltaIndex, point.price + deltaPrice)
|
|
3284
|
+
)
|
|
3285
|
+
};
|
|
3286
|
+
});
|
|
3287
|
+
emitDrawingsChange();
|
|
3288
|
+
draw();
|
|
3289
|
+
return true;
|
|
3290
|
+
};
|
|
3239
3291
|
let isDragging = false;
|
|
3240
3292
|
let dragMode = null;
|
|
3241
3293
|
let lastPointerX = 0;
|
|
@@ -3275,6 +3327,7 @@ function createChart(element, options = {}) {
|
|
|
3275
3327
|
pointerDownInfo = null;
|
|
3276
3328
|
orderDragState = null;
|
|
3277
3329
|
actionDragState = null;
|
|
3330
|
+
drawingDragState = null;
|
|
3278
3331
|
canvas.style.cursor = "default";
|
|
3279
3332
|
setCrosshairPoint(null);
|
|
3280
3333
|
};
|
|
@@ -3367,11 +3420,26 @@ function createChart(element, options = {}) {
|
|
|
3367
3420
|
drawingSelectHandler?.({
|
|
3368
3421
|
drawing: serializeDrawing(drawingHit.drawing),
|
|
3369
3422
|
target: drawingHit.target,
|
|
3423
|
+
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
3370
3424
|
x: point.x,
|
|
3371
3425
|
y: point.y
|
|
3372
3426
|
});
|
|
3427
|
+
if (!drawingHit.drawing.locked) {
|
|
3428
|
+
const startCanvasPoint = drawingPointFromCanvas(point.x, point.y);
|
|
3429
|
+
if (startCanvasPoint) {
|
|
3430
|
+
drawingDragState = {
|
|
3431
|
+
drawingId: drawingHit.drawing.id,
|
|
3432
|
+
target: drawingHit.target,
|
|
3433
|
+
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
3434
|
+
startCanvasPoint,
|
|
3435
|
+
startPoints: drawingHit.drawing.points.map((drawingPoint) => ({ ...drawingPoint }))
|
|
3436
|
+
};
|
|
3437
|
+
activePointerId = event.pointerId;
|
|
3438
|
+
canvas.setPointerCapture(event.pointerId);
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3373
3441
|
setCrosshairPoint(null);
|
|
3374
|
-
canvas.style.cursor = "pointer";
|
|
3442
|
+
canvas.style.cursor = drawingHit.drawing.locked ? "pointer" : drawingHit.target === "handle" ? "grab" : "move";
|
|
3375
3443
|
return;
|
|
3376
3444
|
}
|
|
3377
3445
|
}
|
|
@@ -3411,6 +3479,15 @@ function createChart(element, options = {}) {
|
|
|
3411
3479
|
pointerDownInfo.moved = true;
|
|
3412
3480
|
}
|
|
3413
3481
|
}
|
|
3482
|
+
if (drawingDragState) {
|
|
3483
|
+
if (activePointerId !== null && event.pointerId !== activePointerId) {
|
|
3484
|
+
return;
|
|
3485
|
+
}
|
|
3486
|
+
updateDrawingDrag(point.x, point.y);
|
|
3487
|
+
canvas.style.cursor = drawingDragState.target === "handle" ? "grabbing" : "move";
|
|
3488
|
+
setCrosshairPoint(null);
|
|
3489
|
+
return;
|
|
3490
|
+
}
|
|
3414
3491
|
if (draftDrawing && activeDrawingTool === "trendline") {
|
|
3415
3492
|
const nextPoint = drawingPointFromCanvas(point.x, point.y);
|
|
3416
3493
|
if (nextPoint) {
|
|
@@ -3494,7 +3571,8 @@ function createChart(element, options = {}) {
|
|
|
3494
3571
|
return;
|
|
3495
3572
|
}
|
|
3496
3573
|
if (!activeDrawingTool && getDrawingHit(point.x, point.y)) {
|
|
3497
|
-
|
|
3574
|
+
const drawingHit = getDrawingHit(point.x, point.y);
|
|
3575
|
+
canvas.style.cursor = drawingHit?.drawing.locked ? "pointer" : drawingHit?.target === "handle" ? "grab" : "move";
|
|
3498
3576
|
setCrosshairPoint(null);
|
|
3499
3577
|
return;
|
|
3500
3578
|
}
|
|
@@ -3590,6 +3668,10 @@ function createChart(element, options = {}) {
|
|
|
3590
3668
|
}
|
|
3591
3669
|
actionDragState = null;
|
|
3592
3670
|
}
|
|
3671
|
+
if (drawingDragState) {
|
|
3672
|
+
drawingDragState = null;
|
|
3673
|
+
emitDrawingsChange();
|
|
3674
|
+
}
|
|
3593
3675
|
isDragging = false;
|
|
3594
3676
|
dragMode = null;
|
|
3595
3677
|
activePointerId = null;
|
|
@@ -935,6 +935,7 @@ function createChart(element, options = {}) {
|
|
|
935
935
|
let drawings = (options.drawings ?? []).map((drawing) => normalizeDrawingState(drawing));
|
|
936
936
|
let activeDrawingTool = null;
|
|
937
937
|
let draftDrawing = null;
|
|
938
|
+
let drawingDragState = null;
|
|
938
939
|
let drawingsChangeHandler = null;
|
|
939
940
|
let drawingSelectHandler = null;
|
|
940
941
|
const emitDrawingsChange = () => {
|
|
@@ -2019,10 +2020,12 @@ function createChart(element, options = {}) {
|
|
|
2019
2020
|
const point = drawing.points[0];
|
|
2020
2021
|
if (point) {
|
|
2021
2022
|
const y = clamp(yFromPrice(point.price), chartTop + 1, chartBottom - 1);
|
|
2023
|
+
const handleX = chartRight - 64;
|
|
2022
2024
|
ctx.beginPath();
|
|
2023
2025
|
ctx.moveTo(crisp(chartLeft), crisp(y));
|
|
2024
2026
|
ctx.lineTo(crisp(chartRight), crisp(y));
|
|
2025
2027
|
ctx.stroke();
|
|
2028
|
+
drawDrawingHandle(handleX, y, drawing.color);
|
|
2026
2029
|
}
|
|
2027
2030
|
} else if (drawing.type === "trendline") {
|
|
2028
2031
|
const first = drawing.points[0];
|
|
@@ -3067,6 +3070,15 @@ function createChart(element, options = {}) {
|
|
|
3067
3070
|
...time ? { time: time.toISOString() } : {}
|
|
3068
3071
|
};
|
|
3069
3072
|
};
|
|
3073
|
+
const normalizeDrawingPoint = (index, price) => {
|
|
3074
|
+
const roundedIndex = Math.round(index);
|
|
3075
|
+
const time = getTimeForIndex(roundedIndex);
|
|
3076
|
+
return {
|
|
3077
|
+
index,
|
|
3078
|
+
price: roundToPricePrecision(price),
|
|
3079
|
+
...time ? { time: time.toISOString() } : {}
|
|
3080
|
+
};
|
|
3081
|
+
};
|
|
3070
3082
|
const canvasXFromDrawingPoint = (point) => {
|
|
3071
3083
|
if (!drawState) return 0;
|
|
3072
3084
|
return drawState.chartLeft + (point.index + 0.5 - drawState.xStart) / drawState.xSpan * drawState.chartWidth;
|
|
@@ -3092,6 +3104,10 @@ function createChart(element, options = {}) {
|
|
|
3092
3104
|
const point = drawing.points[0];
|
|
3093
3105
|
if (!point) continue;
|
|
3094
3106
|
const lineY = canvasYFromDrawingPrice(point.price);
|
|
3107
|
+
const handleX = drawState ? drawState.chartRight - 64 : 0;
|
|
3108
|
+
if (Math.hypot(x - handleX, y - lineY) <= 8) {
|
|
3109
|
+
return { drawing, target: "handle", pointIndex: 0 };
|
|
3110
|
+
}
|
|
3095
3111
|
if (Math.abs(y - lineY) <= 7) {
|
|
3096
3112
|
return { drawing, target: "line" };
|
|
3097
3113
|
}
|
|
@@ -3103,8 +3119,11 @@ function createChart(element, options = {}) {
|
|
|
3103
3119
|
const y1 = canvasYFromDrawingPrice(first.price);
|
|
3104
3120
|
const x2 = canvasXFromDrawingPoint(second);
|
|
3105
3121
|
const y2 = canvasYFromDrawingPrice(second.price);
|
|
3106
|
-
if (Math.hypot(x - x1, y - y1) <= 8
|
|
3107
|
-
return { drawing, target: "handle" };
|
|
3122
|
+
if (Math.hypot(x - x1, y - y1) <= 8) {
|
|
3123
|
+
return { drawing, target: "handle", pointIndex: 0 };
|
|
3124
|
+
}
|
|
3125
|
+
if (Math.hypot(x - x2, y - y2) <= 8) {
|
|
3126
|
+
return { drawing, target: "handle", pointIndex: 1 };
|
|
3108
3127
|
}
|
|
3109
3128
|
if (distanceToSegment(x, y, x1, y1, x2, y2) <= 6) {
|
|
3110
3129
|
return { drawing, target: "line" };
|
|
@@ -3212,6 +3231,39 @@ function createChart(element, options = {}) {
|
|
|
3212
3231
|
}
|
|
3213
3232
|
return false;
|
|
3214
3233
|
};
|
|
3234
|
+
const updateDrawingDrag = (x, y) => {
|
|
3235
|
+
if (!drawingDragState) {
|
|
3236
|
+
return false;
|
|
3237
|
+
}
|
|
3238
|
+
const currentPoint = drawingPointFromCanvas(x, y);
|
|
3239
|
+
if (!currentPoint) {
|
|
3240
|
+
return true;
|
|
3241
|
+
}
|
|
3242
|
+
const deltaIndex = currentPoint.index - drawingDragState.startCanvasPoint.index;
|
|
3243
|
+
const deltaPrice = currentPoint.price - drawingDragState.startCanvasPoint.price;
|
|
3244
|
+
drawings = drawings.map((drawing) => {
|
|
3245
|
+
if (drawing.id !== drawingDragState?.drawingId || drawing.locked) {
|
|
3246
|
+
return drawing;
|
|
3247
|
+
}
|
|
3248
|
+
if (drawingDragState.target === "handle") {
|
|
3249
|
+
return {
|
|
3250
|
+
...drawing,
|
|
3251
|
+
points: drawing.points.map(
|
|
3252
|
+
(point, index) => index === (drawingDragState?.pointIndex ?? 0) ? normalizeDrawingPoint(currentPoint.index, currentPoint.price) : point
|
|
3253
|
+
)
|
|
3254
|
+
};
|
|
3255
|
+
}
|
|
3256
|
+
return {
|
|
3257
|
+
...drawing,
|
|
3258
|
+
points: drawingDragState.startPoints.map(
|
|
3259
|
+
(point) => normalizeDrawingPoint(point.index + deltaIndex, point.price + deltaPrice)
|
|
3260
|
+
)
|
|
3261
|
+
};
|
|
3262
|
+
});
|
|
3263
|
+
emitDrawingsChange();
|
|
3264
|
+
draw();
|
|
3265
|
+
return true;
|
|
3266
|
+
};
|
|
3215
3267
|
let isDragging = false;
|
|
3216
3268
|
let dragMode = null;
|
|
3217
3269
|
let lastPointerX = 0;
|
|
@@ -3251,6 +3303,7 @@ function createChart(element, options = {}) {
|
|
|
3251
3303
|
pointerDownInfo = null;
|
|
3252
3304
|
orderDragState = null;
|
|
3253
3305
|
actionDragState = null;
|
|
3306
|
+
drawingDragState = null;
|
|
3254
3307
|
canvas.style.cursor = "default";
|
|
3255
3308
|
setCrosshairPoint(null);
|
|
3256
3309
|
};
|
|
@@ -3343,11 +3396,26 @@ function createChart(element, options = {}) {
|
|
|
3343
3396
|
drawingSelectHandler?.({
|
|
3344
3397
|
drawing: serializeDrawing(drawingHit.drawing),
|
|
3345
3398
|
target: drawingHit.target,
|
|
3399
|
+
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
3346
3400
|
x: point.x,
|
|
3347
3401
|
y: point.y
|
|
3348
3402
|
});
|
|
3403
|
+
if (!drawingHit.drawing.locked) {
|
|
3404
|
+
const startCanvasPoint = drawingPointFromCanvas(point.x, point.y);
|
|
3405
|
+
if (startCanvasPoint) {
|
|
3406
|
+
drawingDragState = {
|
|
3407
|
+
drawingId: drawingHit.drawing.id,
|
|
3408
|
+
target: drawingHit.target,
|
|
3409
|
+
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
3410
|
+
startCanvasPoint,
|
|
3411
|
+
startPoints: drawingHit.drawing.points.map((drawingPoint) => ({ ...drawingPoint }))
|
|
3412
|
+
};
|
|
3413
|
+
activePointerId = event.pointerId;
|
|
3414
|
+
canvas.setPointerCapture(event.pointerId);
|
|
3415
|
+
}
|
|
3416
|
+
}
|
|
3349
3417
|
setCrosshairPoint(null);
|
|
3350
|
-
canvas.style.cursor = "pointer";
|
|
3418
|
+
canvas.style.cursor = drawingHit.drawing.locked ? "pointer" : drawingHit.target === "handle" ? "grab" : "move";
|
|
3351
3419
|
return;
|
|
3352
3420
|
}
|
|
3353
3421
|
}
|
|
@@ -3387,6 +3455,15 @@ function createChart(element, options = {}) {
|
|
|
3387
3455
|
pointerDownInfo.moved = true;
|
|
3388
3456
|
}
|
|
3389
3457
|
}
|
|
3458
|
+
if (drawingDragState) {
|
|
3459
|
+
if (activePointerId !== null && event.pointerId !== activePointerId) {
|
|
3460
|
+
return;
|
|
3461
|
+
}
|
|
3462
|
+
updateDrawingDrag(point.x, point.y);
|
|
3463
|
+
canvas.style.cursor = drawingDragState.target === "handle" ? "grabbing" : "move";
|
|
3464
|
+
setCrosshairPoint(null);
|
|
3465
|
+
return;
|
|
3466
|
+
}
|
|
3390
3467
|
if (draftDrawing && activeDrawingTool === "trendline") {
|
|
3391
3468
|
const nextPoint = drawingPointFromCanvas(point.x, point.y);
|
|
3392
3469
|
if (nextPoint) {
|
|
@@ -3470,7 +3547,8 @@ function createChart(element, options = {}) {
|
|
|
3470
3547
|
return;
|
|
3471
3548
|
}
|
|
3472
3549
|
if (!activeDrawingTool && getDrawingHit(point.x, point.y)) {
|
|
3473
|
-
|
|
3550
|
+
const drawingHit = getDrawingHit(point.x, point.y);
|
|
3551
|
+
canvas.style.cursor = drawingHit?.drawing.locked ? "pointer" : drawingHit?.target === "handle" ? "grab" : "move";
|
|
3474
3552
|
setCrosshairPoint(null);
|
|
3475
3553
|
return;
|
|
3476
3554
|
}
|
|
@@ -3566,6 +3644,10 @@ function createChart(element, options = {}) {
|
|
|
3566
3644
|
}
|
|
3567
3645
|
actionDragState = null;
|
|
3568
3646
|
}
|
|
3647
|
+
if (drawingDragState) {
|
|
3648
|
+
drawingDragState = null;
|
|
3649
|
+
emitDrawingsChange();
|
|
3650
|
+
}
|
|
3569
3651
|
isDragging = false;
|
|
3570
3652
|
dragMode = null;
|
|
3571
3653
|
activePointerId = null;
|
package/dist/index.cjs
CHANGED
|
@@ -959,6 +959,7 @@ function createChart(element, options = {}) {
|
|
|
959
959
|
let drawings = (options.drawings ?? []).map((drawing) => normalizeDrawingState(drawing));
|
|
960
960
|
let activeDrawingTool = null;
|
|
961
961
|
let draftDrawing = null;
|
|
962
|
+
let drawingDragState = null;
|
|
962
963
|
let drawingsChangeHandler = null;
|
|
963
964
|
let drawingSelectHandler = null;
|
|
964
965
|
const emitDrawingsChange = () => {
|
|
@@ -2043,10 +2044,12 @@ function createChart(element, options = {}) {
|
|
|
2043
2044
|
const point = drawing.points[0];
|
|
2044
2045
|
if (point) {
|
|
2045
2046
|
const y = clamp(yFromPrice(point.price), chartTop + 1, chartBottom - 1);
|
|
2047
|
+
const handleX = chartRight - 64;
|
|
2046
2048
|
ctx.beginPath();
|
|
2047
2049
|
ctx.moveTo(crisp(chartLeft), crisp(y));
|
|
2048
2050
|
ctx.lineTo(crisp(chartRight), crisp(y));
|
|
2049
2051
|
ctx.stroke();
|
|
2052
|
+
drawDrawingHandle(handleX, y, drawing.color);
|
|
2050
2053
|
}
|
|
2051
2054
|
} else if (drawing.type === "trendline") {
|
|
2052
2055
|
const first = drawing.points[0];
|
|
@@ -3091,6 +3094,15 @@ function createChart(element, options = {}) {
|
|
|
3091
3094
|
...time ? { time: time.toISOString() } : {}
|
|
3092
3095
|
};
|
|
3093
3096
|
};
|
|
3097
|
+
const normalizeDrawingPoint = (index, price) => {
|
|
3098
|
+
const roundedIndex = Math.round(index);
|
|
3099
|
+
const time = getTimeForIndex(roundedIndex);
|
|
3100
|
+
return {
|
|
3101
|
+
index,
|
|
3102
|
+
price: roundToPricePrecision(price),
|
|
3103
|
+
...time ? { time: time.toISOString() } : {}
|
|
3104
|
+
};
|
|
3105
|
+
};
|
|
3094
3106
|
const canvasXFromDrawingPoint = (point) => {
|
|
3095
3107
|
if (!drawState) return 0;
|
|
3096
3108
|
return drawState.chartLeft + (point.index + 0.5 - drawState.xStart) / drawState.xSpan * drawState.chartWidth;
|
|
@@ -3116,6 +3128,10 @@ function createChart(element, options = {}) {
|
|
|
3116
3128
|
const point = drawing.points[0];
|
|
3117
3129
|
if (!point) continue;
|
|
3118
3130
|
const lineY = canvasYFromDrawingPrice(point.price);
|
|
3131
|
+
const handleX = drawState ? drawState.chartRight - 64 : 0;
|
|
3132
|
+
if (Math.hypot(x - handleX, y - lineY) <= 8) {
|
|
3133
|
+
return { drawing, target: "handle", pointIndex: 0 };
|
|
3134
|
+
}
|
|
3119
3135
|
if (Math.abs(y - lineY) <= 7) {
|
|
3120
3136
|
return { drawing, target: "line" };
|
|
3121
3137
|
}
|
|
@@ -3127,8 +3143,11 @@ function createChart(element, options = {}) {
|
|
|
3127
3143
|
const y1 = canvasYFromDrawingPrice(first.price);
|
|
3128
3144
|
const x2 = canvasXFromDrawingPoint(second);
|
|
3129
3145
|
const y2 = canvasYFromDrawingPrice(second.price);
|
|
3130
|
-
if (Math.hypot(x - x1, y - y1) <= 8
|
|
3131
|
-
return { drawing, target: "handle" };
|
|
3146
|
+
if (Math.hypot(x - x1, y - y1) <= 8) {
|
|
3147
|
+
return { drawing, target: "handle", pointIndex: 0 };
|
|
3148
|
+
}
|
|
3149
|
+
if (Math.hypot(x - x2, y - y2) <= 8) {
|
|
3150
|
+
return { drawing, target: "handle", pointIndex: 1 };
|
|
3132
3151
|
}
|
|
3133
3152
|
if (distanceToSegment(x, y, x1, y1, x2, y2) <= 6) {
|
|
3134
3153
|
return { drawing, target: "line" };
|
|
@@ -3236,6 +3255,39 @@ function createChart(element, options = {}) {
|
|
|
3236
3255
|
}
|
|
3237
3256
|
return false;
|
|
3238
3257
|
};
|
|
3258
|
+
const updateDrawingDrag = (x, y) => {
|
|
3259
|
+
if (!drawingDragState) {
|
|
3260
|
+
return false;
|
|
3261
|
+
}
|
|
3262
|
+
const currentPoint = drawingPointFromCanvas(x, y);
|
|
3263
|
+
if (!currentPoint) {
|
|
3264
|
+
return true;
|
|
3265
|
+
}
|
|
3266
|
+
const deltaIndex = currentPoint.index - drawingDragState.startCanvasPoint.index;
|
|
3267
|
+
const deltaPrice = currentPoint.price - drawingDragState.startCanvasPoint.price;
|
|
3268
|
+
drawings = drawings.map((drawing) => {
|
|
3269
|
+
if (drawing.id !== drawingDragState?.drawingId || drawing.locked) {
|
|
3270
|
+
return drawing;
|
|
3271
|
+
}
|
|
3272
|
+
if (drawingDragState.target === "handle") {
|
|
3273
|
+
return {
|
|
3274
|
+
...drawing,
|
|
3275
|
+
points: drawing.points.map(
|
|
3276
|
+
(point, index) => index === (drawingDragState?.pointIndex ?? 0) ? normalizeDrawingPoint(currentPoint.index, currentPoint.price) : point
|
|
3277
|
+
)
|
|
3278
|
+
};
|
|
3279
|
+
}
|
|
3280
|
+
return {
|
|
3281
|
+
...drawing,
|
|
3282
|
+
points: drawingDragState.startPoints.map(
|
|
3283
|
+
(point) => normalizeDrawingPoint(point.index + deltaIndex, point.price + deltaPrice)
|
|
3284
|
+
)
|
|
3285
|
+
};
|
|
3286
|
+
});
|
|
3287
|
+
emitDrawingsChange();
|
|
3288
|
+
draw();
|
|
3289
|
+
return true;
|
|
3290
|
+
};
|
|
3239
3291
|
let isDragging = false;
|
|
3240
3292
|
let dragMode = null;
|
|
3241
3293
|
let lastPointerX = 0;
|
|
@@ -3275,6 +3327,7 @@ function createChart(element, options = {}) {
|
|
|
3275
3327
|
pointerDownInfo = null;
|
|
3276
3328
|
orderDragState = null;
|
|
3277
3329
|
actionDragState = null;
|
|
3330
|
+
drawingDragState = null;
|
|
3278
3331
|
canvas.style.cursor = "default";
|
|
3279
3332
|
setCrosshairPoint(null);
|
|
3280
3333
|
};
|
|
@@ -3367,11 +3420,26 @@ function createChart(element, options = {}) {
|
|
|
3367
3420
|
drawingSelectHandler?.({
|
|
3368
3421
|
drawing: serializeDrawing(drawingHit.drawing),
|
|
3369
3422
|
target: drawingHit.target,
|
|
3423
|
+
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
3370
3424
|
x: point.x,
|
|
3371
3425
|
y: point.y
|
|
3372
3426
|
});
|
|
3427
|
+
if (!drawingHit.drawing.locked) {
|
|
3428
|
+
const startCanvasPoint = drawingPointFromCanvas(point.x, point.y);
|
|
3429
|
+
if (startCanvasPoint) {
|
|
3430
|
+
drawingDragState = {
|
|
3431
|
+
drawingId: drawingHit.drawing.id,
|
|
3432
|
+
target: drawingHit.target,
|
|
3433
|
+
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
3434
|
+
startCanvasPoint,
|
|
3435
|
+
startPoints: drawingHit.drawing.points.map((drawingPoint) => ({ ...drawingPoint }))
|
|
3436
|
+
};
|
|
3437
|
+
activePointerId = event.pointerId;
|
|
3438
|
+
canvas.setPointerCapture(event.pointerId);
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3373
3441
|
setCrosshairPoint(null);
|
|
3374
|
-
canvas.style.cursor = "pointer";
|
|
3442
|
+
canvas.style.cursor = drawingHit.drawing.locked ? "pointer" : drawingHit.target === "handle" ? "grab" : "move";
|
|
3375
3443
|
return;
|
|
3376
3444
|
}
|
|
3377
3445
|
}
|
|
@@ -3411,6 +3479,15 @@ function createChart(element, options = {}) {
|
|
|
3411
3479
|
pointerDownInfo.moved = true;
|
|
3412
3480
|
}
|
|
3413
3481
|
}
|
|
3482
|
+
if (drawingDragState) {
|
|
3483
|
+
if (activePointerId !== null && event.pointerId !== activePointerId) {
|
|
3484
|
+
return;
|
|
3485
|
+
}
|
|
3486
|
+
updateDrawingDrag(point.x, point.y);
|
|
3487
|
+
canvas.style.cursor = drawingDragState.target === "handle" ? "grabbing" : "move";
|
|
3488
|
+
setCrosshairPoint(null);
|
|
3489
|
+
return;
|
|
3490
|
+
}
|
|
3414
3491
|
if (draftDrawing && activeDrawingTool === "trendline") {
|
|
3415
3492
|
const nextPoint = drawingPointFromCanvas(point.x, point.y);
|
|
3416
3493
|
if (nextPoint) {
|
|
@@ -3494,7 +3571,8 @@ function createChart(element, options = {}) {
|
|
|
3494
3571
|
return;
|
|
3495
3572
|
}
|
|
3496
3573
|
if (!activeDrawingTool && getDrawingHit(point.x, point.y)) {
|
|
3497
|
-
|
|
3574
|
+
const drawingHit = getDrawingHit(point.x, point.y);
|
|
3575
|
+
canvas.style.cursor = drawingHit?.drawing.locked ? "pointer" : drawingHit?.target === "handle" ? "grab" : "move";
|
|
3498
3576
|
setCrosshairPoint(null);
|
|
3499
3577
|
return;
|
|
3500
3578
|
}
|
|
@@ -3590,6 +3668,10 @@ function createChart(element, options = {}) {
|
|
|
3590
3668
|
}
|
|
3591
3669
|
actionDragState = null;
|
|
3592
3670
|
}
|
|
3671
|
+
if (drawingDragState) {
|
|
3672
|
+
drawingDragState = null;
|
|
3673
|
+
emitDrawingsChange();
|
|
3674
|
+
}
|
|
3593
3675
|
isDragging = false;
|
|
3594
3676
|
dragMode = null;
|
|
3595
3677
|
activePointerId = null;
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -935,6 +935,7 @@ function createChart(element, options = {}) {
|
|
|
935
935
|
let drawings = (options.drawings ?? []).map((drawing) => normalizeDrawingState(drawing));
|
|
936
936
|
let activeDrawingTool = null;
|
|
937
937
|
let draftDrawing = null;
|
|
938
|
+
let drawingDragState = null;
|
|
938
939
|
let drawingsChangeHandler = null;
|
|
939
940
|
let drawingSelectHandler = null;
|
|
940
941
|
const emitDrawingsChange = () => {
|
|
@@ -2019,10 +2020,12 @@ function createChart(element, options = {}) {
|
|
|
2019
2020
|
const point = drawing.points[0];
|
|
2020
2021
|
if (point) {
|
|
2021
2022
|
const y = clamp(yFromPrice(point.price), chartTop + 1, chartBottom - 1);
|
|
2023
|
+
const handleX = chartRight - 64;
|
|
2022
2024
|
ctx.beginPath();
|
|
2023
2025
|
ctx.moveTo(crisp(chartLeft), crisp(y));
|
|
2024
2026
|
ctx.lineTo(crisp(chartRight), crisp(y));
|
|
2025
2027
|
ctx.stroke();
|
|
2028
|
+
drawDrawingHandle(handleX, y, drawing.color);
|
|
2026
2029
|
}
|
|
2027
2030
|
} else if (drawing.type === "trendline") {
|
|
2028
2031
|
const first = drawing.points[0];
|
|
@@ -3067,6 +3070,15 @@ function createChart(element, options = {}) {
|
|
|
3067
3070
|
...time ? { time: time.toISOString() } : {}
|
|
3068
3071
|
};
|
|
3069
3072
|
};
|
|
3073
|
+
const normalizeDrawingPoint = (index, price) => {
|
|
3074
|
+
const roundedIndex = Math.round(index);
|
|
3075
|
+
const time = getTimeForIndex(roundedIndex);
|
|
3076
|
+
return {
|
|
3077
|
+
index,
|
|
3078
|
+
price: roundToPricePrecision(price),
|
|
3079
|
+
...time ? { time: time.toISOString() } : {}
|
|
3080
|
+
};
|
|
3081
|
+
};
|
|
3070
3082
|
const canvasXFromDrawingPoint = (point) => {
|
|
3071
3083
|
if (!drawState) return 0;
|
|
3072
3084
|
return drawState.chartLeft + (point.index + 0.5 - drawState.xStart) / drawState.xSpan * drawState.chartWidth;
|
|
@@ -3092,6 +3104,10 @@ function createChart(element, options = {}) {
|
|
|
3092
3104
|
const point = drawing.points[0];
|
|
3093
3105
|
if (!point) continue;
|
|
3094
3106
|
const lineY = canvasYFromDrawingPrice(point.price);
|
|
3107
|
+
const handleX = drawState ? drawState.chartRight - 64 : 0;
|
|
3108
|
+
if (Math.hypot(x - handleX, y - lineY) <= 8) {
|
|
3109
|
+
return { drawing, target: "handle", pointIndex: 0 };
|
|
3110
|
+
}
|
|
3095
3111
|
if (Math.abs(y - lineY) <= 7) {
|
|
3096
3112
|
return { drawing, target: "line" };
|
|
3097
3113
|
}
|
|
@@ -3103,8 +3119,11 @@ function createChart(element, options = {}) {
|
|
|
3103
3119
|
const y1 = canvasYFromDrawingPrice(first.price);
|
|
3104
3120
|
const x2 = canvasXFromDrawingPoint(second);
|
|
3105
3121
|
const y2 = canvasYFromDrawingPrice(second.price);
|
|
3106
|
-
if (Math.hypot(x - x1, y - y1) <= 8
|
|
3107
|
-
return { drawing, target: "handle" };
|
|
3122
|
+
if (Math.hypot(x - x1, y - y1) <= 8) {
|
|
3123
|
+
return { drawing, target: "handle", pointIndex: 0 };
|
|
3124
|
+
}
|
|
3125
|
+
if (Math.hypot(x - x2, y - y2) <= 8) {
|
|
3126
|
+
return { drawing, target: "handle", pointIndex: 1 };
|
|
3108
3127
|
}
|
|
3109
3128
|
if (distanceToSegment(x, y, x1, y1, x2, y2) <= 6) {
|
|
3110
3129
|
return { drawing, target: "line" };
|
|
@@ -3212,6 +3231,39 @@ function createChart(element, options = {}) {
|
|
|
3212
3231
|
}
|
|
3213
3232
|
return false;
|
|
3214
3233
|
};
|
|
3234
|
+
const updateDrawingDrag = (x, y) => {
|
|
3235
|
+
if (!drawingDragState) {
|
|
3236
|
+
return false;
|
|
3237
|
+
}
|
|
3238
|
+
const currentPoint = drawingPointFromCanvas(x, y);
|
|
3239
|
+
if (!currentPoint) {
|
|
3240
|
+
return true;
|
|
3241
|
+
}
|
|
3242
|
+
const deltaIndex = currentPoint.index - drawingDragState.startCanvasPoint.index;
|
|
3243
|
+
const deltaPrice = currentPoint.price - drawingDragState.startCanvasPoint.price;
|
|
3244
|
+
drawings = drawings.map((drawing) => {
|
|
3245
|
+
if (drawing.id !== drawingDragState?.drawingId || drawing.locked) {
|
|
3246
|
+
return drawing;
|
|
3247
|
+
}
|
|
3248
|
+
if (drawingDragState.target === "handle") {
|
|
3249
|
+
return {
|
|
3250
|
+
...drawing,
|
|
3251
|
+
points: drawing.points.map(
|
|
3252
|
+
(point, index) => index === (drawingDragState?.pointIndex ?? 0) ? normalizeDrawingPoint(currentPoint.index, currentPoint.price) : point
|
|
3253
|
+
)
|
|
3254
|
+
};
|
|
3255
|
+
}
|
|
3256
|
+
return {
|
|
3257
|
+
...drawing,
|
|
3258
|
+
points: drawingDragState.startPoints.map(
|
|
3259
|
+
(point) => normalizeDrawingPoint(point.index + deltaIndex, point.price + deltaPrice)
|
|
3260
|
+
)
|
|
3261
|
+
};
|
|
3262
|
+
});
|
|
3263
|
+
emitDrawingsChange();
|
|
3264
|
+
draw();
|
|
3265
|
+
return true;
|
|
3266
|
+
};
|
|
3215
3267
|
let isDragging = false;
|
|
3216
3268
|
let dragMode = null;
|
|
3217
3269
|
let lastPointerX = 0;
|
|
@@ -3251,6 +3303,7 @@ function createChart(element, options = {}) {
|
|
|
3251
3303
|
pointerDownInfo = null;
|
|
3252
3304
|
orderDragState = null;
|
|
3253
3305
|
actionDragState = null;
|
|
3306
|
+
drawingDragState = null;
|
|
3254
3307
|
canvas.style.cursor = "default";
|
|
3255
3308
|
setCrosshairPoint(null);
|
|
3256
3309
|
};
|
|
@@ -3343,11 +3396,26 @@ function createChart(element, options = {}) {
|
|
|
3343
3396
|
drawingSelectHandler?.({
|
|
3344
3397
|
drawing: serializeDrawing(drawingHit.drawing),
|
|
3345
3398
|
target: drawingHit.target,
|
|
3399
|
+
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
3346
3400
|
x: point.x,
|
|
3347
3401
|
y: point.y
|
|
3348
3402
|
});
|
|
3403
|
+
if (!drawingHit.drawing.locked) {
|
|
3404
|
+
const startCanvasPoint = drawingPointFromCanvas(point.x, point.y);
|
|
3405
|
+
if (startCanvasPoint) {
|
|
3406
|
+
drawingDragState = {
|
|
3407
|
+
drawingId: drawingHit.drawing.id,
|
|
3408
|
+
target: drawingHit.target,
|
|
3409
|
+
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
3410
|
+
startCanvasPoint,
|
|
3411
|
+
startPoints: drawingHit.drawing.points.map((drawingPoint) => ({ ...drawingPoint }))
|
|
3412
|
+
};
|
|
3413
|
+
activePointerId = event.pointerId;
|
|
3414
|
+
canvas.setPointerCapture(event.pointerId);
|
|
3415
|
+
}
|
|
3416
|
+
}
|
|
3349
3417
|
setCrosshairPoint(null);
|
|
3350
|
-
canvas.style.cursor = "pointer";
|
|
3418
|
+
canvas.style.cursor = drawingHit.drawing.locked ? "pointer" : drawingHit.target === "handle" ? "grab" : "move";
|
|
3351
3419
|
return;
|
|
3352
3420
|
}
|
|
3353
3421
|
}
|
|
@@ -3387,6 +3455,15 @@ function createChart(element, options = {}) {
|
|
|
3387
3455
|
pointerDownInfo.moved = true;
|
|
3388
3456
|
}
|
|
3389
3457
|
}
|
|
3458
|
+
if (drawingDragState) {
|
|
3459
|
+
if (activePointerId !== null && event.pointerId !== activePointerId) {
|
|
3460
|
+
return;
|
|
3461
|
+
}
|
|
3462
|
+
updateDrawingDrag(point.x, point.y);
|
|
3463
|
+
canvas.style.cursor = drawingDragState.target === "handle" ? "grabbing" : "move";
|
|
3464
|
+
setCrosshairPoint(null);
|
|
3465
|
+
return;
|
|
3466
|
+
}
|
|
3390
3467
|
if (draftDrawing && activeDrawingTool === "trendline") {
|
|
3391
3468
|
const nextPoint = drawingPointFromCanvas(point.x, point.y);
|
|
3392
3469
|
if (nextPoint) {
|
|
@@ -3470,7 +3547,8 @@ function createChart(element, options = {}) {
|
|
|
3470
3547
|
return;
|
|
3471
3548
|
}
|
|
3472
3549
|
if (!activeDrawingTool && getDrawingHit(point.x, point.y)) {
|
|
3473
|
-
|
|
3550
|
+
const drawingHit = getDrawingHit(point.x, point.y);
|
|
3551
|
+
canvas.style.cursor = drawingHit?.drawing.locked ? "pointer" : drawingHit?.target === "handle" ? "grab" : "move";
|
|
3474
3552
|
setCrosshairPoint(null);
|
|
3475
3553
|
return;
|
|
3476
3554
|
}
|
|
@@ -3566,6 +3644,10 @@ function createChart(element, options = {}) {
|
|
|
3566
3644
|
}
|
|
3567
3645
|
actionDragState = null;
|
|
3568
3646
|
}
|
|
3647
|
+
if (drawingDragState) {
|
|
3648
|
+
drawingDragState = null;
|
|
3649
|
+
emitDrawingsChange();
|
|
3650
|
+
}
|
|
3569
3651
|
isDragging = false;
|
|
3570
3652
|
dragMode = null;
|
|
3571
3653
|
activePointerId = null;
|