demoscriptablebubble.lpr 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. program demoscriptablebubble;
  2. {$MODE OBJFPC}
  3. {$MODESWITCH EXTERNALCLASS}
  4. uses
  5. JS,
  6. Web,
  7. SysUtils,
  8. Math,
  9. ChartJS;
  10. const
  11. COLORS: array[0..8] of string = ('#4dc9f6', '#f67019', '#f53794', '#537bc4',
  12. '#acc236', '#166a8f', '#00a950', '#58595b', '#8549ba');
  13. function rand(min, max: Integer): Integer;
  14. begin
  15. Result := RandomRange(min, max);
  16. end;
  17. function ftos(const f: Double): string;
  18. begin
  19. Result := FloatToStrF(f, ffNumber, 15, 1);
  20. end;
  21. const
  22. DATA_COUNT = 16;
  23. MIN_XY = -150;
  24. MAX_XY = 100;
  25. function generateData: TJSArray;
  26. var
  27. i: Integer;
  28. begin
  29. Result := TJSArray.new;
  30. for i := 0 to Pred(DATA_COUNT) do
  31. begin
  32. Result.push(TChartXYVData.new(rand(MIN_XY, MAX_XY), rand(MIN_XY, MAX_XY),
  33. rand(0, 1000)));
  34. end;
  35. end;
  36. function colorize(opaque: Boolean; context: TChartOptionsContext): JSValue;
  37. var
  38. value: TChartXYVData;
  39. x, y, r, g, b, a: Double;
  40. begin
  41. value := TChartXYVData(
  42. TChartBubbleDataset(context.dataset).data_[context.dataIndex]);
  43. x := value.x_ / 100;
  44. y := value.y_ / 100;
  45. r := IfThen((x < 0) and (y < 0), 250, IfThen(x < 0, 150, IfThen(y < 0, 50, 0)));
  46. g := IfThen((x < 0) and (y < 0), IfThen(x < 0, 50, IfThen(y < 0, 150, 250)));
  47. b := IfThen((x < 0) and (y < 0), 0, IfThen((x > 0) and (y > 0), 250, 150));
  48. a := IfThen(opaque, 1, 0.5 * value.v_ / 1000);
  49. Result := 'rgba(' + ftos(r) + ',' + ftos(g) + ',' + ftos(b) + ',' +
  50. ftos(a) + ')';
  51. end;
  52. function color(index: NativeInt): string;
  53. begin
  54. Result := COLORS[index mod Length(COLORS)];
  55. end;
  56. var
  57. chart: TChart;
  58. config: TChartConfiguration;
  59. options: TChartOptions;
  60. data: TChartData;
  61. dataset: TChartBubbleDataset;
  62. begin
  63. data := TChartData.new;
  64. data.datasets_ := TJSArray.new;
  65. dataset := TChartBubbleDataset.new;
  66. dataset.data_ := generateData;
  67. data.datasets_.push(dataset);
  68. dataset := TChartBubbleDataset.new;
  69. dataset.data_ := generateData;
  70. data.datasets_.push(dataset);
  71. options := TChartOptions.new;
  72. options.aspectRatio := 1;
  73. options.legend_ := False;
  74. options.tooltips_ := False;
  75. options.elements := TChartElementsConfiguration.new;
  76. options.elements.point := TChartElementPoint.new;
  77. options.elements.point.backgroundColor_ := TJSFunction(@colorize).bind(nil, False);
  78. options.elements.point.borderColor_ := TJSFunction(@colorize).bind(nil, True);
  79. options.elements.point.borderWidth_ :=
  80. function(context: TChartOptionsContext): JSValue
  81. begin
  82. Result := Min(Max(1, context.datasetIndex + 1), 8);
  83. end;
  84. options.elements.point.hoverBackgroundColor := 'transparent';
  85. options.elements.point.hoverBorderColor_ :=
  86. function(context: TChartOptionsContext): JSValue
  87. begin
  88. Result := color(context.datasetIndex);
  89. end;
  90. options.elements.point.hoverBorderWidth_ :=
  91. function(context: TChartOptionsContext): JSValue
  92. var
  93. value: TChartXYVData;
  94. begin
  95. value := TChartXYVData(
  96. TChartBubbleDataset(context.dataset).data_[context.dataIndex]);
  97. Result := Round(8 * value.v_ / 1000);
  98. end;
  99. options.elements.point.radius_ :=
  100. function(context: TChartOptionsContext): JSValue
  101. var
  102. value: TChartXYVData;
  103. size: NativeUInt;
  104. base: Double;
  105. begin
  106. value := TChartXYVData(TChartBubbleDataset(
  107. context.dataset).data_[context.dataIndex]);
  108. size := context.chart.width;
  109. base := Abs(value.v_) / 1000;
  110. Result := (size / 24) * base;
  111. end;
  112. config := TChartConfiguration.new;
  113. config.type_ := 'bubble';
  114. config.data := data;
  115. config.options := options;
  116. chart := TChart.new('chart-0', config);
  117. document.getElementById('randomize').addEventListener('click',
  118. procedure
  119. begin
  120. chart.config.data.datasets_.forEach(
  121. function(element: JSValue; index: NativeInt; arr: TJSArray): Boolean
  122. begin
  123. TChartBubbleDataset(element).data_ := generateData;
  124. end);
  125. chart.update;
  126. end);
  127. document.getElementById('addDataset').addEventListener('click',
  128. procedure
  129. var
  130. dataset: TChartBubbleDataset;
  131. begin
  132. dataset := TChartBubbleDataset.new;
  133. dataset.data_ := generateData;
  134. chart.config.data.datasets_.push(dataset);
  135. chart.update;
  136. end);
  137. document.getElementById('removeDataset').addEventListener('click',
  138. procedure
  139. begin
  140. chart.config.data.datasets_.shift;
  141. chart.update;
  142. end);
  143. end.