Page 1 of 1

Group bars/draw line to separate bar groups/add axes?

Posted: Tue Dec 09, 2014 1:06 pm
by 17770651
I need to group several bars within one series (because there is a relation in between) and to draw an annotated Line (e.g. Job A) for visual separation. Concerning that topic I studied the example code for multiple axes and tried to adopt it but not yet successfully. The snapshot shows a Tee-Bar-Chart-example which is realized in VB6, but I have to implement it by HTML5/JavaScript. Any help would be nice.

Thanks, Juliane

Re: Group bars/draw line to separate bar groups/add axes?

Posted: Wed Dec 10, 2014 11:41 am
by yeray
Hello,

Do you have a simple example in VB6 we can take as model?

Re: Group bars/draw line to separate bar groups/add axes?

Posted: Fri Dec 12, 2014 1:58 pm
by 17770651
Dear Yeray,

Here the VB6 code:

Code: Select all

'
' shows qsv bar chart.
' shows 1-mean bar chart
'
Private Sub ShowQSVMeanChart( _
        ByVal sTeeFile As String, _
        ctType As ChartType)

    Dim cQSVData As Dictionary
    Dim cSubstAlias As Dictionary
    Dim cSubstQSV As Dictionary
    Dim cSubstGroup As Dictionary
    Dim cSubstRank As Dictionary
    Dim cSubstJob As Dictionary
    Dim cGroups As Dictionary
    Dim cSubstRel As Dictionary
    Dim cSubstRelAlias As Dictionary
    Dim cJobs As Dictionary
    Dim vSubstance, vGroup, vSubst
    Dim bDummy As Boolean
    Dim nPos As Long
    Dim nIndex As Long
    Dim clColor As OLE_COLOR
    Dim clColors(6) As OLE_COLOR
    
    If ctType <> ctQSV And ctType <> ctMean Then
        RaiseError vbError, "ICChart.ShowQSVChart()", "Invalid chart type."
    End If
    
    Set cGroups = New Dictionary
    Set cJobs = New Dictionary
    
    ' get qsv data
    Set cQSVData = GetQSVMeanData(ctType)
    
    ' split data in single dic's
    Set cSubstAlias = cQSVData("alias")
    Set cSubstGroup = cQSVData("group")
    Set cSubstRank = cQSVData("rank")
    Set cSubstQSV = cQSVData("qsv")
    Set cSubstJob = cQSVData("job")
    Set cSubstRel = cQSVData("rel")
    Set cSubstRelAlias = cQSVData("rel_alias")
    
    ' get group count
    nPos = 1
    For Each vSubstance In cSubstGroup.Keys()
        If Not cGroups.Exists(cSubstGroup(vSubstance)) Then
            cGroups.Add cSubstGroup(vSubstance), nPos
            nPos = nPos + 1
        End If
    Next
    
    ' show chart now: prepare chart for qsv
    With frmICChart.tchSeries
    
        .ClearChart
        .Import.LoadFromFile sTeeFile     ' load config
        
        .RemoveAllSeries
        .Header.Text.Clear
        .Legend.Visible = False
        .Zoom.Enable = True
        .Zoom.Animated = True
        .Zoom.AnimatedSteps = 15
        .Zoom.Direction = tzdBoth
        .Zoom.MouseButton = mbLeft
        .Zoom.Brush.Style = bsClear
        .Axis.Bottom.Labels.Separation = 0
        .Canvas.Pen.Width = 0
        
        If ctType = ctQSV Then
            .Header.Text.Add UCase(qsvFeature)
            .Axis.Left.Title.Caption = UCase(qsvFeature) + " VALUES"
            .Axis.Bottom.Title.Caption = sChartQSVAxisBottomTitle
        End If
        
        If ctType = ctMean Then
            .Header.Text.Add UCase(signalFeature)
            .Axis.Left.Title.Caption = UCase(signalFeature) + " VALUES"
            .Axis.Bottom.Title.Caption = sChartMeanAxisBottomTitle
        End If
    End With

    ' a little color palette
    clColors(0) = vbRed
    clColors(1) = vbBlue
    clColors(2) = vbGreen
    clColors(3) = vbMagenta
    clColors(4) = vbYellow
    clColors(5) = vbCyan
    clColors(6) = vbBlack

    Dim nPosFix
    ' add series to chart
    nPos = 0
    nPosFix = 0
    nIndex = 1
    bDummy = True
    
    Dim xyz
    With frmICChart.tchSeries.Series(frmICChart.tchSeries.AddSeries(scBar))
        .asBar.MultiBar = mbSide
        .asBar.AutoBarSize = True
        .asBar.BarWidthPercent = 80
        .asBar.BarPen.Width = 0
        .Marks.Visible = False
        
        For Each vSubstance In cSubstGroup.Keys
            nPos = nPos + 1
            nPosFix = nPos
            .AddXY nPos, cSubstQSV(vSubstance), cSubstAlias(vSubstance), vbRed
            For Each xyz In cSubstRel(vSubstance)
                nPos = nPos + 1
                .AddXY nPosFix + cSubstRel(vSubstance)(xyz), cSubstQSV(xyz), cSubstRelAlias(vSubstance)(xyz), vbBlue
            Next
            nPos = nPos + 1
            cJobs.Add nPos - 0.2, cSubstJob(vSubstance)
            .AddNullXY nPos, cSubstQSV(xyz), vbNullString ', frmICChart.BackColor
        Next
        
        'frmICChart.tchSeries.Axis.Bottom.Labels.Font.Size = 7
        'frmICChart.tchSeries.Axis.Left.Labels.Font.Size = 7
        'If .Count > nScaleDownLimit1 Then
        '    frmICChart.tchSeries.Axis.Bottom.Labels.Font.Size = 6
        '    frmICChart.tchSeries.Axis.Left.Labels.Font.Size = 6
        'End If
        'If .Count > nScaleDownLimit2 Then
        '    frmICChart.tchSeries.Axis.Bottom.Labels.Font.Size = 4
        '    frmICChart.tchSeries.Axis.Left.Labels.Font.Size = 4
        'End If
        
    End With

    With frmICChart
        Set .Jobs = cJobs
        .GroupDistance = cGroups.Count()
        .tchSeries.Zoom.Undo
        .tchSeries.Repaint
        .countData = nPos
    
        .tchSeries_Init
    End With
End Sub
Regards, Juliane

Re: Group bars/draw line to separate bar groups/add axes?

Posted: Mon Dec 15, 2014 12:17 pm
by yeray
Hi Juliane,

There are many variables being used in that code snipped we don't have here. Could you please arrange a simple example project we can run as-is to reproduce the problem here?

Thanks in advance.

Re: Group bars/draw line to separate bar groups/add axes?

Posted: Thu Dec 18, 2014 10:56 am
by 17770651
Hello,
The data structure looks like this: attached code. The values for the targets are derived from variable “bar_data”. The requirements are the following:
Groups of targets are to be shown in given order.
Group name (job) must be recognizable for related targets.
The bar of first target of group is to be shown in different color.
The font size of labels for targets should be resized automatically in case there are lots of bars to be shown.
Editor: WebStorm8.0.5

Thanks,
Juliane

Code: Select all

<!DOCTYPE html>
<html>
<head>
    <title>Groups of Bars</title>
    <script src="js/teechart.js" type="text/javascript"></script>
    <script>
        function draw() {

            var rel_groups = [["jobA", ['target5','target4','target11']], ["jobB", ['target13']],["jobC", ['target8','target7','target6']]];

            var bar_data = ['mg_name1',{'target1':7,'target2':8,'target3':9,'target4':4,'target5':3,'target6':2,'target7':11,'target8':5,'target9':6,'target10':12,'target11':10,'target12':14,'target13':16},'feat_name1'];

            var target_val = bar_data[1];

            var val_array = [];
            var x_array = []; //  to be solved: bar groups
            var target_name = []; //  to be solved: grouped target_names
            var number_target;
            var line; // to be solved: Line after jobA
            var anno; //  to be solved: Annotation: for example "jobA" for Line after jobA



            for (var i = 0; i < rel_groups.length; i++)
            {
                var iter = rel_groups[i][1];

                for (var k = 0; k < iter.length; k++)
                {
                    target_name = rel_groups[i][1][k];

                    for (target in target_val)
                    {
                        if (target == target_name)
                        {
                            x_array.push (target);
                            val_array.push (target_val[target]);
                        }
                    }
                }
            }

            number_target = x_array.length;
            var x_array_numb = new Array(number_target);
            x_array_numb[0] = 1;

            for (var i = 0; i<number_target; ++i) {
                x_array_numb[i] = i;
            }

            Chart1=new Tee.Chart("canvas");

            var vdata1 = new Tee.Bar();
            Chart1.addSeries(vdata1);
            vdata1.data.values = val_array;
            vdata1.data.x =  x_array_numb;

            Chart1.axes.bottom.labels.ongetlabel=function(value,s)
            {
                  return x_array[value]
            }

            Chart1.title.text="Groups of Bars?";
            Chart1.axes.bottom.labels.rotation = 90;
            Chart1.draw();
        }
    </script>


</head>
<body onload="draw()">
    <br><canvas id="canvas" width="600" height="400">
    This browser does not seem to support HTML5 Canvas.
    </canvas>


</body>
</html>

Re: Group bars/draw line to separate bar groups/add axes?

Posted: Fri Dec 19, 2014 2:54 pm
by yeray
Hello ,

Take a look at this variant.
I'm manually drawing the vertical lines and the "group" texts:

Code: Select all

function draw() {
    var rel_groups = [["jobA", ['target5','target4','target11']], ["jobB", ['target13']],["jobC", ['target8','target7','target6']]];

    var bar_data = ['mg_name1',{'target1':7,'target2':8,'target3':9,'target4':4,'target5':3,'target6':2,'target7':11,'target8':5,'target9':6,'target10':12,'target11':10,'target12':14,'target13':16},'feat_name1']

	var target_val = bar_data[1];
	
	var val_array = [];
    var x_array = []; //  to be solved: bar groups
    var target_name = []; //  to be solved: grouped target_names
    var number_target;
    var line; // to be solved: Line after jobA
    var anno; //  to be solved: Annotation: for example "jobA" for Line after jobA

	for (var i = 0; i < rel_groups.length; i++)
    {
		var iter = rel_groups[i][1];

		for (var k = 0; k < iter.length; k++)
        {
			target_name = rel_groups[i][1][k];

			for (target in target_val)
			{
				if (target == target_name)
				{
					x_array.push (target);
					val_array.push (target_val[target]);
				}
			}
		}
	}

	number_target = x_array.length;
	var x_array_numb = new Array(number_target);
	x_array_numb[0] = 1;

	for (var i = 0; i<number_target; ++i) {
		x_array_numb[i] = i;
	}
			
    Chart1=new Tee.Chart("canvas1");

    Chart1.ondraw=function() {
		var c=Chart1.ctx,
			y0=Chart1.chartRect.y, y1=Chart1.chartRect.getBottom();

		c.beginPath();

		var pos = 0;
		var diff = Chart1.axes.bottom.calc(0.5) - Chart1.axes.bottom.calc(0);
		var f =  new Tee.Format(Chart1);
		var r = new Rectangle();
		r.height=f.textHeight("Wj");
		
		for (var i = 0; i<rel_groups.length; i++) {
			c.moveTo( pos + Chart1.axes.bottom.calc(rel_groups[i][1].length) - diff, y0 );
			c.lineTo( pos + Chart1.axes.bottom.calc(rel_groups[i][1].length) - diff, y1 );			
			c.strokeStyle="black";
			c.lineWidth=1;
			c.stroke();
			
			var s = rel_groups[i][0];
			r.width = f.textWidth(s);
			r.x = pos + Chart1.axes.bottom.calc(rel_groups[i][1].length) - diff - r.height;
			r.y = y0;
			f.fill = "";       
			c.save();
			c.translate(r.x, r.y);
			c.rotate(-Math.PI*90/180);
			c.textAlign = "right";
			r.x = -rotatedWidth(90, r.width) * 0.5;
			r.y = -(rotatedWidth(90, r.height) * 0.5)+3;
			f.drawText(r, s);
			c.restore();
			
			pos = pos + Chart1.axes.bottom.calc(rel_groups[i][1].length) - Chart1.axes.bottom.calc(0);
		}
	}
	
    var vdata1 = new Tee.Bar();
    Chart1.addSeries(vdata1);
    vdata1.data.values = val_array;
    vdata1.data.x = x_array_numb;
	
	Chart1.axes.bottom.labels.ongetlabel=function(value,s)
	{
		return x_array[value]
	}

    Chart1.title.text="Groups of Bars";
    Chart1.axes.bottom.labels.rotation = 90;
    Chart1.draw();
}

function Rectangle(x,y,width,height)
{
  this.set(x,y,width,height);
}

Rectangle.prototype.set=function(x,y,width,height) {
  this.x=x;
  this.y=y;
  this.width=width;
  this.height=height;
};

rotatedWidth = function(a, w) {
  return Math.abs(Math.sin(toRadians(a)) * w);
}

function toRadians(angle) {
  return angle * (Math.PI / 180);
}

Re: Group bars/draw line to separate bar groups/add axes?

Posted: Tue Jan 20, 2015 1:35 pm
by 17770651
Dear Yeray,
Thank you very much for your help, it works fine.

Kind regards,
Juliane

Re: Group bars/draw line to separate bar groups/add axes?

Posted: Mon May 04, 2015 1:23 pm
by 17770651
Hello,
I would like to add to this code just one feature (see below), but legend annotations are empty.
Regards, Juliane

Code: Select all

Chart1.legend.textStyle="label";

Re: Group bars/draw line to separate bar groups/add axes?

Posted: Tue May 05, 2015 11:17 am
by yeray
Hello Juliane,

Setting the "label" textStyle in the legend makes it to use the strings on the series' data.labels. So, if you want to use it, you can populate the data.labels array as follows:

Code: Select all

	vdata1.data.labels = x_array;
	vdata1.marks.style="value"; //this is to force the series marks to only show the values and not the labels