Home

Awesome

ticklEcharts

Tcl wrapper around Apache ECharts.

Photo gallery

Dependencies :

huddle package from Tcllib

Usage :

package require ticklecharts

set chart [ticklecharts::chart new]

$chart Xaxis -data [list {Mon Tue Wed Thu Fri Sat Sun}]
$chart Yaxis
$chart Add "lineSeries" -data [list {150 230 224 218 135 147 260}]

$chart Render

Basic line chart

# Initializes a new 2D Chart Class
set chart [ticklecharts::chart new]
Argument available :
argsDescriptionDefault value
-themeDefines the theme namecustom (possible values: vintage,westeros,wonderland,dark)
# Adds the X axis with its values.
$chart Xaxis -data [list {Mon Tue Wed Thu Fri Sat Sun}]

# Adds the Y axis.
$chart Yaxis

# Adds data for line series.
$chart Add "lineSeries" -data [list {150 230 224 218 135 147 260}]

[!IMPORTANT]
-data property should be a list of list [list {...}]

# Export chart to HTML file
$chart Render
Arguments available :
argsDescriptionDefault values
-titleHTML title page"ticklEcharts !!!"
-widthContainer's width"900px"
-heightContainer's height"500px"
-renderercanvas or svg"canvas"
-jschartvarVariable name chartchart_[uuid]
-dividName container's IDid_[uuid]
-outfileFull path HTML file'./render.html'
-jsechartsScript echarts.jshttps://cdn.jsdelivr.net/...
-jsvarVariable name optionoption_[uuid]
-scriptExtra JS script'null' (see Add script section)
-classSpecify container's CSS"chart-container"
-styleInline style"width:'-width'; height:'-height'";
-templateFile or string template'file' (template.html)
# Example properties :
$chart Render -width "1200px" -height "800px" -renderer "svg"

Data series :

-data (y values only) :

# Example for lineseries
$chart Add "lineSeries" -data [list {150 230 224 218 135 147 260}]
$chart Yaxis

-data (x, y values) :

# Example for lineseries
$chart Add "lineSeries" -data [list {Mon 150} {Tue 230} {Wed 224} {... ...}]
# Mon = X value
# 150 = Y value
# Please note : X data is not included.
$chart Xaxis
$chart Yaxis

-dataItem :

# Example for lineseries
# Additional options are valid, see ticklecharts::lineItem in options.tcl
$chart Add "lineSeries" -dataItem {
    {name "Mon" value 150}
    {name "Tue" value 230}
    {name "Wed" value 224}
    {name "Thu" value 218}
    {name "Fri" value 135}
    {name "Sat" value 147}
    {name "Sun" value 260}
}

-dataset :

set data(0) {
    {"Day" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun"}
    {"value" 150 230 224 218 135 147 260}
}

# Init dataset class.
# Note : Starting from version '2.6', it is possible 
# to add several 'items' like this :
# > [list [list source $data(0) sourceHeader "True"] [list source $data(1) ...]]]
set obj [ticklecharts::dataset new [list source $data(0) sourceHeader "True"]]

# Add '$obj' to dataset property. 
$chart SetOptions -dataset $obj
# Add line series.
$chart Xaxis
$chart Yaxis
$chart Add "lineSeries" -seriesLayoutBy "row"

Useful methods :

  1. Get default options according to a key (name of procedure) :
# e.g for series :
$chart getOptions -series lineSeries
# e.g for axis :
$chart getOptions -axis X
# e.g for global options :
$chart getOptions -globalOptions ; # no value required
# get all options for 'title' :
$chart getOptions -option title
# output :
 id                -minversion 5  -validvalue {}                      -type str|null    -default "nothing"
 show              -minversion 5  -validvalue {}                      -type bool        -default "True"
 text              -minversion 5  -validvalue {}                      -type str|null    -default "nothing"
 link              -minversion 5  -validvalue {}                      -type str|null    -default "nothing"
 target            -minversion 5  -validvalue formatTarget            -type str         -default "blank"
 textStyle         -minversion 5  -validvalue {}                      -type dict|null
   color                -minversion 5  -validvalue formatColor          -type str.t|jsfunc|null -default $color
   fontStyle            -minversion 5  -validvalue formatFontStyle      -type str               -default "normal"
   fontWeight           -minversion 5  -validvalue formatFontWeight     -type str.t|num.t|null  -default $fontWeight
   fontFamily           -minversion 5  -validvalue {}                   -type str               -default "sans-serif"
   fontSize             -minversion 5  -validvalue {}                   -type num.t|null        -default $fontSize
   lineHeight           -minversion 5  -validvalue {}                   -type num|null          -default "nothing"
   width                -minversion 5  -validvalue {}                   -type num               -default 100
   height               -minversion 5  -validvalue {}                   -type num               -default 50
   textBorderColor      -minversion 5  -validvalue {}                   -type str|null          -default "null"
   textBorderWidth      -minversion 5  -validvalue {}                   -type num               -default 0
   textBorderType       -minversion 5  -validvalue formatTextBorderType -type str|num|list.n    -default "solid"
   textBorderDashOffset -minversion 5  -validvalue {}                   -type num               -default 0
   textShadowColor      -minversion 5  -validvalue formatColor          -type str               -default "transparent"
   textShadowBlur       -minversion 5  -validvalue {}                   -type num               -default 0
   textShadowOffsetX    -minversion 5  -validvalue {}                   -type num               -default 0
   textShadowOffsetY    -minversion 5  -validvalue {}                   -type num               -default 0
   overflow             -minversion 5  -validvalue formatOverflow       -type str|null          -default "null"
   ellipsis             -minversion 5  -validvalue {}                   -type str               -default "..."
   # ...
 subtext           -minversion 5  -validvalue {}                      -type str|null    -default "nothing"
 sublink           -minversion 5  -validvalue {}                      -type str|null    -default "nothing"
 ...
 ...
# Following options voluntarily deleted.
  1. Delete series by index:
$chart Add "lineSeries" -data [list {1 2 3 4}]
$chart Add "barSeries"  -data [list {5 6 7 8}]

# Delete bar series :
$chart deleteSeries 1
  1. Gets json data :
$chart toJSON
  1. Export chart as HTML fragment :
$chart toHTML ?-template ?...
  1. Add JSON structure:
$chart AddJSON $struct ?-parent ?... ; # See '# Structure' section
  1. Capture an image:
$chart SnapShot ?-outfile ?... ; # See '# Image' section

Add extra JS script, variable, etc. :

When permitted, ticklecharts::jsfunc class can insert a function directly in JSON data :

# Initializes a new jsfunc Class and insert 
# a 'JS function' as argument :
set js [ticklecharts::jsfunc new {
        function (value, index) {
            return value + ' (C°)';
        }
    }
]

# Add $js variable to 'formatter' property. 
$chart Xaxis -axisLabel [subst {
    show "True"
    margin 8
    formatter $js
    showMinLabel "null"
    # ...
}]
$chart toJSON
"axisLabel": {
  "show": true,
  "margin": 8,
  "formatter": function (value, index) {
    return value + ' (C°)';
  },
  "showMinLabel": null,
  // ...
}

[!NOTE]
formatter accepts a javascript function most times but in some cases formatter supports
string template like this '{b0}: {c0}<br />{b1}: {c1}'

There are three ways to do this :

{"{b0}: {c0}<br />{b1}: {c1}"}

new estr "{b0}: {c0}<br />{b1}: {c1}"

"<0123>b0<0125>: <0123>c0<0125><br /><0123>b1<0125>: <0123>c1<0125>"

CharsMap
{<0123>
}<0125>
[<091>
]<093>

Combined with Render method and -script property, you can add JavaScript elements in the HTML template file.

# Adds a variable at the start:
set var [ticklecharts::jsfunc new {
        var maskImage = new Image();
        maskImage.src = './logo.png';
    } -start
]

# Adds a header script:
set header [ticklecharts::jsfunc new {
        <script type="text/javascript" src="tcl.js"></script>
    } -header
]
# Note: Inserting a script, variable, etc. in the HTML file is
# based on a search for a string in the template if this is not found,
# an error is generated.
$chart Render -title "Example jsfunc class" -script [list [list $var $header]]
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Example jsfunc class</title>
    <script type="text/javascript" src="echarts.min.js"></script>
    <!-- -header <script>...</script> -->
    <script type="text/javascript" src="tcl.js"></script>
  </head>
  <body>
    <div id="main" class="chart-container" style="width:900px; height:500px;"></div>
    <script>
        var chart = echarts.init(document.getElementById('main'), null, {renderer: 'canvas'});
        // -start script...
        var maskImage = new Image();
        maskImage.src = './logo.png';
        var option = {
            "backgroundColor": "rgba(0,0,0,0)",
            "color": [
              // ...
            ],
            "maskImage": maskImage,
            // ...
        }
    </script>
  </body>
</html>

Performance :

Since version 2, some huddle/ehuddle procedures can be replaced by functions written in C with help of critcl.
Critcl package should be available and this command ticklecharts::eHuddleCritcl should be set to valid Tcl_boolean value.
You may be processing important data and if you want to gain speed, this command can be useful, below how to use it :

package require ticklecharts

# Load critcl package
# Note : A warning message may be displayed on your console
# if there was a problem compiling or loading critcl package
ticklecharts::eHuddleCritcl True

source examples/candlestick/candlestick_large_scale.tcl ; # dataCount set to 200,000
#             | This run (Mac Os Core i7)
#    pure Tcl | 25354915 microseconds per iteration 
#    critcl   |  6338728 microseconds per iteration (≃4x faster)

Note : No advantage to use this command with small data.

Type substitution :

Since version 3.1, two new classes have been introduced. They allow string and list values to be substituted.
In some cases, it is difficult to find the type for a variable, since everything is considered to be a string in Tcl.
These 2 classes below get around the problem (partly):

See line_eList.tcl and line and bar mixed demo to know why this class has been implemented for certain cases.

Since version 3.2.3 when default type is list.d it can be replaced by list.s or list.n ehuddle type.
This improves performance by avoiding the need to scan the list to find the type of data. By example, the default type
for Xaxis.data is list.d, this property can be written as follows :

# Note : If you are sure that the X data is of type 'string', you can replace 
# -data [list {...}] property by :
$chart Xaxis -data [new elist.s {...}]

Structure :

Since version 3.2.4, it is now possible to construct your own JSON, and a new eStruct class has been added
for this purpose. The idea here is to give the user the choice of making their own structure.

# The keys must be typed (str, struct, bool...).
# Be careful, input data is not verified, you have control.
new estruct myStruct {
    key1:num    "number value"
    key2:str    "string value"
    key3:list.n "list of numbers"
    key4:bool   "boolean value"
    key4:...    "..."
}
# Optional argument to 'AddJSON' method: 
# '-parent' (with or without index).
# With this optional argument, we can add our structure to a specific location.
$chart AddJSON $myStruct ?-parent ?key1(?index).?key2(?index)

See line_build_your_own_JSON.tcl for a more detailed example.

Image :

Since version 3.2.4, if Chrome or Edge is installed, it is possible to capture an image via chrome devtools protocol.
The return type for image is either a *.(png|svg) file or data in base64 format.

Dependencies : websocket package from Tcllib

Arguments available :
argsDescriptionDefault values
-addressLocal adress"127.0.0.1"
-portPort number8888
-exeFull path executable"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
-htmlHtml fragment"nothing"
-jschartvarVariable name chart"nothing" (Required if -html property is set)
-rendererbase64, png or svg"png"
-outfileFull path file"./render.(png|svg)"
-excludecomponentsExcluded components"nothing" (List e.g. ['toolbox', 'title', '...'])
-timeoutTime to execute JS function400 (milliseconds)
# Note : Animations must be disabled, which is not the case by default. 
$chart SetOptions -animation "False"
# ...
$chart SnapShot -timeout 600 -port 8080 ;  # Returns full path '*.png' file

# Example with 'html' fragment on Windows :
# It is important to specify the variable 'jschartvar' to have the same 
# one for the 'SnapShot' method.
#
set html [$chart toHTML -jschartvar "mychart"] ; # Export '$chart' as HTML fragment.
# Note : A full path should be specified if 'msedge.exe' is not included in 'env(PATH)'.
$chart SnapShot -exe "msedge.exe"  -jschartvar "mychart" -html $html -renderer "base64"

# For 'svg' renderer it's important to set the '-renderer' property
# to 'svg' in 'toHTML' method.
set html [$chart toHTML -jschartvar "mychart" -renderer "svg"]
$chart SnapShot -jschartvar "mychart" -renderer "svg" -html $html
# ...

[!NOTE]

Global variables :

package require ticklecharts

# Set theme with global variable
# Or with class : ticklecharts::(Gridlayout|chart|timeline|chart3D) new -theme "vintage"
set ::ticklecharts::theme "vintage" ; # default "custom" 

# Minimum properties:
# Only write values that are defined in the *.tcl file. (Benefit : performance + minifying your HTML files)
# Be careful, properties in the *.tcl file must be implicitly marked.
set ::ticklecharts::minProperties "True" ; # default "False"

# Output 'render.html' full path to stdout. 
set ::ticklecharts::htmlstdout "False" ; # default "True"

# Google API Key 
# Note : To use the Google map API 'gmap' a valid key is required.
set ::ticklecharts::keyGMAPI "??" ; # Please replace '??' with your own API key.

# Set versions for js script.
# Note : Num version (@X.X.X) should be defined in js path. If no pattern matches, the script path is left unchanged.
set ::ticklecharts::echarts_version "X.X.X" ; # Echarts version
set ::ticklecharts::gl_version      "X.X.X" ; # Echarts GL version
set ::ticklecharts::gmap_version    "X.X.X" ; # gmap version
set ::ticklecharts::wc_version      "X.X.X" ; # wordcloud version

 # Verify if a URL exists when Echarts version changed.
set ::ticklecharts::checkURL "True" ; # default "False"

Note : All the above variables can be modified in the ticklecharts.tcl file.

Examples :

See the examples folder for all demos (from Apache Echarts examples)

line and bar mixed

# line + bar on same canvas.
package require ticklecharts

# Initializes a new 2D Chart Class.
set chart [ticklecharts::chart new]

# Set options
$chart SetOptions -tooltip {show True trigger "axis" axisPointer {type "cross" crossStyle {color "#999"}}} \
                  -grid {left "3%" right "4%" bottom "3%" containLabel "True"} \
                  -legend {}
               
$chart Xaxis -data [list {"Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun"}] \
             -axisPointer {type "shadow"}

# Encapsulates the string with braces + quotes or use 'ticklecharts::eString'
# class for 'formatter' property (See '# string template' section).
$chart Yaxis -name "Precipitation" -position "left" -min 0 -max 250 -interval 50 \
                                   -axisLabel {formatter {"{value} ml"}}
$chart Yaxis -name "Temperature"   -position "right" -min 0 -max 25  -interval 5 \
                                   -axisLabel [list formatter [new estr "{value} °C"]]

# Add bars series.
$chart Add "barSeries" -name "Evaporation" \
                       -data [list {2.0 4.9 7.0 23.2 25.6 76.7 135.6 162.2 32.6 20.0 6.4 3.3}]
                    
$chart Add "barSeries" -name "Precipitation" \
                       -data [list {2.6 5.9 9.0 26.4 28.7 70.7 175.6 182.2 48.7 18.8 6.0 2.3}]                    

# Add line series.                  
$chart Add "lineSeries" -name "Temperature" \
                        -yAxisIndex 1 \
                        -data [list {2.0 2.2 3.3 4.5 6.3 10.2 20.3 23.4 23.0 16.5 12.0 6.2}]

# Output
$chart Render

line, bar and pie layout

# Demo layout with line, bar and pie charts.
set data(0) {1 2 3 4 5}
set data(1) {2 3.6 6 2 10}

# Format label
set js [ticklecharts::jsfunc new {
    function (value, index) {
        return value + ' (C°)';
    },
}]

set line [ticklecharts::chart new]
                  
$line SetOptions -title   {text "layout line + bar + pie charts..."} \
                 -tooltip {show "True"} \
                 -legend {top "56%" left "20%"}    
    
$line Xaxis -data [list $data(0)] -boundaryGap "False"
$line Yaxis
$line Add "lineSeries" -data [list $data(0)] -areaStyle {} -smooth "True"
$line Add "lineSeries" -data [list $data(1)] -smooth "True"

set bar [ticklecharts::chart new]

$bar SetOptions -legend {top "2%" left "20%"}

$bar Xaxis -data [list {A B C D E}] \
           -axisLabel [list show "True" formatter $js]
$bar Yaxis
$bar Add "barSeries" -data [list {50 6 80 120 30}]
$bar Add "barSeries" -data [list {20 30 50 100 25}]

set pie [ticklecharts::chart new]

$pie SetOptions -legend {top "6%" left "65%"} 

$pie Add "pieSeries" -name "Access From" -radius [list {"50%" "70%"}] \
                     -labelLine {show "True"} \
                     -dataItem {
                        {value 1048 name "C++"}
                        {value 300 name "Tcl"}
                        {value 580 name "Javascript"}
                        {value 484 name "Python"}
                        {value 735 name "C"}
                    }

# Initializes a new 'Gridlayout' Class.
set layout [ticklecharts::Gridlayout new]

# Arrange the different series on the canvas.
$layout Add $bar  -bottom "60%" -width "40%" -left "5%"
$layout Add $line -top    "60%" -width "40%" -left "5%"
$layout Add $pie  -center [list {75% 50%}]

$layout Render

Currently chart and options supported are :

[!NOTE]
custom series contains a lot of Javascript codes, I don’t think it’s interesting to write it in this package.
If you are interested, please report to the github issue tracker.

License :

ticklEcharts is covered under the terms of the MIT license.

Change log :

See detailed changes for each release.