fix #7522 - merge insights into main branch
authorAlan <alan@roojs.com>
Tue, 9 May 2023 07:47:52 +0000 (15:47 +0800)
committerAlan <alan@roojs.com>
Tue, 9 May 2023 07:47:52 +0000 (15:47 +0800)
g.bar.overlay.js
g.bar.split.js
g.pie.circular.js
g.pie.sector.js
seed/toSVG.js
test/bartest.html

index 7ad21ee..221a81a 100644 (file)
@@ -31,8 +31,6 @@ if (typeof(Raphael) == 'undefined') {
  
 
 /*\
- * Paper.vbarchart
- [ method ]
  **
  * Creates a vertical bar chart
  **
@@ -45,18 +43,37 @@ if (typeof(Raphael) == 'undefined') {
  - values (array) values
  - opts (object) options for the chart
  o {
- o type (string) type of endings of the bar. Default: 'square'. Other options are: 'round', 'sharp', 'soft'.
- o gutter (number)(string) default '20%' (WHAT DOES IT DO?)
- o vgutter (number)
- o colors (array) colors be used repeatedly to plot the bars. If multicolumn bar is used each sequence of bars with use a different color.
- o stacked (boolean) whether or not to tread values as in a stacked bar chart
- o to
- o stretch (boolean)
+    background (string) : background color
+    gutter (string) (number) : indicate width of gutters with repsect to the bars in terms of percentage (e.g. '20%' means that the width ratio of gutter to bar is 10:2)
+    barsteps (number) : number of bars shown
+    barfill (string) : color to fill the empty bar (not filling if not provided)
+    baroffset (number) : distance between the rightmost bar and y axis;
+    colors (array) : colors of the bars 
+    axis (string) : composed of 4 '0' / '1' separated by space (indicated whether top / right / bottom / left axis should be shown) 
+    (e.g. '0 1 1 0' indicates that the right and the bottom axis should be shown)
+    asixxheight (number) : height of x axis area
+    axisxlabels (string) : labels in x axis
+    asixywidth (number) : width of y axis area
+    axisystep (number) : number of steps in y axis
+    axislinecolor (string) : color of lines in y axis
+    axisfont (string) : font family of labels in axes
+    axisfontsize (number) : font size of labels in axes
+    axisfontweight (string) (number) : font weight of labels in axes
+    axisfontcolor (string) : font color of labels in axes
+    labelfont (string) : font family of labels
+    labelsize (number) : font size of labels
+    labelweight (string)(number) : font weight of labels
+    labelcolors (array) : font colors of the labels
+    legends (array) : legend
+    legendheight : height of the legend
+    legendkeyshape (string) : shape of the legend keys ('circle' / 'rect')
+    legendkeysize (number) : size of the legend keys (diameter for 'circle' and width for 'rect')
+    legendfont (string) : font family of the legend labels
+    legendfontsize (number) : font size of the legend labels
+    legendfontweight (string)(number) : font weight of the legend labels
+    legendfontcolor (string) : font color of the legend colors
  o }
  **
- = (object) path element of the popup
- > Usage
- | r.vbarchart(0, 0, 620, 260, [[76, 70], [67, 71]], {})
  \*/
 
  
@@ -68,14 +85,36 @@ if (typeof(Raphael) == 'undefined') {
             chart = paper.set(),
             bars = paper.set(),
             covers = paper.set(),
+            len = values.length,
+            gutter = parseFloat(opts.gutter || "0%"), 
             barsteps = opts.barsteps || 20,
-            colors = opts.colors || chartinst.colors;
+            barFill = opts.barfill || false, // default no fill
+            colors = opts.colors || chartinst.colors,
+            axisLineColor = opts.axislinecolor || '#BABABA',
+            axisFont = opts.axisfont || "'Fontin Sans', Fontin-Sans, sans-serif",
+            axisFontSize = opts.axisfontsize || ((barsteps > 10) ? 12 : 14),
+            axisFontWeight = opts.axisfontweight || 'bold',
+            axisFontColor = opts.axisfontcolor || '#BABABA',
+            labelFont = opts.labelfont || "'Fontin Sans', Fontin-Sans, sans-serif",
+            labelSize = opts.labelsize || ((barsteps > 10) ? 10 : 12),
+            labelWeight = opts.labelweight || 'bold',
+            labelColors = opts.labelcolors || [],
+            legendKeyShape = opts.legendkeyshape || 'circle',
+            legendKeySize = opts.legendkeysize || 16,
+            legendFont = opts.legendfont || "'Fontin Sans', Fontin-Sans, sans-serif",
+            legendFontSize = opts.legendfontsize || 14,
+            legendFontWeight = opts.legendfontweight || 'bold',
+            legendFontColor = opts.legendfontcolor || '#0C014D';
+
+        for(var i = 0; i < len; i++) {
+            labelColors.push('#FFFFFF');
+        }
             
         
         opts.axis = opts.axis || "";
         opts.baroffset = opts.baroffset || 10;
-        opts.asixxheight = opts.asixxheight || 100;
-        opts.asixywidth = opts.asixywidth || 100;
+        axisXHeight = opts.asixxheight || 100;
+        axisYWidth = opts.asixywidth || 100;
         opts.axisxlabels = opts.axisxlabels || [];
         opts.legendheight = opts.legendheight || 80;
         opts.legends = opts.legends || 100;
@@ -84,16 +123,22 @@ if (typeof(Raphael) == 'undefined') {
         paper.rect(0, 0, width, height).attr({ stroke: "none", fill: (opts.background || "#F0F4F7") });
 //        background.toBack();
         
-        // bar border
-        var barwidth = Math.floor((width - x - opts.asixywidth - opts.baroffset) / barsteps);
-        var barheight = height - y - opts.asixxheight - opts.legendheight || 100;
-        var path = ["M", x + 1, y + opts.legendheight, "l", 0, barheight]
+        // bar border && bar gutter
+        // total 'barsteps' of bars and 'barsteps - 1' of gutters
+        var barWidth = (width - x - axisYWidth - opts.baroffset) / (barsteps * (100 + gutter) - gutter) * 100;
+        var barGutter = barWidth * gutter / 100;
+        var barHeight = height - y - axisXHeight - opts.legendheight || 100;
+        var path = [];
         
         for (var i = 0; i < barsteps; i++) {
-            path = path.concat(["M", x + (i * barwidth), y + opts.legendheight + 1, "l", barwidth, 0, "l", 0, barheight]);
+            path = path.concat(["M", x + (i * (barWidth + barGutter)), height - axisXHeight, "l", 0, -1 * barHeight, "l", barWidth, 0, "l", 0, barHeight]);
+
+            if(barFill) {
+                paper.rect(x + (i * (barWidth + barGutter)) + 1 , y + opts.legendheight + 1, barWidth - 2, barHeight - 2).attr({ stroke: "none", fill: barFill });
+            }
         }
         
-        paper.path(path).attr({ stroke: "#fff", "stroke-width": 2 });
+        paper.path(path).attr({ stroke: "#FFF", "stroke-width": 2});
         
         var max = 0;
         
@@ -103,29 +148,44 @@ if (typeof(Raphael) == 'undefined') {
             }
     
             value.forEach(function(v,k)  {
+                if(k >= barsteps) {
+                    return;
+                }
                 max = (v > max) ? v : max;
             });
             
         });
         
+        // legends
         values.forEach(function(value,i) {
             if (!Raphael.is(value, "array")) {
                 value = [value];
             }
+
+            // 10 pixels away from top of the chart
+            // 10 pixels away from left of the chart
+            if(legendKeyShape == 'rect') {
+                // pass top left position for 'rect'
+                paper.rect(x + (i * (width - x) / len) + 10, y + 10, legendKeySize, legendKeySize, 0).attr({ fill: colors[i%colors.length], "stroke": "#fff" });
+            }
+            else {
+                // pass center position for 'circle'
+                paper.circle(x + (i * (width - x) / len) + 10 + (legendKeySize / 2), y + 10 + (legendKeySize / 2), legendKeySize / 2).attr({ fill: colors[i%colors.length], "stroke": "#fff" });
+            }
             
-            paper.circle(x + (i * 400) + 8, y + 10, 8).attr({ fill: colors[i%colors.length], "stroke": "#fff" });
-            
-            paper.text(x + (i * 400) + 18, y + 8, opts.legends[i%opts.legends.length]).attr({ 
-                "font-size": "14",
-                "font-family": "'Fontin Sans', Fontin-Sans, sans-serif",
-                "font-weight": "bold",
+            // 10 pixels away from right of the legend key
+            //  align legend key and text horizontally
+            paper.text(x + (i * (width - x) / len) + 10 + legendKeySize + 10, y + 10 + (legendKeySize / 2) - legendFontSize / 10, opts.legends[i%opts.legends.length]).attr({ 
+                "font-size": legendFontSize,
+                "font-family": legendFont,
+                "font-weight": legendFontWeight,
                 "text-anchor": "start",
-                fill : "#0C014D"
+                fill : legendFontColor
             });
         });
         
         //bars
-        var unit = barheight / max;
+        var unit = barHeight / max;
         
         values.forEach(function(value,i) {
             if (!Raphael.is(values, "array")) {
@@ -133,27 +193,32 @@ if (typeof(Raphael) == 'undefined') {
             }
             
             value.forEach(function(v,k)  {
-                if(v == 0) {
+                if(v == 0 || k >= barsteps) {
                     return;
                 }
                 
-                paper.rect(x + 1 + (k * barwidth) , y + opts.legendheight + 1 + (max - v) * unit, barwidth - 2, v * unit).attr({ stroke: "none", fill: colors[i%colors.length] });
-                
-                var indicator_y = y + opts.legendheight + (max - v) * unit - 42;
+                paper.rect(x + (k * (barWidth + barGutter)) + 1 , y + opts.legendheight + 1 + (max - v) * unit, barWidth - 2, v * unit - 2).attr({ stroke: "none", fill: colors[i%colors.length] });
+
+                // width and height of indicator
+                var iw = barWidth * 0.8;
+                var ih = Math.min(30, iw * 0.5);
+
+                // position of indicator
+                var ix = x + (k * (barWidth + barGutter)) + 1 + (barWidth - iw) / 2;
+                var iy = y + opts.legendheight + 1 + (max - v) * unit - ih - 20;
                 
                 if(i == 0) {
-                    indicator_y = y + opts.legendheight - 42;
+                    iy = y + opts.legendheight + 1 - ih - 20;
                 }
                 
-                var fontSize = barsteps > 10 ? 10 : 12;
-                
-                paper.rect(x + 1 + (k * barwidth) + 5 , indicator_y, barwidth - 10, 30, 5).attr({ stroke: "none", fill: colors[i%colors.length] });
-                paper.path(["M", x + 1 + (k * barwidth) + barwidth / 4 + 10, indicator_y + 30, "l", 5, 10, "l", 5, -10]).attr({ stroke: "none", fill: colors[i%colors.length] });
-                paper.text(x + 1 + (k * barwidth) + barwidth / 2, indicator_y + 14, Roo.util.Format.number(v, 0)).attr({ 
-                    "font-size": fontSize,
-                    "font-family": "'Fontin Sans', Fontin-Sans, sans-serif",
-                    "font-weight": "bold",
-                    fill : "#fff"
+                paper.rect(ix , iy, iw, ih, 4).attr({ stroke: "none", fill: colors[i%colors.length] });
+                paper.path(["M", ix + (iw - 10) / 2, iy + ih, "l", 5, 10, "l", 5, -10]).attr({ stroke: "none", fill: colors[i%colors.length] });
+                // align labels center
+                paper.text(ix + iw / 2, iy + ih / 2 - labelSize / 10, Roo.util.Format.number(v, 0)).attr({ 
+                    "font-size": labelSize,
+                    "font-family": labelFont,
+                    "font-weight": labelWeight,
+                    fill : labelColors[i]
                 });
             });
         });
@@ -164,14 +229,18 @@ if (typeof(Raphael) == 'undefined') {
         // right axis
         +ax[1] && axis.push(
             chartinst.rightAxis(
-                width - opts.asixywidth,
-                height - opts.asixxheight,
-                height - y - opts.asixxheight - opts.legendheight,
+                width - axisYWidth,
+                height - axisXHeight,
+                height - y - axisXHeight - opts.legendheight,
                 max,
                 opts.axisystep || 10,
-                opts.asixywidth,
-                barsteps,
-                paper
+                axisYWidth,
+                paper,
+                axisLineColor,
+                axisFont,
+                axisFontSize,
+                axisFontWeight,
+                axisFontColor
             )
         );
         
@@ -179,13 +248,19 @@ if (typeof(Raphael) == 'undefined') {
         +ax[2] && axis.push(
             chartinst.bottomAxis(
                 x ,
-                height - opts.asixxheight,
-                width,
-                opts.axisxlabels.length,
+                height - axisXHeight,
+                width - x - axisYWidth / 2,
                 opts.axisxlabels,
-                barwidth,
-                opts.asixxheight,
-                paper
+                barsteps,
+                barWidth,
+                barGutter,
+                axisXHeight,
+                paper,
+                axisLineColor,
+                axisFont,
+                axisFontSize,
+                axisFontWeight,
+                axisFontColor
             )
         );
         
@@ -204,13 +279,12 @@ if (typeof(Raphael) == 'undefined') {
         return new MVBarchart(this, x, y, width, height, values, opts);
     };
     
-    MVBarchart.prototype.rightAxis = function (x, y, length, max, steps, asixywidth, barsteps, paper)
+    MVBarchart.prototype.rightAxis = function (x, y, length, max, steps, axisYWidth, paper, axisLineColor, axisFont, axisFontSize, axisFontWeight, axisFontColor)
     {
 //        Roo.log('Right Axis');
-//        Roo.log([x, y, length, max, steps, asixywidth]);
+//        Roo.log([x, y, length, max, steps, axisYWidth]);
         
         var path = [],
-            color = "#bababa",
             text = paper.set(),
             d = Math.ceil(max / steps);
         
@@ -222,14 +296,15 @@ if (typeof(Raphael) == 'undefined') {
         for(var i = 0; i <= steps; i++) {
             
             if(i != 0) {
-                paper.text(x + (asixywidth / 2), Y + 15, label).attr({ 
-                    "font-size": (barsteps > 10) ? "12" : "14",
-                    "font-family": "'Fontin Sans', Fontin-Sans, sans-serif",
-                    "font-weight": "bold",
+                // 6 pixels away from bottom of the line
+                paper.text(x + (axisYWidth / 2), Y + axisFontSize / 2 + 6, label).attr({ 
+                    "font-size": axisFontSize,
+                    "font-family": axisFont,
+                    "font-weight": axisFontWeight,
                     "text-anchor": "end",
-                    fill : color
+                    fill : axisFontColor
                 });
-                path = path.concat(["M", x, Y, "l", (asixywidth / 2), 0]);
+                path = path.concat(["M", x , Y, "l", axisYWidth / 2, 0]);
                 
             }
             
@@ -237,7 +312,7 @@ if (typeof(Raphael) == 'undefined') {
             Y -= dx;
         }
         
-        var res = paper.path(path).attr({ stroke: color, "stroke-width": 2 });
+        var res = paper.path(path).attr({ stroke: axisLineColor, "stroke-width": 2 });
 
         res.text = text;
         res.all = paper.set([res, text]);
@@ -249,26 +324,28 @@ if (typeof(Raphael) == 'undefined') {
         return res;
     }
     
-    MVBarchart.prototype.bottomAxis = function (x, y, length, steps, labels, barwidth, eheight, paper)
+    MVBarchart.prototype.bottomAxis = function (x, y, length, labels, barsteps, barWidth, barGutter, height, paper, axisLineColor, axisFont, axisFontSize, axisFontWeight, axisFontColor)
     {
 //        Roo.log('Bottom Axis');
-//        Roo.log([x, y, length, steps, labels, barwidth]);
+//        Roo.log([x, y, length, steps, labels, barWidth]);
         
         var path = ["M", x, y, "l", length, 0],
-            color = "#bababa",
             text = paper.set(),
-            offset = Math.round(barwidth / 2);
+            offset = Math.round(barWidth / 2);
     
         labels.forEach(function(v,k)  {
-            paper.text(x + (k * barwidth) + offset, y + (eheight / 2), v).attr({ 
-                "font-size": (steps > 10) ? "12" : "14",
-                "font-family": "'Fontin Sans', Fontin-Sans, sans-serif",
-                "font-weight": "bold",
-                fill : color
+            if(k >= barsteps) {
+                return;
+            }
+            paper.text(x + (k * (barWidth + barGutter)) + offset, y + (height / 2), v).attr({ 
+                "font-size": axisFontSize,
+                "font-family": axisFont,
+                "font-weight": axisFontWeight,
+                fill : axisFontColor
             });
         });
         
-        var res = paper.path(path).attr({ stroke: color, "stroke-width": 2 });
+        var res = paper.path(path).attr({ stroke: axisLineColor, "stroke-width": 2 });
 
         res.text = text;
         res.all = paper.set([res, text]);
index e665971..4084984 100644 (file)
@@ -19,9 +19,26 @@ Roo = typeof(Roo) != 'undefined' ? Roo:  (imports ? imports.seed.Roo.Roo: {});
      * @param {int} r - radius
      * @param {Array} values
      * @param {Object} opts options
-     *   cut : after this meany items - do not show a pie element?
-     *   
-     *   
+     *   top (number) : top padding
+     *   bottom (number) : bottom padding
+     *   left (number) : left padding
+     *   right (number) : right padding
+     *   background (string) : background color
+     *   borderstlye (string) : border style of empty bars
+     *   bordercolor (string): border color of empty bars 
+     *   barwidth (number) : width of the bars
+     *   color (string) : color of the bars
+     *   indicatorwidth (number): width of indicator
+     *   indicatorheight (number): height of indicator
+     *   indicatorcolor (string): color of indicator
+     *   labelfont (string) : font family of labels
+     *   labelsize (number) : font size of labels
+     *   labelweight (string)(number) : font weight of labels
+     *   labelcolor (string) : font color of the labels
+     *   legendfont (string) : font family of the legend labels
+     *   legendfontsize (number) : font size of the legend labels
+     *   legendfontweight (string)(number) : font weight of the legend labels
+     *   legendfontcolor (string) : font color of the legend colors
      * 
      */
 
@@ -30,47 +47,60 @@ Roo = typeof(Roo) != 'undefined' ? Roo:  (imports ? imports.seed.Roo.Roo: {});
         opts = opts || {};
 
         var chartinst = this,
-            chart = paper.set();
-    
-        opts.top = opts.top || 50;
-        opts.bottom = opts.bottom || 50;
-        opts.left = opts.left || 20;
-        opts.right = opts.right || 20;
-        opts.barwidth = opts.barwidth || 100
-        opts.color = opts.color || '#0A2BC4';
+            chart = paper.set(),
+            top = opts.top || 50,
+            bottom = opts.bottom || 50,
+            left = opts.left || 20,
+            right = opts.right || 20,
+            borderColor = opts.bordercolor || '#CCCCCC',
+            borderStyle = opts.borderstyle || '--',
+            barWidth = opts.barwidth || 100,
+            Color = opts.color || '#0A2BC4',
+            indicatorWidth = opts.indicatorwidth || barWidth / 2,
+            indicatorHeight = opts.indicatorheight || 30,
+            indicatorColor = opts.indicatorcolor || '#0C014D',
+            labelFont = opts.labelfont || "'Fontin Sans', Fontin-Sans, sans-serif",
+            labelSize = opts.labelsize || 16,
+            labelWeight = opts.labelweight || 'bold',
+            labelColor = opts.labelcolor || '#FFFFFF',
+            legendFont = opts.legendfont || "'Fontin Sans', Fontin-Sans, sans-serif",
+            legendFontSize = opts.legendfontsize || 22,
+            legendFontWeight = opts.legendfontweight || 'bold',
+            legendFontColor = opts.legendfontcolor || '#0C024B';
         
         paper.rect(0, 0, width, height).attr({ stroke: "none", fill: (opts.background || "#F0F4F7") });
         
-        var cw = width - opts.left - opts.right,
-            ch = height - opts.top - opts.bottom;
+        var cw = width - left - right,
+            ch = height - top - bottom;
         
-        paper.rect(opts.left, opts.top, opts.barwidth, ch).attr({ stroke: "#CCCCCC", "stroke-dasharray": "--" });
-        paper.rect(opts.left + cw / 2, opts.top, opts.barwidth, ch).attr({ stroke: "#CCCCCC", "stroke-dasharray": "--" });
+        paper.rect(left, top, barWidth, ch).attr({ stroke: borderColor, "stroke-dasharray": borderStyle });
+        paper.rect(left + cw / 2, top, barWidth, ch).attr({ stroke: borderColor, "stroke-dasharray": borderStyle });
         
         values.forEach(function(v,k)  {
             v = Math.min(100, v);
             var bh = v * ch / 100,
-                bx = (k == 0) ? opts.left : opts.left + cw / 2,
-                by = opts.top + ch - bh;
-            
-            paper.rect(bx, by, opts.barwidth, bh).attr({ stroke: "none", fill: opts.color });
+                bx = (k == 0) ? left : left + cw / 2,
+                by = top + ch - bh;
             
-            paper.rect(bx + opts.barwidth / 4 , by - 42, opts.barwidth / 2, 30, 5).attr({ stroke: "none", fill: "#0C014D" });
-            paper.path(["M", bx + opts.barwidth / 4 + 10, by - 12, "l", 5, 10, "l", 5, -10]).attr({ stroke: "none", fill: "#0C014D" });
+            paper.rect(bx, by, barWidth, bh).attr({ stroke: "none", fill: Color });
+
+            paper.rect(bx + (barWidth - indicatorWidth) / 2 , by - 20 - indicatorHeight, indicatorWidth, indicatorHeight, 5).attr({ stroke: "none", fill: indicatorColor });
+            paper.path(["M", bx + (barWidth - indicatorWidth) / 2 + (indicatorWidth - 10) / 2, by - 20, "l", 5, 10, "l", 5, -10]).attr({ stroke: "none", fill: indicatorColor });
             
-            paper.text(bx + opts.barwidth / 4 + 25, by - 28, v + '%').attr({ 
-                "font-size": "16",
-                "font-family": "'Fontin Sans', Fontin-Sans, sans-serif",
-                "font-weight": "bold",
-                fill : "#fff"
+            paper.text(bx + barWidth / 2, by - 20 - indicatorHeight / 2, v + '%').attr({ 
+                "font-size": labelSize,
+                "font-family": labelFont,
+                "font-weight": labelWeight,
+                "text-anchor": "middle",
+                fill : labelColor
             });
             
-            paper.text(bx + opts.barwidth + 25, opts.top + 50, opts.legend[k]).attr({ 
-                "font-size": "22",
-                "font-family": "'Fontin Sans', Fontin-Sans, sans-serif",
-                "font-weight": "bold",
+            paper.text(bx + barWidth + 25, top + 50, opts.legend[k]).attr({ 
+                "font-size": legendFontSize,
+                "font-family": legendFont,
+                "font-weight": legendFontWeight,
                 "text-anchor": "start",
-                fill : "#0C024B"
+                fill : legendFontColor
             });
         });
         
index a3ac8d3..9190dc8 100644 (file)
@@ -19,9 +19,19 @@ Roo = typeof(Roo) != 'undefined' ? Roo:  (imports ? imports.seed.Roo.Roo: {});
      * @param {int} r - radius
      * @param {Array} values
      * @param {Object} opts options
-     *   cut : after this meany items - do not show a pie element?
-     *   
-     *   
+     *   background (string) : background color
+     *   colors (array) : colors of the pies
+     *   borderwidth (number) : width of circle border
+     *   labelfont (string) : font family of labels
+     *   labelsize (number) : font size of labels
+     *   labelweight (string) (number) : font weight of labels
+     *   labelcolor (string) : font color of the labels
+     *   linewidth (number) : width of the lines connecting the legend and the circles
+     *   lineheight (number) : height of the lines connecting the legend and the circles
+     *   legend (array) : legend
+     *   legendfont (string) : font family of the legend labels
+     *   legendfontsize (number) : font size of the legend labels
+     *   legendfontcolor (string) : font color of the legend colors
      * 
      */
 
@@ -32,8 +42,17 @@ Roo = typeof(Roo) != 'undefined' ? Roo:  (imports ? imports.seed.Roo.Roo: {});
         var chartinst = this,
             chart = paper.set(),
             len = values.length;
-        
-        opts.linewidth = opts.linewidth || 200;
+            borderWidth = typeof(opts.borderwidth) != 'undefined' ? opts.borderwidth : 2, // width can be 0 (no border)
+            labelFont = opts.labelfont || "'Fontin Sans', Fontin-Sans, sans-serif",
+            labelSize = opts.labelsize || 18,
+            labelWeight = opts.labelweight || 'bold',
+            labelColor = opts.labelcolor || '#FFFFFF',
+            lineWidth = opts.linewidth || 200,
+            lineHeight = opts.lineheight || 2,
+            lineColor = opts.linecolor || '#FFFFFF',
+            legendFont = opts.legendfont || "'Fontin Sans', Fontin-Sans, sans-serif",
+            legendFontSize = opts.legendfontsize || 18,
+            legendFontColor = opts.legendfontcolor || '#0C024B';
         
         paper.rect(0, 0, width, height).attr({ stroke: "none", fill: (opts.background || "#F0F4F7") });
         
@@ -49,14 +68,17 @@ Roo = typeof(Roo) != 'undefined' ? Roo:  (imports ? imports.seed.Roo.Roo: {});
             return b.value - a.value;
         });
         
+        // dx, dy: position of the center of the circle
+        // dr: radius of the circle
         var dx = cx,
             dy = cy,
             dr = r;
     
         for (i = 0; i < len; i++) {
             
-            paper.circle(dx, dy, dr).attr({ fill: opts.colors && opts.colors[i] || chartinst.colors[i] || "#3E66BC", stroke: "#fff", "stroke-width": 2 });
+            paper.circle(dx, dy, dr).attr({ fill: opts.colors && opts.colors[i] || chartinst.colors[i] || "#3E66BC", stroke: "#fff", "stroke-width": borderWidth });
             
+            // nx, ny: position of the label
             var nx = dx,
                 ny = dy - dr + 20;
         
@@ -65,18 +87,20 @@ Roo = typeof(Roo) != 'undefined' ? Roo:  (imports ? imports.seed.Roo.Roo: {});
             }
             
             paper.text(nx, ny, Roo.util.Format.number(values[i], 0)).attr({ 
-                "font-size": "18",
-                "font-family": "'Fontin Sans', Fontin-Sans, sans-serif",
-                "font-weight": "bold",
-                fill : "#fff"
+                "font-size": labelSize,
+                "font-family": labelFont,
+                "font-weight": labelWeight,
+                "text-anchor": "middle",
+                fill : labelColor
             });
             
-            paper.path(["M", dx, dy - dr, "l", opts.linewidth, 0]).attr({ stroke: "#fff", "stroke-width": 2 });
-            paper.text(dx + opts.linewidth + 10, dy - dr, opts.legend[values[i].origin]).attr({ 
-                "font-size": "18",
-                "font-family": "'Fontin Sans', Fontin-Sans, sans-serif",
+            paper.path(["M", dx, dy - dr, "l", lineWidth, 0]).attr({ stroke: lineColor, "stroke-width": lineHeight });
+
+            paper.text(dx + lineWidth + 10, dy - dr, opts.legend[values[i].origin]).attr({ 
+                "font-size": legendFontSize,
+                "font-family": legendFont,
                 "text-anchor": "start",
-                fill : "#0C024B"
+                fill : legendFontColor
             });
             
             dy = dy + dr / 4 *3;
index 9f7deb7..ceca7d8 100644 (file)
@@ -19,10 +19,27 @@ Roo = typeof(Roo) != 'undefined' ? Roo:  (imports ? imports.seed.Roo.Roo: {});
      * @param {int} r - radius
      * @param {Array} values
      * @param {Object} opts options
-     *   cut : after this meany items - do not show a pie element?
-     *   
-     *   
-     * 
+     *   background (string) : background color
+     *   start_angle (number) : the angle of the starting position of the first pie
+     *   barwidth (number) : width of a pie
+     *   colors (array) : colors of the pies
+     *   cut (number) : after showing this number of elements using this number of pies, merge and show the rest of the elements using one pie (maximum 'cut' + 1 pies in total)
+     *   others (string) : legend label labelling the pie for the merged elements (*required if there are merged elements)
+     *   no_sort (boolean) : sort the values in descending order if it is not set
+     *   labels (array) : labels on the pie
+     *   labelfont (string) : font family of the labels
+     *   labelsize (number) : font size of the labels
+     *   labelweight (string)(number) : font weight of the labels
+     *   labelcolor (string) : font color of the labels
+     *   legend (array) : legend
+     *   legendpos (string) : position of the legend ('right' / 'bottom')
+     *   legendkeyshape (string) : shape of the legend keys ('circle' / 'rect')
+     *   legendkeysize (number) : size of the legend keys (diameter for 'circle' and width for 'rect')
+     *   legendfont (string) : font family of the legend labels
+     *   legendfontsize (number) : font size of the legend labels
+     *   legendfontcolor (string) : font color of the legend colors
+     *   lineheight (number) : distance between two legend labels
+     *   legendcolumn (number) : number of columns used to show legend (1 / 2)
      */
 
     function Piesectorchart(paper, width, height, cx, cy, r, values, opts) {
@@ -32,12 +49,15 @@ Roo = typeof(Roo) != 'undefined' ? Roo:  (imports ? imports.seed.Roo.Roo: {});
         var chartinst = this,
             chart = paper.set(),
             len = values.length,
-            angle = opts.start_angle || 90,
             total = 0,
-            others = 0,
+            angle = opts.start_angle || 90, 
             cut = opts.cut || 9,
-            defcut = true
-            lineheight = opts.lineheight || 30;
+            defcut = true,
+            labels = opts.labels || false; // default no labels
+            labelFont = opts.labelfont || "'Fontin Sans', Fontin-Sans, sans-serif",
+            labelSize = opts.labelsize || 18,
+            labelWeight = opts.labelweight || 'normal',
+            labelColor = opts.labelcolor || '#FFFFFF';
         
         opts.barwidth = opts.barwidth || 80;
         
@@ -56,22 +76,22 @@ Roo = typeof(Roo) != 'undefined' ? Roo:  (imports ? imports.seed.Roo.Roo: {});
 
             return {path: path, stroke: color};
         };
+
+        for (var i = 0; i < len; i++) {
+            total += values[i] * 1;
+            values[i] = {
+                value: values[i],
+                origin: i,
+                valueOf: function () { return this.value; }
+            };
+        }
         
         if (len == 1) {
-            total = values[0];
             paper.circle(cx, cy, r + opts.barwidth / 2).attr({ fill: opts.colors && opts.colors[0] || chartinst.colors[0] || "#3E66BC", "stroke": "#fff" });
             paper.circle(cx, cy, r - opts.barwidth / 2).attr({ fill: opts.background || "#F0F4F7", "stroke": "#fff" });
             
         } else {
             
-            for (var i = 0; i < len; i++) {
-                total += values[i] * 1;
-                values[i] = {
-                    value: values[i],
-                    valueOf: function () { return this.value; }
-                };
-            }
-            
             if (!opts.no_sort) {
                 values.sort(function (a, b) {
                     return b.value - a.value;
@@ -79,6 +99,7 @@ Roo = typeof(Roo) != 'undefined' ? Roo:  (imports ? imports.seed.Roo.Roo: {});
             }
             
             for (i = 0; i < len; i++) {
+                // minimum degree of a pie shown
                 if (defcut && values[i] * 360 / total <= 1.5) {
                     cut = i;
                     defcut = false;
@@ -92,52 +113,138 @@ Roo = typeof(Roo) != 'undefined' ? Roo:  (imports ? imports.seed.Roo.Roo: {});
             }
             
             len = Math.min(cut + 1, values.length);
+
+            var a = angle;
             
             for (i = 0; i < len; i++) {
-                
-                var p = paper.path().attr({
+                paper.path().attr({
                     "stroke": "#fff", 
                     "stroke-width": opts.barwidth
-                }).attr({sector: [cx, cy, angle, angle -= 360 * values[i] / total, opts.colors && opts.colors[i] || chartinst.colors[i], r]});
-            
+                }).attr({sector: [cx, cy, a, a -= 360 * values[i] / total, opts.colors && opts.colors[i] || chartinst.colors[i], r]});
             }
             
         }
+
+        // labels
+        var rad = Math.PI / 180;
+
+        var a = angle;
+
+        for (i = 0; i < len; i++) {
+
+            a -= 360 * values[i] / total;
+
+            // show the label only if the values >= 5% of total
+            if(labels && values[i] / total >= 0.05) {
+                var text = labels[i];
+
+                if(text.indexOf('#qty#') !== -1) {
+                    text = text.replace('#qty#', Math.round(values[i]));
+                }
+
+                if(text.indexOf('#%#') !== -1) {
+                    text = text.replace('#%#', Math.round(values[i] / total * 100) + '%');
+                }
+
+                var tx = cx + r * Math.cos(-(a + 180 * values[i] / total) * rad),
+                    ty = cy + r * Math.sin(-(a + 180 * values[i] / total) * rad);
+
+                paper.text(tx, ty, text).attr({ 
+                    "font-size": labelSize,
+                    "font-family": labelFont,
+                    "font-weight" : labelWeight,
+                    "text-anchor": "middle",
+                    fill : labelColor
+                });
+            }
+        }
+
         
-        var ix = cx + r + opts.barwidth / 2 + 30,
+        legend(paper, cx, cy, r, values, opts, total, len);
+
+        chart.cx = cx;
+        chart.cy = cy;
+        chart.r = r;
+        return chart;
+    }
+    
+    // draw legend
+    function legend(paper, cx, cy, r, values, opts, total, len) 
+    {
+        var legendPos = opts.legendpos || 'right',
+            legendKeyShape = opts.legendkeyshape || 'circle',
+            legendKeySize = opts.legendkeysize || 12,
+            legendFont = opts.legendfont || "'Fontin Sans', Fontin-Sans, sans-serif",
+            legendFontSize = opts.legendfontsize || 18,
+            legendFontColor = opts.legendfontcolor || '#0C014F',
+            lineHeight = opts.lineheight || 30,
+            legendColumn = opts.legendcolumn || 1;
+
+        // default 'legendPos' is 'right'
+        // ix, iy: center position of legend key
+        var ix = cx + r + opts.barwidth / 2 + 30, // 30 pixels away from right of the chart
             iy = cy - r - 30;
-        
+
+        if(legendPos == 'bottom') {
+            ix = cx - r - opts.barwidth / 2 - 30; // 30 pixels away from left of the chart
+            iy = cy + r + opts.barwidth / 2 + 30; // 30 pixels away from bottom of the chart
+
+            // default 'legendColumn' is 1
+            if(legendColumn == 2) {
+                ix = cx - r - opts.barwidth / 2 - 90; // 90 pixels away from left of the chart
+            }
+        }
+
         for (var i = 0; i < len; i++) {
             
-            paper.circle(ix, iy, 6).attr({ fill: opts.colors && opts.colors[i] || chartinst.colors[i] || "#3E66BC", "stroke": "#fff" });
-            
-            var text = (values[i].others) ? opts.others : opts.legend[i] || values[i];
+            if(legendKeyShape == 'rect') {
+                // pass top left position for 'rect'
+                paper.rect(ix - (legendKeySize / 2), iy - (legendKeySize / 2), legendKeySize, legendKeySize, 0).attr({ fill: opts.colors && opts.colors[i] || chartinst.colors[i] || "#3E66BC", "stroke": "#fff" });
+            }
+            else {
+                // pass center position for 'circle'
+                paper.circle(ix, iy, legendKeySize / 2).attr({ fill: opts.colors && opts.colors[i] || chartinst.colors[i] || "#3E66BC", "stroke": "#fff" });
+            }
+
+            var text = (values[i].others) ? opts.others : opts.legend[values[i].origin] || values[i];
             
             if(text.indexOf('#qty#') !== -1) {
                 text = text.replace('#qty#', Math.round(values[i]));
             }
-            
+
             if(text.indexOf('#%#') !== -1) {
                 text = text.replace('#%#', Math.round(values[i] / total * 100) + '%');
             }
+
+            var ty = iy - legendFontSize / 10;
+
+            if(text.includes("\n")) {
+                var ty = iy - legendFontSize / 10 + legendFontSize / 2;
+            }
             
-            paper.text(ix + 20, iy, text).attr({ 
-                "font-size": "18",
-                "font-family": "'Fontin Sans', Fontin-Sans, sans-serif",
+            // 12 pixels away from the right of legend key
+            // align legend key and text horizontally
+            paper.text(ix + legendKeySize / 2 + 12, ty, text).attr({ 
+                "font-size": legendFontSize,
+                "font-family": legendFont,
                 "text-anchor": "start",
-                fill : "#0C014F"
+                fill : legendFontColor
             });
-            
-            iy += lineheight;
-            
+
+            if(legendColumn == 2) {
+                if(i % 2 == 0) {
+                    ix += r + opts.barwidth / 2 + 120;
+                    iy -= lineHeight;
+                }
+                else {
+                    ix -= r + opts.barwidth / 2 + 120;
+                }
+            }
+
+            iy += lineHeight;
         }
+    }
 
-        chart.cx = cx;
-        chart.cy = cy;
-        chart.r = r;
-        return chart;
-    };
-    
     //inheritance
     var F = function() {};
     F.prototype = Raphael.g;
index b95cbd7..dce97c3 100644 (file)
@@ -108,7 +108,8 @@ function extractStyle(node) {
         font: {
             family: typeof node.attrs['font-family'] === 'undefined' ? null : node.attrs['font-family'],
             size: typeof node.attrs['font-size'] === 'undefined' ? null : (node.attrs['font-size']),
-            anchor: typeof node.attrs['text-anchor'] === 'undefined' ? null : node.attrs['text-anchor'],
+            weight: typeof node.attrs['font-weight'] === 'undefined' ? null : (node.attrs['font-weight']),
+            anchor: typeof node.attrs['text-anchor'] === 'undefined' ? null : node.attrs['text-anchor']
         }
     };
 }
@@ -122,7 +123,6 @@ function styleToString(style) {
     //Roo.log(JSON.stringify(style));
     var r = [
         'font-family:' + style.font.family,
-        'font-weight:normal',
         'font-style:normal',
         'font-stretch:normal',
         'font-variant:normal'
@@ -130,6 +130,12 @@ function styleToString(style) {
     if (style.font.size !== null) {
         r.push('font-size: ' + style.font.size + 'px')
     }
+    if (style.font.weight !== null) {
+        r.push('font-weight: ' + style.font.weight);
+    }
+    else {
+        r.push('font-weight: normal');
+    }
 
     return r.join(';')
 
index a90bb64..bfee2b2 100644 (file)
@@ -3,40 +3,91 @@
 <html lang="en">
     <head>
         <title>gRaphaĆ«l Dynamic Bar Chart</title>
-        <script src="../seed/Roo.js" type="text/javascript" charset="utf-8"></script>
 
         <link rel="stylesheet" href="css/demo.css" type="text/css" media="screen" charset="utf-8">
         <link rel="stylesheet" href="css/demo-print.css" type="text/css" media="print" charset="utf-8">
-        <script src="../seed/importz.js" type="text/javascript" charset="utf-8"></script>
+        <script src="/roojs1/roojs-all.js" type="text/javascript" charset="utf-8"></script>
+        <script src="../raphael-min.js" type="text/javascript" charset="utf-8"></script>
+        <script src="../g.raphael.js" type="text/javascript"></script>
+        <script src="../g.bar.horizontal.js" type="text/javascript" charset="utf-8"></script>
+        <script src="../g.bar.overlay.js" type="text/javascript" charset="utf-8"></script>
+        <script src="../g.pie.sector.js" type="text/javascript" charset="utf-8"></script>
         <script type="text/javascript" charset="utf-8">
-        importz.path = '../seed/';
         
         </script>
         
          <script type="text/javascript" charset="utf-8">
-            
-            importz("../g.bar.0.51",'__null__');
-            importz('Raphael');
+;
             window.onload = function () {
-                var r = new Raphael("holder")
-                
-                r.text(340, 290, 'Date').attr( { 'font-size': 12, 'font-family':  "'Fontin Sans', Fontin-Sans, sans-serif" });
-        
-                r.barchart(30, 30, 560, 250, ["1"], {
-                            labels : ["1"],
-                            axis : '0 0 1 1',
-                            axisxlabels :  ["20\/Jun"],
-                            axisystep : 10,
-                            ymin : 0
-                        });
-                console.log(r.toSVG());
+                var r = new Raphael("holder",550,450);
+
+                // r.mhbarchart(1300, 600, [31,10,5,4,4,4,4,4,4,4], {
+                //     colors : ["#FF36C5","#FF36C5","#FF36C5","#FF36C5","#FF36C5","#FF36C5","#FF36C5","#FF36C5","#FF36C5","#FF36C5"],
+                //     axis : '0 0 1 1',
+                //     leftaxislabels :  ["South China Morning Post\n(Hong Kong S.A.R.)","The Standard\n(Hong Kong S.A.R.)","Dainik Tribune\n(India)","Bloomberg\n(Hong Kong S.A.R.)","HK01\n(Hong Kong S.A.R.)","Hong Kong Economic Journal\n(Hong Kong S.A.R.)","Hong Kong Economic Times\n(Hong Kong S.A.R.)","Nikkei Asian Review\n(Hong Kong S.A.R.)","Macau Daily Times\n(Macao S.A.R.)","Chinese Media Group\n(Singapore)"]
+                // });
+
+                // r.mbarchart(50, 10, 1300, 700, [[0,269,0,0,0,0,0,0,0,0,0,0,0,0],[0,21,0,0,0,0,0,0,0,0,0,0,0,0]], {
+                //     gutter: 10,
+                //     barsteps: 14,
+                //     barfill: '#F2F6FF',
+                //     baroffset: 60,
+                //     background: '#FFFFFF',
+                //     colors : ["#D1DEFF","#1E47DA"],
+                //     axis : '0 1 1 0',
+                //     axisxlabels :  ["Jul\n01","Jul\n08","Jul\n15","Jul\n22","Jul\n29","Aug\n05","Aug\n12","Aug\n19","Aug\n26","Sep\n02","Sep\n09","Sep\n16","Sep\n23","Sep\n30"],
+                //     axisystep : 5,
+                //     asixywidth: 100,
+                //     asixxheight: 80,
+                //     axislinecolor: '#ACACAC',
+                //     axisfont: 'Work Sans',
+                //     axisfontsize: 18,
+                //     axisfontweight: 600,
+                //     axisfontcolor: '#606060',
+                //     labelfont: 'Work Sans',
+                //     labelsize: 18,
+                //     labelweight: 600,
+                //     labelcolors: ["#323232","#FFFFFF"],
+                //     legends: ["Guaranteed online news postings: 269","Media write-up by journalists (Earned): 21"],
+                //     legendheight: 120,
+                //     legendkeyshape: 'rect',
+                //     legendkeysize: 18,
+                //     legendfont: 'Work Sans',
+                //     legendfontsize: 22,
+                //     legendfontweight: 600,
+                //     legendfontcolor: '#606060'
+                // });
+                        
+                // console.log(r);
+
+
+        r.piesectorchart(550, 450, 275, 150, 105, [52,27,31,9,31,20,12,5,2,29,23,4,2,2,4,1,2], {
+            background: '#FFFFFF',
+            barwidth : 70,
+            colors:  ["#83DBFF","#F9C80A","#1E47DA","#B21ADF","#FF11BA","#FF8C30"],
+            cut: 5,
+            others: 'Others - #qty# (#%#)',
+            labels: ["#%#","#%#","#%#","#%#","#%#","#%#","#%#","#%#","#%#","#%#","#%#","#%#","#%#","#%#","#%#","#%#","#%#"],
+            labelfont: 'Work Sans',
+            labelsize: 20,
+            labelweight: 600,
+            legend:  ["Hong Kong S.A.R. - #qty# (#%#)","Singapore - #qty# (#%#)","India - #qty# (#%#)","Australia - #qty# (#%#)","Taiwan - #qty# (#%#)","Indonesia - #qty# (#%#)","Philippines - #qty# (#%#)","New Zealand - #qty# (#%#)","Cambodia - #qty# (#%#)","Malaysia - #qty# (#%#)","Vietnam - #qty# (#%#)","Thailand - #qty# (#%#)","Asia Pacific - #qty# (#%#)","South Korea - #qty# (#%#)","Macao S.A.R. - #qty# (#%#)","Pakistan - #qty# (#%#)","Laos - #qty# (#%#)"],
+            legendpos: 'bottom',
+            legendkeyshape: 'rect',
+            legendkeysize: 14,
+            legendfont: 'Work Sans',
+            legendfontsize: 14,
+            legendfontcolor: '#323232',
+            lineheight : 40,
+            legendcolumn : 2
+        });
                         
                      
             };
         </script>
     </head>
     <body class="raphael" id="g.raphael.dmitry.baranovskiy.com">
-        <div id="holder"></div>
+        <div id="holder" style='width:1300px !important; height:600px!important'></div>
         <p>
             Demo of <a href="http://g.raphaeljs.com/">gRaphaĆ«l</a> JavaScript library.
         </p>