Chart-Plotly
view release on metacpan or search on metacpan
lib/Chart/Plotly.pm view on Meta::CPAN
package Chart::Plotly;
use strict;
use warnings;
use utf8;
use Exporter 'import';
use vars qw(@EXPORT_OK);
@EXPORT_OK = qw(show_plot);
use JSON;
use Params::Validate qw(:all);
use Text::Template;
use Module::Load;
use Ref::Util;
use HTML::Show;
use UUID::Tiny ':std';
use File::ShareDir;
use Path::Tiny;
our $VERSION = '0.042'; # VERSION
# ABSTRACT: Generate html/javascript charts from perl data using javascript library plotly.js
sub render_full_html {
## no critic
my %params = validate( @_, { data => { type => ARRAYREF | OBJECT }, } );
## use critic
my $data = $params{'data'};
my $chart_id = create_uuid_as_string(UUID_TIME);
my $html;
if ( Ref::Util::is_blessed_ref($data) && $data->isa('Chart::Plotly::Plot') ) {
$html = _render_html_wrap( $data->html( div_id => $chart_id ) );
} else {
$html = _render_html_wrap( _render_cell( _process_data($data), $chart_id ) );
}
return $html;
}
sub _render_html_wrap {
my $body = shift;
my $html_begin = <<'HTML_BEGIN';
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
</head>
<body>
HTML_BEGIN
my $html_end = <<'HTML_END';
</body>
</html>
HTML_END
return $html_begin . $body . $html_end;
}
sub _render_cell {
my $data_string = shift();
my $chart_id = shift() // create_uuid_as_string(UUID_TIME);
my $layout = shift();
my $config = shift();
my $extra = shift() // { load_plotly_using_script_tag => 1 };
if ( defined $layout ) {
$layout = "," . $layout;
}
if ( defined $config ) {
$config = "," . $config;
}
my $load_plotly = _load_plotly( ${$extra}{'load_plotly_using_script_tag'} );
my $template = <<'TEMPLATE';
<div id="{$chart_id}"></div>
{$load_plotly}
<script>
Plotly.{$plotlyjs_plot_function}(document.getElementById('{$chart_id}'),{$data} {$layout} {$config});
</script>
TEMPLATE
my $template_variables = { data => $data_string,
chart_id => $chart_id,
load_plotly => $load_plotly,
plotlyjs_plot_function => plotlyjs_plot_function(),
defined $layout ? ( layout => $layout ) : (),
defined $config ? ( config => $config ) : (),
};
return Text::Template::fill_in_string( $template, HASH => $template_variables );
}
sub _process_data {
my $data = shift;
my $json_formatter = JSON->new->allow_blessed(1)->convert_blessed(1);
local *PDL::TO_JSON = sub { $_[0]->unpdl };
if ( Ref::Util::is_blessed_ref($data) ) {
my $adapter_name = 'Chart::Plotly::Adapter::' . ref $data;
eval {
load $adapter_name;
my $adapter = $adapter_name->new( data => $data );
$data = $adapter->traces();
};
if ($@) {
warn 'Cannot load adapter: ' . $adapter_name . '. ' . $@;
}
}
my $data_string = $json_formatter->encode($data);
return $data_string;
}
sub _load_plotly {
my $how_to_load = shift;
if ($how_to_load) {
if ( $how_to_load eq "1" || $how_to_load eq 'cdn' ) {
return '<script src="https://cdn.plot.ly/plotly-' . plotlyjs_version() . '.min.js"></script>';
} elsif ( $how_to_load eq 'embed' ) {
my $minified_plotly = File::ShareDir::dist_file( 'Chart-Plotly', 'plotly.js/plotly.min.js' );
return '<script>' . Path::Tiny::path($minified_plotly)->slurp . '</script>';
} elsif ( $how_to_load eq 'module_dist' ) {
my $minified_plotly = File::ShareDir::dist_file( 'Chart-Plotly', 'plotly.js/plotly.min.js' );
return '<script src="file://' . $minified_plotly . '"></script>';
}
} else {
return '';
}
}
sub html_plot {
my @data_to_plot = @_;
my $rendered_cells = "";
for my $data (@data_to_plot) {
my $id = create_uuid_as_string(UUID_TIME);
if ( Ref::Util::is_blessed_ref($data) && $data->isa('Chart::Plotly::Plot') ) {
$rendered_cells .= $data->html( div_id => $id );
} else {
$rendered_cells .= _render_cell( _process_data($data), $id );
}
}
return _render_html_wrap($rendered_cells);
}
sub show_plot {
HTML::Show::show( html_plot(@_) );
}
sub plotlyjs_version {
return '2.14.0'; # plotlyjs_version_tag
}
sub plotlyjs_plot_function {
return 'react';
}
sub plotlyjs_plot_function_parameters {
return qw(div data layout config);
}
1;
__END__
=pod
=encoding utf-8
=head1 NAME
Chart::Plotly - Generate html/javascript charts from perl data using javascript library plotly.js
=head1 VERSION
version 0.042
=head1 SYNOPSIS
use Chart::Plotly 'show_plot';
my $data = { x => [ 1 .. 10 ],
mode => 'markers',
type => 'scatter'
};
$data->{'y'} = [ map { rand 10 } @{ $data->{'x'} } ];
show_plot([$data]);
use aliased 'Chart::Plotly::Trace::Scattergl';
my $big_array = [ 1 .. 10000 ];
my $scattergl = Scattergl->new( x => $big_array, y => [ map { rand 100 } @$big_array ] );
show_plot([$scattergl]);
use Chart::Plotly qw(show_plot);
( run in 1.571 second using v1.01-cache-2.11-cpan-39bf76dae61 )