@operato/scene-scichart 9.0.0-beta.7 → 9.0.0

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.
@@ -211,7 +211,7 @@ export async function buildSciChart(config, container, { fontSize = 14, fontFami
211
211
  var { theme, tooltip = true, animation = true, legend = {
212
212
  display: true,
213
213
  position: 'top'
214
- }, scales: fromScales, xGridLine = false, yGridLine = false, y2ndGridLine = false, stacked = false, multiAxis = false, annotations = [] } = options || {};
214
+ }, scales: fromScales, xGridLine = false, yGridLine = false, y2ndGridLine = false, stacked = false, multiAxis = false } = options || {};
215
215
  var baseColor = getBaseColorFromTheme(theme);
216
216
  if (theme === 'auto') {
217
217
  theme = getThemeFromBrowser();
@@ -250,9 +250,31 @@ export async function buildSciChart(config, container, { fontSize = 14, fontFami
250
250
  showAxisLabel: true /* show x-axis label for cursor */,
251
251
  modifierGroup: grouped,
252
252
  tooltipDataTemplate: (seriesInfo) => {
253
+ var _a, _b;
253
254
  const valuesWithLabels = [];
254
255
  const xySeriesInfo = seriesInfo;
255
- valuesWithLabels.push(xySeriesInfo.formattedYValue);
256
+ let formattedValue = xySeriesInfo.yValue;
257
+ // 시리즈 이름으로 인덱스 찾기
258
+ const datasetIdx = datasets.findIndex(ds => ds.label === xySeriesInfo.seriesName);
259
+ const thisDataset = datasets[datasetIdx >= 0 ? datasetIdx : index];
260
+ const valueFormat = (thisDataset === null || thisDataset === void 0 ? void 0 : thisDataset.valueFormat) || '0.##';
261
+ if (typeof formattedValue === 'number') {
262
+ // prefix, numberFormat, suffix 분리
263
+ const match = valueFormat.match(/^(.*?)([#,0.]+)(.*?)$/);
264
+ const prefix = match ? match[1] : '';
265
+ const numberFormat = match ? match[2] : valueFormat;
266
+ const suffix = match ? match[3] : '';
267
+ const decimalPart = (_a = numberFormat.split('.')[1]) === null || _a === void 0 ? void 0 : _a.replace(/[^#0]/g, '');
268
+ let minFrac = decimalPart ? decimalPart.length : 0;
269
+ let maxFrac = ((_b = numberFormat.split('.')[1]) === null || _b === void 0 ? void 0 : _b.length) || 2;
270
+ const formattedNumber = new Intl.NumberFormat(undefined, {
271
+ minimumFractionDigits: minFrac,
272
+ maximumFractionDigits: maxFrac,
273
+ useGrouping: numberFormat.includes(',')
274
+ }).format(formattedValue);
275
+ formattedValue = `${prefix}${formattedNumber}${suffix}`;
276
+ }
277
+ valuesWithLabels.push(formattedValue);
256
278
  return valuesWithLabels;
257
279
  }
258
280
  });
@@ -278,85 +300,6 @@ export async function buildSciChart(config, container, { fontSize = 14, fontFami
278
300
  sciChartSurface.renderableSeries.add(stackedMountainCollection);
279
301
  }
280
302
  }
281
- if (annotations) {
282
- annotations.forEach(annotation => {
283
- let sciAnnotation;
284
- let horizontalAnchorPoint = annotation.horizontalAnchorPoint == 'Right'
285
- ? EHorizontalAnchorPoint.Right
286
- : annotation.horizontalAnchorPoint == 'Left'
287
- ? EHorizontalAnchorPoint.Left
288
- : EHorizontalAnchorPoint.Center;
289
- let verticalAnchorPoint = annotation.verticalAnchorPoint == 'Top'
290
- ? EVerticalAnchorPoint.Top
291
- : annotation.verticalAnchorPoint == 'Bottom'
292
- ? EVerticalAnchorPoint.Bottom
293
- : EVerticalAnchorPoint.Center;
294
- switch (annotation.type) {
295
- case 'text':
296
- sciAnnotation = new TextAnnotation({
297
- x1: annotation.x1,
298
- y1: annotation.y1,
299
- text: annotation.text,
300
- horizontalAnchorPoint,
301
- verticalAnchorPoint,
302
- fontSize: annotation.fontSize,
303
- fontFamily: annotation.fontFamily,
304
- textColor: convertColor(annotation.stroke, fontColor),
305
- xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
306
- yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue)
307
- });
308
- break;
309
- case 'line':
310
- sciAnnotation = new LineAnnotation({
311
- x1: annotation.x1,
312
- y1: annotation.y1,
313
- x2: annotation.x2,
314
- y2: annotation.y2,
315
- stroke: convertColor(annotation.stroke, '#FF0000'),
316
- strokeThickness: annotation.strokeThickness,
317
- xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
318
- yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue)
319
- });
320
- break;
321
- case 'box':
322
- sciAnnotation = new BoxAnnotation({
323
- x1: annotation.x1,
324
- y1: annotation.y1,
325
- x2: annotation.x2,
326
- y2: annotation.y2,
327
- fill: convertColor(annotation.fill, '#FF0000'),
328
- stroke: convertColor(annotation.stroke, '#FF0000'),
329
- strokeThickness: annotation.strokeThickness,
330
- xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
331
- yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue)
332
- });
333
- break;
334
- case 'horizontalLine':
335
- sciAnnotation = new HorizontalLineAnnotation({
336
- y1: annotation.y1,
337
- stroke: convertColor(annotation.stroke, '#FF0000'),
338
- strokeThickness: annotation.strokeThickness,
339
- xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
340
- yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue)
341
- });
342
- break;
343
- case 'verticalLine':
344
- sciAnnotation = new VerticalLineAnnotation({
345
- x1: annotation.x1,
346
- stroke: convertColor(annotation.stroke, '#FF0000'),
347
- strokeThickness: annotation.strokeThickness,
348
- xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
349
- yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue)
350
- });
351
- break;
352
- default:
353
- break;
354
- }
355
- if (sciAnnotation) {
356
- sciChartSurface.annotations.add(sciAnnotation);
357
- }
358
- });
359
- }
360
303
  sciChartSurface.chartModifiers.add(new RubberBandXyZoomModifier({ executeOn: EExecuteOn.MouseRightButton, modifierGroup: grouped }),
361
304
  // new ZoomPanModifier({ xyDirection: EXyDirection.XDirection }),
362
305
  new ZoomPanModifier({ xyDirection: EXyDirection.XDirection }), new MouseWheelZoomModifier({ xyDirection: EXyDirection.XDirection }), new ZoomExtentsModifier(), new XAxisDragModifier(), new YAxisDragModifier());
@@ -458,4 +401,407 @@ function getDefaultYAxis(wasmContext, sciChartSurface) {
458
401
  });
459
402
  sciChartSurface.yAxes.add(yAxis);
460
403
  }
404
+ // Helper 함수 - verticalAnchorPoint에 따라 적절한 y1 값을 반환
405
+ function getYPositionByAnchor(anchor) {
406
+ if (anchor === EVerticalAnchorPoint.Top) {
407
+ return 0.05; // 상단에서 5% 위치
408
+ }
409
+ else if (anchor === EVerticalAnchorPoint.Center) {
410
+ return 0.5; // 중앙
411
+ }
412
+ else if (anchor === EVerticalAnchorPoint.Bottom) {
413
+ return 0.95; // 차트 맨 아래
414
+ }
415
+ // 기본값 (Bottom이거나 값이 없는 경우)
416
+ return 0.95; // 바닥에서 5% 위치
417
+ }
418
+ // Helper 함수 - verticalAnchorPoint에 따라 적절한 좌표 모드 반환
419
+ function getYCoordModeByAnchor(anchor) {
420
+ // verticalAnchorPoint 값과 상관없이 상대 좌표 사용
421
+ return ECoordinateMode.Relative;
422
+ }
423
+ export function updateAnnotations(sciChartSurface, annotations = [], fromData, rawData = [], fontFamily, fontColor) {
424
+ sciChartSurface.annotations.clear();
425
+ if (annotations) {
426
+ annotations.forEach(annotation => {
427
+ let sciAnnotation;
428
+ let horizontalAnchorPoint = annotation.horizontalAnchorPoint == 'Right'
429
+ ? EHorizontalAnchorPoint.Right
430
+ : annotation.horizontalAnchorPoint == 'Left'
431
+ ? EHorizontalAnchorPoint.Left
432
+ : EHorizontalAnchorPoint.Center;
433
+ let verticalAnchorPoint = annotation.verticalAnchorPoint == 'Top'
434
+ ? EVerticalAnchorPoint.Top
435
+ : annotation.verticalAnchorPoint == 'Bottom'
436
+ ? EVerticalAnchorPoint.Bottom
437
+ : EVerticalAnchorPoint.Center;
438
+ // dataKey가 있는 경우 데이터와 연동
439
+ if (annotation.dataKey && rawData && rawData.length > 0) {
440
+ const attrX = (fromData === null || fromData === void 0 ? void 0 : fromData.labelDataKey) || ''; // X축 데이터 키 가져오기
441
+ if (annotation.type === 'verticalLine') {
442
+ // 수직 라인: falsy => truthy 변화 지점에만 표시
443
+ let prevValue = undefined;
444
+ for (let i = 0; i < rawData.length; i++) {
445
+ // 원본 데이터에서 직접 값 가져오기
446
+ const currentValue = rawData[i][annotation.dataKey];
447
+ const isChanged = prevValue !== currentValue;
448
+ const isTruthy = !!currentValue || annotation.text;
449
+ if (isTruthy && isChanged) {
450
+ // falsy에서 truthy로 변화한 지점
451
+ // X 값은 인덱스나 타임스탬프 사용
452
+ const xValue = attrX ? new Date(rawData[i][attrX]).getTime() / 1000 : i;
453
+ // 수직선 추가
454
+ const sciVerticalLine = new VerticalLineAnnotation({
455
+ x1: xValue,
456
+ stroke: convertColor(annotation.stroke, '#FF0000'),
457
+ strokeThickness: annotation.strokeThickness,
458
+ xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
459
+ yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue)
460
+ });
461
+ sciChartSurface.annotations.add(sciVerticalLine);
462
+ // 텍스트 레이블 추가
463
+ // if (annotation.text !== undefined || currentValue !== undefined) {
464
+ // 표시할 텍스트 결정
465
+ const labelText = currentValue ? String(currentValue) : annotation.text;
466
+ // 텍스트 주석 추가 (수직선 상단에)
467
+ const sciTextAnnotation = new TextAnnotation({
468
+ // 동일한 X 위치 사용
469
+ x1: xValue,
470
+ // verticalAnchorPoint에 따라 Y 위치 결정
471
+ y1: getYPositionByAnchor(annotation.verticalAnchorPoint),
472
+ text: labelText,
473
+ // 가운데 정렬
474
+ horizontalAnchorPoint: (annotation.horizontalAnchorPoint ||
475
+ EHorizontalAnchorPoint.Center),
476
+ // 텍스트의 하단이 y1에 위치
477
+ verticalAnchorPoint: (annotation.verticalAnchorPoint ||
478
+ EVerticalAnchorPoint.Bottom),
479
+ fontFamily: annotation.fontFamily || fontFamily,
480
+ fontSize: annotation.fontSize || 14,
481
+ textColor: convertColor(annotation.stroke, '#FF0000'),
482
+ background: 'rgba(255, 255, 255, 0.7)', // 텍스트 배경 추가
483
+ padding: { left: 5, top: 5, right: 5, bottom: 5 }, // 패딩 추가
484
+ xCoordinateMode: ECoordinateMode.DataValue,
485
+ // verticalAnchorPoint에 따라 좌표 모드 결정
486
+ yCoordinateMode: getYCoordModeByAnchor(annotation.verticalAnchorPoint)
487
+ });
488
+ sciChartSurface.annotations.add(sciTextAnnotation);
489
+ // }
490
+ }
491
+ prevValue = currentValue;
492
+ }
493
+ // 기본 annotation 처리 건너뛰기
494
+ return;
495
+ }
496
+ else if (annotation.type === 'text') {
497
+ // 텍스트: 해당 값을 그대로 출력
498
+ for (let i = 0; i < rawData.length; i++) {
499
+ // 원본 데이터에서 직접 값 가져오기
500
+ const value = rawData[i][annotation.dataKey];
501
+ // null이나 undefined가 아닌 값만 표시
502
+ if (value !== undefined && value !== null) {
503
+ // X 값은 인덱스나 타임스탬프 사용
504
+ const xValue = attrX ? new Date(rawData[i][attrX]).getTime() / 1000 : i;
505
+ const sciTextAnnotation = new TextAnnotation({
506
+ x1: xValue,
507
+ y1: value,
508
+ text: String(value),
509
+ horizontalAnchorPoint,
510
+ verticalAnchorPoint,
511
+ fontSize: annotation.fontSize,
512
+ fontFamily: annotation.fontFamily,
513
+ textColor: convertColor(annotation.stroke, fontColor),
514
+ xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
515
+ yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue)
516
+ });
517
+ sciChartSurface.annotations.add(sciTextAnnotation);
518
+ }
519
+ }
520
+ // 기본 annotation 처리 건너뛰기
521
+ return;
522
+ }
523
+ else {
524
+ // 다른 타입의 annotation은 원래 로직으로 처리
525
+ // 원본 데이터에서 값 추출
526
+ const dataValues = rawData.map(item => item[annotation.dataKey]).filter(v => v !== undefined);
527
+ if (dataValues.length > 0) {
528
+ // annotation 타입에 따라 데이터 값을 적용
529
+ if (annotation.type === 'horizontalLine') {
530
+ annotation.y1 = dataValues[0];
531
+ }
532
+ else if (annotation.type === 'line' || annotation.type === 'box') {
533
+ // 데이터 값이 최소 한 개 이상인 경우에만 적용
534
+ if (annotation.yCoordinateMode === 'DataValue') {
535
+ annotation.y1 = dataValues[0];
536
+ }
537
+ if (annotation.xCoordinateMode === 'DataValue' && !annotation.x1) {
538
+ annotation.x1 = 0;
539
+ }
540
+ // 두 번째 지점이 필요한 경우 (line, box)
541
+ if (dataValues.length > 1) {
542
+ if (annotation.yCoordinateMode === 'DataValue') {
543
+ annotation.y2 = dataValues[dataValues.length - 1];
544
+ }
545
+ if (annotation.xCoordinateMode === 'DataValue' && !annotation.x2) {
546
+ annotation.x2 = dataValues.length - 1;
547
+ }
548
+ }
549
+ }
550
+ }
551
+ }
552
+ }
553
+ else {
554
+ // 기본 annotation 생성 (dataKey가 없거나 rawData가 없는 경우)
555
+ switch (annotation.type) {
556
+ case 'text':
557
+ sciAnnotation = new TextAnnotation({
558
+ x1: annotation.x1,
559
+ y1: annotation.y1,
560
+ text: annotation.text,
561
+ horizontalAnchorPoint,
562
+ verticalAnchorPoint,
563
+ fontSize: annotation.fontSize,
564
+ fontFamily: annotation.fontFamily,
565
+ textColor: convertColor(annotation.stroke, fontColor),
566
+ xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
567
+ yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue)
568
+ });
569
+ break;
570
+ case 'line':
571
+ sciAnnotation = new LineAnnotation({
572
+ x1: annotation.x1,
573
+ y1: annotation.y1,
574
+ x2: annotation.x2,
575
+ y2: annotation.y2,
576
+ stroke: convertColor(annotation.stroke, '#FF0000'),
577
+ strokeThickness: annotation.strokeThickness,
578
+ xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
579
+ yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue)
580
+ });
581
+ break;
582
+ case 'box':
583
+ sciAnnotation = new BoxAnnotation({
584
+ x1: annotation.x1,
585
+ y1: annotation.y1,
586
+ x2: annotation.x2,
587
+ y2: annotation.y2,
588
+ fill: convertColor(annotation.fill, '#FF0000'),
589
+ stroke: convertColor(annotation.stroke, '#FF0000'),
590
+ strokeThickness: annotation.strokeThickness,
591
+ xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
592
+ yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue)
593
+ });
594
+ break;
595
+ case 'horizontalLine':
596
+ sciAnnotation = new HorizontalLineAnnotation({
597
+ y1: annotation.y1,
598
+ stroke: convertColor(annotation.stroke, '#FF0000'),
599
+ strokeThickness: annotation.strokeThickness,
600
+ xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
601
+ yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue)
602
+ });
603
+ break;
604
+ case 'verticalLine':
605
+ sciAnnotation = new VerticalLineAnnotation({
606
+ x1: annotation.x1,
607
+ stroke: convertColor(annotation.stroke, '#FF0000'),
608
+ strokeThickness: annotation.strokeThickness,
609
+ xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
610
+ yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue)
611
+ });
612
+ // 텍스트가 있는 경우에만 텍스트 주석 추가
613
+ if (annotation.text) {
614
+ // 수직선을 먼저 추가
615
+ if (sciAnnotation) {
616
+ sciChartSurface.annotations.add(sciAnnotation);
617
+ }
618
+ // 텍스트 주석 생성
619
+ const textAnnotation = new TextAnnotation({
620
+ x1: annotation.x1,
621
+ y1: getYPositionByAnchor(annotation.verticalAnchorPoint),
622
+ text: annotation.text,
623
+ horizontalAnchorPoint: (annotation.horizontalAnchorPoint ||
624
+ EHorizontalAnchorPoint.Center),
625
+ verticalAnchorPoint: (annotation.verticalAnchorPoint ||
626
+ EVerticalAnchorPoint.Bottom),
627
+ fontFamily: annotation.fontFamily || fontFamily,
628
+ fontSize: annotation.fontSize || 14,
629
+ textColor: convertColor(annotation.stroke, '#FF0000'),
630
+ background: 'rgba(255, 255, 255, 0.7)', // 텍스트 배경 추가
631
+ padding: { left: 5, top: 5, right: 5, bottom: 5 }, // 패딩 추가
632
+ xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
633
+ yCoordinateMode: getYCoordModeByAnchor(annotation.verticalAnchorPoint)
634
+ });
635
+ // 텍스트 주석 추가
636
+ sciChartSurface.annotations.add(textAnnotation);
637
+ sciAnnotation = null; // 이미 추가했으므로 아래에서 다시 추가하지 않도록 null로 설정
638
+ }
639
+ break;
640
+ default:
641
+ console.error('Unknown annotation type:', annotation.type);
642
+ break;
643
+ }
644
+ }
645
+ // switch (annotation.type) {
646
+ // case 'text':
647
+ // sciAnnotation = new TextAnnotation({
648
+ // x1: annotation.x1,
649
+ // y1: annotation.y1,
650
+ // text: annotation.text,
651
+ // horizontalAnchorPoint,
652
+ // verticalAnchorPoint,
653
+ // fontSize: annotation.fontSize,
654
+ // fontFamily: annotation.fontFamily,
655
+ // textColor: convertColor(annotation.stroke, fontColor),
656
+ // xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue) as ECoordinateMode,
657
+ // yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue) as ECoordinateMode
658
+ // })
659
+ // break
660
+ // case 'line':
661
+ // sciAnnotation = new LineAnnotation({
662
+ // x1: annotation.x1,
663
+ // y1: annotation.y1,
664
+ // x2: annotation.x2,
665
+ // y2: annotation.y2,
666
+ // stroke: convertColor(annotation.stroke, '#FF0000'),
667
+ // strokeThickness: annotation.strokeThickness,
668
+ // xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue) as ECoordinateMode,
669
+ // yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue) as ECoordinateMode
670
+ // })
671
+ // break
672
+ // case 'box':
673
+ // sciAnnotation = new BoxAnnotation({
674
+ // x1: annotation.x1,
675
+ // y1: annotation.y1,
676
+ // x2: annotation.x2,
677
+ // y2: annotation.y2,
678
+ // fill: convertColor(annotation.fill, '#FF0000'),
679
+ // stroke: convertColor(annotation.stroke, '#FF0000'),
680
+ // strokeThickness: annotation.strokeThickness,
681
+ // xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue) as ECoordinateMode,
682
+ // yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue) as ECoordinateMode
683
+ // })
684
+ // break
685
+ // case 'horizontalLine':
686
+ // sciAnnotation = new HorizontalLineAnnotation({
687
+ // y1: annotation.y1,
688
+ // stroke: convertColor(annotation.stroke, '#FF0000'),
689
+ // strokeThickness: annotation.strokeThickness,
690
+ // xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue) as ECoordinateMode,
691
+ // yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue) as ECoordinateMode
692
+ // })
693
+ // break
694
+ // case 'verticalLine':
695
+ // sciAnnotation = new VerticalLineAnnotation({
696
+ // x1: annotation.x1,
697
+ // stroke: convertColor(annotation.stroke, '#FF0000'),
698
+ // strokeThickness: annotation.strokeThickness,
699
+ // xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue) as ECoordinateMode,
700
+ // yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue) as ECoordinateMode
701
+ // })
702
+ // break
703
+ // default:
704
+ // break
705
+ // }
706
+ if (sciAnnotation) {
707
+ sciChartSurface.annotations.add(sciAnnotation);
708
+ }
709
+ });
710
+ }
711
+ }
712
+ /**
713
+ * 데이터 append 시, 값이 변경된 경우(이전 값과 다를 때)만 annotation을 추가하고,
714
+ * annotation의 텍스트는 변경된 값이 되도록 한다.
715
+ */
716
+ export function addAnnotationsOnDataChange(sciChartSurface, annotations = [], fromData, prevData = [], appendum = [], fontFamily, fontColor) {
717
+ if (!annotations || !appendum || !appendum.length)
718
+ return;
719
+ const attrX = (fromData === null || fromData === void 0 ? void 0 : fromData.labelDataKey) || '';
720
+ annotations
721
+ .filter(annotation => annotation.dataKey && (annotation.type == 'text' || annotation.type == 'verticalLine'))
722
+ .forEach(annotation => {
723
+ if (!annotation.dataKey)
724
+ return;
725
+ let prevValue = prevData.length > 0 ? prevData[prevData.length - 1][annotation.dataKey] : undefined;
726
+ appendum.forEach((item, idx) => {
727
+ const currentValue = item[annotation.dataKey];
728
+ const isChanged = prevValue !== currentValue;
729
+ const isTruthy = !!currentValue || annotation.text;
730
+ if (isChanged && isTruthy) {
731
+ const xValue = attrX ? new Date(item[attrX]).getTime() / 1000 : prevData.length + idx;
732
+ // 수직선 annotation 추가
733
+ if (annotation.type === 'verticalLine') {
734
+ const sciVerticalLine = new VerticalLineAnnotation({
735
+ x1: xValue,
736
+ stroke: convertColor(annotation.stroke, '#FF0000'),
737
+ strokeThickness: annotation.strokeThickness,
738
+ xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
739
+ yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue)
740
+ });
741
+ sciChartSurface.annotations.add(sciVerticalLine);
742
+ // 텍스트 annotation 추가 (변경된 값이 텍스트)
743
+ const labelText = currentValue ? String(currentValue) : annotation.text;
744
+ const sciTextAnnotation = new TextAnnotation({
745
+ x1: xValue,
746
+ y1: getYPositionByAnchor(annotation.verticalAnchorPoint),
747
+ text: labelText,
748
+ horizontalAnchorPoint: (annotation.horizontalAnchorPoint ||
749
+ EHorizontalAnchorPoint.Center),
750
+ verticalAnchorPoint: (annotation.verticalAnchorPoint ||
751
+ EVerticalAnchorPoint.Bottom),
752
+ fontFamily: annotation.fontFamily || fontFamily,
753
+ fontSize: annotation.fontSize || 14,
754
+ textColor: convertColor(annotation.stroke, '#FF0000'),
755
+ background: 'rgba(255, 255, 255, 0.7)',
756
+ padding: { left: 5, top: 5, right: 5, bottom: 5 },
757
+ xCoordinateMode: ECoordinateMode.DataValue,
758
+ yCoordinateMode: getYCoordModeByAnchor(annotation.verticalAnchorPoint)
759
+ });
760
+ sciChartSurface.annotations.add(sciTextAnnotation);
761
+ }
762
+ // 텍스트 annotation 타입도 지원
763
+ if (annotation.type === 'text') {
764
+ const sciTextAnnotation = new TextAnnotation({
765
+ x1: xValue,
766
+ y1: currentValue,
767
+ text: String(currentValue),
768
+ horizontalAnchorPoint: (annotation.horizontalAnchorPoint ||
769
+ EHorizontalAnchorPoint.Center),
770
+ verticalAnchorPoint: (annotation.verticalAnchorPoint ||
771
+ EVerticalAnchorPoint.Bottom),
772
+ fontFamily: annotation.fontFamily || fontFamily,
773
+ fontSize: annotation.fontSize || 14,
774
+ textColor: convertColor(annotation.stroke, fontColor),
775
+ xCoordinateMode: (annotation.xCoordinateMode || ECoordinateMode.DataValue),
776
+ yCoordinateMode: (annotation.yCoordinateMode || ECoordinateMode.DataValue)
777
+ });
778
+ sciChartSurface.annotations.add(sciTextAnnotation);
779
+ }
780
+ }
781
+ prevValue = currentValue;
782
+ });
783
+ });
784
+ }
785
+ export function removeAnnotationsByData(sciChartSurface, removedData = [], fromData, annotations = []) {
786
+ if (!removedData || !removedData.length || !annotations.length)
787
+ return;
788
+ const attrX = (fromData === null || fromData === void 0 ? void 0 : fromData.labelDataKey) || '';
789
+ const removedXValues = removedData
790
+ .map(item => {
791
+ const xValue = attrX ? new Date(item[attrX]).getTime() / 1000 : undefined;
792
+ return isNaN(Number(xValue)) ? undefined : xValue;
793
+ })
794
+ .filter(x => x !== undefined);
795
+ if (!removedXValues.length)
796
+ return;
797
+ // annotation config 조건에 맞는 것만 삭제
798
+ annotations
799
+ .filter(annotation => annotation.dataKey && (annotation.type === 'text' || annotation.type === 'verticalLine'))
800
+ .forEach(() => {
801
+ sciChartSurface.annotations
802
+ .asArray()
803
+ .filter((a) => removedXValues.includes(a.x1))
804
+ .forEach((a) => sciChartSurface.annotations.remove(a));
805
+ });
806
+ }
461
807
  //# sourceMappingURL=scichart-builder.js.map