pas2js/demo/chartjs/demoscriptablebubble.lpr

156 lines
4.3 KiB
ObjectPascal

program demoscriptablebubble;
{$MODE OBJFPC}
{$MODESWITCH EXTERNALCLASS}
uses
JS,
Web,
SysUtils,
Math,
ChartJS;
const
COLORS: array[0..8] of string = ('#4dc9f6', '#f67019', '#f53794', '#537bc4',
'#acc236', '#166a8f', '#00a950', '#58595b', '#8549ba');
function rand(min, max: Integer): Integer;
begin
Result := RandomRange(min, max);
end;
function ftos(const f: Double): string;
begin
Result := FloatToStrF(f, ffNumber, 15, 1);
end;
const
DATA_COUNT = 16;
MIN_XY = -150;
MAX_XY = 100;
function generateData: TJSArray;
var
i: Integer;
begin
Result := TJSArray.new;
for i := 0 to Pred(DATA_COUNT) do
begin
Result.push(TChartXYVData.new(rand(MIN_XY, MAX_XY), rand(MIN_XY, MAX_XY),
rand(0, 1000)));
end;
end;
function colorize(opaque: Boolean; context: TChartOptionsContext): JSValue;
var
value: TChartXYVData;
x, y, r, g, b, a: Double;
begin
value := TChartXYVData(
TChartBubbleDataset(context.dataset).data_[context.dataIndex]);
x := value.x_ / 100;
y := value.y_ / 100;
r := IfThen((x < 0) and (y < 0), 250, IfThen(x < 0, 150, IfThen(y < 0, 50, 0)));
g := IfThen((x < 0) and (y < 0), IfThen(x < 0, 50, IfThen(y < 0, 150, 250)));
b := IfThen((x < 0) and (y < 0), 0, IfThen((x > 0) and (y > 0), 250, 150));
a := IfThen(opaque, 1, 0.5 * value.v_ / 1000);
Result := 'rgba(' + ftos(r) + ',' + ftos(g) + ',' + ftos(b) + ',' +
ftos(a) + ')';
end;
function color(index: NativeInt): string;
begin
Result := COLORS[index mod Length(COLORS)];
end;
var
chart: TChart;
config: TChartConfiguration;
options: TChartOptions;
data: TChartData;
dataset: TChartBubbleDataset;
begin
data := TChartData.new;
data.datasets_ := TJSArray.new;
dataset := TChartBubbleDataset.new;
dataset.data_ := generateData;
data.datasets_.push(dataset);
dataset := TChartBubbleDataset.new;
dataset.data_ := generateData;
data.datasets_.push(dataset);
options := TChartOptions.new;
options.aspectRatio := 1;
options.legend_ := False;
options.tooltips_ := False;
options.elements := TChartElementsConfiguration.new;
options.elements.point := TChartElementPoint.new;
options.elements.point.backgroundColor_ := TJSFunction(@colorize).bind(nil, False);
options.elements.point.borderColor_ := TJSFunction(@colorize).bind(nil, True);
options.elements.point.borderWidth_ :=
function(context: TChartOptionsContext): JSValue
begin
Result := Min(Max(1, context.datasetIndex + 1), 8);
end;
options.elements.point.hoverBackgroundColor := 'transparent';
options.elements.point.hoverBorderColor_ :=
function(context: TChartOptionsContext): JSValue
begin
Result := color(context.datasetIndex);
end;
options.elements.point.hoverBorderWidth_ :=
function(context: TChartOptionsContext): JSValue
var
value: TChartXYVData;
begin
value := TChartXYVData(
TChartBubbleDataset(context.dataset).data_[context.dataIndex]);
Result := Round(8 * value.v_ / 1000);
end;
options.elements.point.radius_ :=
function(context: TChartOptionsContext): JSValue
var
value: TChartXYVData;
size: NativeUInt;
base: Double;
begin
value := TChartXYVData(TChartBubbleDataset(
context.dataset).data_[context.dataIndex]);
size := context.chart.width;
base := Abs(value.v_) / 1000;
Result := (size / 24) * base;
end;
config := TChartConfiguration.new;
config.type_ := 'bubble';
config.data := data;
config.options := options;
chart := TChart.new('chart-0', config);
document.getElementById('randomize').addEventListener('click',
procedure
begin
chart.config.data.datasets_.forEach(
function(element: JSValue; index: NativeInt; arr: TJSArray): Boolean
begin
TChartBubbleDataset(element).data_ := generateData;
end);
chart.update;
end);
document.getElementById('addDataset').addEventListener('click',
procedure
var
dataset: TChartBubbleDataset;
begin
dataset := TChartBubbleDataset.new;
dataset.data_ := generateData;
chart.config.data.datasets_.push(dataset);
chart.update;
end);
document.getElementById('removeDataset').addEventListener('click',
procedure
begin
chart.config.data.datasets_.shift;
chart.update;
end);
end.