0

Diagramm mit Daten aus Funktionsfeldern

Ich möchte gerne ein Balkendiagramm erzeugen, das Werte aus mehreren Formelfeldern des Datensatzes wiedergibt.

Soweit konnte ich das bereits mit Quickchart und deren open api realisieren.

Bei meiner Integration triggert die entsprechende Funktion aber erst wenn der Tab geöffnet wird, und je nachdem wie man sich durch die Datensätze bewegt, muss man dann hin und her schalten, damit die Grafik erzeugt wird.

Womit wir bei dem zweiten Punkt sind, den ich nur so halb gut finde:

Im Falle meiner Einbindung sendet Ninox die Daten an Quickchart und erhält dann im Gegenzug die Grafik als png.

Ich zeige diese Grafik dann im Funktionsfeld an, als iframe. Man sieht aber so einen blöden Rahmen und 2 scrollbalken. Das ganze sieht nicht so schön aus, und ist auf dem Mac auch nicht richtig scharf. Wobei letzteres wohl per Option der Ausgabe via pixelrate zu steuern ist.

Meine beiden Fragen

A) gibt es ein bessere Idee um die Erzeugung der Grafik zu triggern

B) kann man so eine Einbindung nicht auch irgendwie schicker hinbekommen? Mit Html5 oder so?

 

Hat hier jemand mit einem ähnlichen Szenario schon Erfahrung gemacht?

 

Allen ein gutes neues Jahr und vielen Dank.

2 Antworten

null
    • mirko3
    • vor 3 Monaten
    • Gemeldet - anzeigen

    Hallo Arwin. Über HTML ist mir nur die sehr aufwändige Form mit svg-Grafiken bekannt. Da braucht es schon tiefere Einsicht in das Thema, die ich nicht habe.

    Graphisch halbwegs ansprechend ist eine schräge Version mit Fortschrittsbalken (siehe: https://forum.ninox.de/profile/x2h8xvf?pg=2), die optisch ähnliche Auskünfte gibt, wenn die Spaltenanzahl niedrig ist. Aber ist eben kein Diagramm.

    In Ninox sind es die an DOS-Zeiten erninnernden Diagramme. Die können aber auch nur für jeweils einen Datensatz benutzt werden. Das Script für eine Diagrammansicht lautet wie unten. Hier hast Du wenigstens nicht den Transport Deiner Daten über diverse Server, aber richtig gern ansehen tue ich sie mir nicht. Mirko

    let me := this;
    (select Tabelle)[this = me]
    
    • Michi.1
    • vor 3 Monaten
    • Gemeldet - anzeigen

    Wenn du mit die variablen richtig übergeben kannst (am Ende vom Skript) , dann ist das eventuell was.

    Einfach in ein Funktionsfeld

    let css := "
    <!DOCTYPE html>
    <html lang=de>
    <head>
    <body>
        <div id='chart'>
    
        </div>
    
        <script type='text/javascript' src='js/chart.js'></script>
        <script type='text/javascript' src='js/line-chart.js'></script>
        <script type='text/javascript' src='js/main.js'></script>
    </body>
    </html>
    <script>
    function Chart() {}
    Chart.prototype = {
        colors: ['#14568a', '#8a1616', '#dddb2f', '#1d7e07', '#2c4a4a'],
        createSvgElement: function(tag, attributes) {
            var element = document.createElementNS('http://www.w3.org/2000/svg', tag);
            for(var key in attributes) {
                element.setAttribute(key, attributes[key]);
            }
            return element;
        },
        formatNumber: function(number) {
            var string = '';
    
            number = number + '';
            while(number.length > 3) {
                string = '.' + number.substr(number.length - 3) + string;
                number = number.substr(0, number.length - 3);
            }
            string = number + string;
    
            return string;
        }
    };
    function LineChart(container, data) {
        Chart.call(this);
    
        var chart = this;
    
        chart.container = container;
        chart.labels = data.labels;
        chart.lines = data.lines;
    
        chart.svgElement = chart.createSvgElement('svg', {
            style: 'font-family: Arial, sans-serif;'
        });
        chart.container.appendChild(chart.svgElement);
    
        window.addEventListener('resize', function() {
            chart.render();
        });
    
        chart.render();
    }
    LineChart.prototype = Object.create(Chart.prototype, {
        constructor: {
            value: LineChart
        },
        render: {
            value: function() {
                var chart = this;
    
                chart.width = chart.container.clientWidth;
                chart.height = 500;
    
                chart.svgElement.setAttribute('width', chart.width);
                chart.svgElement.setAttribute('height', chart.height);
                chart.svgElement.setAttribute('viewBox', '0 0 ' + chart.width + ' ' + chart.height);
    
                while(chart.svgElement.childNodes.length) {
                    chart.svgElement.removeChild(chart.svgElement.firstChild);
                }
    
                chart.renderLegend();
                chart.renderAxis();
                chart.renderLines();
            }
        },
        renderLegend: {
            value: function() {
                var chart = this;
    
                chart.legend = chart.createSvgElement('g');
                chart.svgElement.appendChild(chart.legend);
    
                var offset = 0;
                for(var index = 0; index < chart.lines.length; index++) {
                    var legendItemElement = chart.createSvgElement('g', {
                        transform: 'translate(' + offset + ', 0)'
                    });
                    chart.legend.appendChild(legendItemElement);
    
                    var circleElement = chart.createSvgElement('circle', {
                        cx: 10,
                        cy: 8,
                        r: 3.5,
                        fill: chart.colors[index % chart.colors.length],
                        stroke: 'none'
                    });
                    legendItemElement.appendChild(circleElement);
    
                    var textElement = chart.createSvgElement('text', {
                        x: 20,
                        y: 13,
                        'font-size': 14
                    });
                    legendItemElement.appendChild(textElement);
    
                    textElement.textContent = chart.lines[index].title;
    
                    offset += legendItemElement.getBBox().width + 20;
                }
            }
        },
        renderAxis: {
            value: function() {
                var chart = this;
    
                chart.axis = {
                    x: {
                        nthLabel: 1
                    },
                    y: {
                        maximum: 1,
                        step: 1
                    }
                };
    
                for(var lineIndex = 0; lineIndex < chart.lines.length; lineIndex++) {
                    for(var datumIndex = 0; datumIndex < chart.lines[lineIndex].data.length; datumIndex++) {
                        chart.axis.y.maximum = Math.max(chart.axis.y.maximum, chart.lines[lineIndex].data[datumIndex]);
                    }
                }
    
                while(chart.axis.y.step * 7 < chart.axis.y.maximum) {
                    chart.axis.y.step *= 10;
                }
                if(chart.axis.y.step % 2 === 0 && chart.axis.y.step * 3.5 > chart.axis.y.maximum) {
                    chart.axis.y.step /= 2;
                }
    
                chart.axis.y.maximum = Math.ceil(chart.axis.y.maximum / chart.axis.y.step) * chart.axis.y.step;
    
                chart.axis.x.element = chart.createSvgElement('g');
                chart.svgElement.appendChild(chart.axis.x.element);
    
                chart.axis.y.element = chart.createSvgElement('g');
                chart.svgElement.appendChild(chart.axis.y.element);
    
                for(var index = 0; index < chart.labels.length; index++) {
                    chart.axis.x.element.appendChild(chart.renderXAxisLabel(chart.labels[index]));
                }
    
                for(var y = 0; y <= chart.axis.y.maximum; y += chart.axis.y.step) {
                    chart.axis.y.element.appendChild(chart.renderYAxisLabel(chart.formatNumber(y)));
                }
    
                chart.padding = {
                    top: chart.legend.getBBox().height + 20,
                    left: -1 * Math.min(chart.axis.x.element.getBBox().x + 20, chart.axis.y.element.getBBox().x - 8),
                    bottom: chart.axis.x.element.getBBox().height
                };
    
                chart.axis.x.element.setAttribute('transform', 'translate(0, ' + (chart.height - chart.padding.bottom) + ')');
                chart.axis.x.stepSize = chart.labels.length > 1 ? (chart.width - chart.padding.left - 40) / (chart.labels.length - 1) : 20;
    
                while(chart.axis.x.stepSize * chart.axis.x.nthLabel < 20) {
                    chart.axis.x.nthLabel++;
                }
    
                if(chart.axis.x.nthLabel > 1) {
                    for(var index = chart.axis.x.element.childNodes.length - 1; index > 0; index--) {
                        if(index % chart.axis.x.nthLabel) {
                            chart.axis.x.element.removeChild(chart.axis.x.element.childNodes[index]);
                        }
                    }
                }
    
                for(var index = 0; index < chart.axis.x.element.childNodes.length; index++) {
                    chart.axis.x.element.childNodes[index].setAttribute('transform', 'translate(' + (chart.padding.left + 20 + chart.axis.x.nthLabel * index * chart.axis.x.stepSize) + ', 0)');
                }
    
                chart.axis.y.element.setAttribute('transform', 'translate(' + chart.padding.left + ', 0)');
                chart.axis.y.stepSize = (500 - chart.padding.bottom - chart.padding.top) / (chart.axis.y.maximum / chart.axis.y.step);
                for(var index = 0; index < chart.axis.y.element.childNodes.length; index++) {
                    chart.axis.y.element.childNodes[index].setAttribute('transform', 'translate(0, ' + (500 - chart.padding.bottom - index * chart.axis.y.stepSize) + ')');
                }
            }
        },
        renderXAxisLabel: {
            value: function(label) {
                var chart = this;
    
                var labelElement = chart.createSvgElement('g');
    
                var lineElement = chart.createSvgElement('line', {
                    x1: 0,
                    y1: 0,
                    x2: 0,
                    y2: 5,
                    stroke: '#c0c0c0'
                });
                labelElement.appendChild(lineElement);
    
                var textElement = chart.createSvgElement('text', {
                    x: -15,
                    y: 7,
                    'font-size': 11,
                    'text-anchor': 'end',
                    transform: 'rotate(-45 0 0)'
                });
                textElement.textContent = label;
                labelElement.appendChild(textElement);
    
                return labelElement;
            }
        },
        renderYAxisLabel: {
            value: function(label) {
                var chart = this;
    
                var labelElement = chart.createSvgElement('g');
    
                var lineElement = chart.createSvgElement('line', {
                    x1: 0,
                    y1: 0,
                    x2: chart.width,
                    y2: 0,
                    stroke: '#c0c0c0'
                });
                labelElement.appendChild(lineElement);
    
                var textElement = chart.createSvgElement('text', {
                    x: -8,
                    y: 4,
                    'font-size': 11,
                    'text-anchor': 'end'
                });
                textElement.textContent = label;
                labelElement.appendChild(textElement);
    
                return labelElement;
            }
        },
        renderLines: {
            value: function() {
                var chart = this;
    
                for(var lineIndex = 0; lineIndex < chart.lines.length; lineIndex++) {
                    chart.lines[lineIndex].element = chart.createSvgElement('g', {
                        transform: 'translate(' + (chart.padding.left + 20) + ', ' + (500 - chart.padding.bottom) + ')'
                    });
                    chart.svgElement.appendChild(chart.lines[lineIndex].element);
    
                    var points = [];
                    chart.lines[lineIndex].circles = [];
    
                    for(var datumIndex = 0; datumIndex < chart.lines[lineIndex].data.length; datumIndex++) {
                        var point = {
                            x: datumIndex * chart.axis.x.stepSize,
                            y: -1 * chart.lines[lineIndex].data[datumIndex] * (chart.axis.y.stepSize / chart.axis.y.step),
                        };
                        points.push(point.x + ',' + point.y);
    
                        if(chart.axis.x.stepSize >= 10) {
                            var circleElement = chart.createSvgElement('circle', {
                                cx: point.x,
                                cy: point.y,
                                r: 3.5,
                                fill: chart.colors[lineIndex % chart.colors.length],
                                stroke: 'none'
                            });
                            chart.lines[lineIndex].element.appendChild(circleElement);
                            chart.lines[lineIndex].circles.push(circleElement);
                        }
                    }
    
                    var lineElement = chart.createSvgElement('polyline', {
                        points: points.join(' '),
                        stroke: chart.colors[lineIndex % chart.colors.length],
                        'stroke-width': 2,
                        fill: 'none'
                    });
                    chart.lines[lineIndex].element.appendChild(lineElement);
                    chart.lines[lineIndex].line = lineElement;
                }
            }
        }
    });
    
    
    var data = {
        labels: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni','Juli','August','September','Oktober','November','Dezember'],
        lines: [{
            title: '2020',
            data: [10,12,15,23,28],
        }, {
            title: '2021',
            data: [15,18,10,9,20]
        },{
            title: '2022',
            data: [12,8,15,9,25]
        }]
    };
    new LineChart(document.getElementById('chart'), data);
    
    </script>";
    html(css)
    

Content aside

  • vor 3 MonatenZuletzt aktiv
  • 2Antworten
  • 42Ansichten
  • 3 Folge bereits