Jump to content

Recommended Posts

Posted

Добрый день!

Можно как то добавить новый Axes, чтобы он был справа, я не смог найти примеры на форуме

Хочется повторить вот такой график

Слева BarSeries по кол-ву и с привязкой к левой Axes

Справа LineSeries по процентам и с привязкой к правой Axes

image.thumb.png.d8c8a902259a4499537749e0ac14c5a7.png

Posted

1. UniChart1

image.png.92fefcf034228c5696dc259c9e7c1113.png

2. 

procedure TMainForm.CreateDemoData;
var
  CDS: TClientDataSet;
begin
  CDS := TClientDataSet.Create(Self);
  // создаём поля
  with CDS.FieldDefs do
  begin
    Add('Category', ftString, 50);
    Add('Count', ftInteger);
    Add('Percent', ftFloat);
  end;
  CDS.CreateDataSet;
  CDS.AppendRecord(['1200-1400', 10520, 41]);
  CDS.AppendRecord(['1000-1200', 5439, 62]);
  CDS.AppendRecord(['1400-1600', 4339, 79]);
  CDS.AppendRecord(['Other', 3775, 94]);
  CDS.AppendRecord(['<1000', 1700, 100]);
  DataSource1.DataSet := CDS;

  UniBarSeries1.DataSource := DataSource1;
  UniBarSeries1.XLabelsSource := 'Category';
  UniBarSeries1.YValues.ValueSource := 'Count';

  UniLineSeries1.DataSource := DataSource1;
  UniLineSeries1.XLabelsSource := 'Category';
  UniLineSeries1.YValues.ValueSource := 'Percent';
end;

3. 

procedure TMainForm.UniFormCreate(Sender: TObject);
begin
  CreateDemoData;
end;

4. UniChart1.ClientEvents.UniEvents ->

function chart.beforeInit(sender, config)
{
    config.innerPadding = {
        left: 4,
        right: 10,
        top: 40
    };

    config.axes = [{
        type: 'numeric',
        position: 'left',
        fields: ['A'],
        title: 'Count',
        grid: true
    },{
        type: 'numeric',
        position: 'right',
        fields: ['B'],
        minimum: 0,
        maximum: 100,
        title: 'Percent',
        label: {
            renderer: function(v){
                return v + '%';
            }
        }
    },{
        type: 'category',
        position: 'bottom',
        fields: ['LL']
    }];

    Ext.Array.each(config.series || [], function(series){

        // BAR SERIES
        if (series.type === 'bar') {

            series.label = {
                field: 'A',
                display: 'outside',
                orientation: 'horizontal',
                padding: 10,
                renderer: function(v){
                    return Ext.util.Format.number(v,'0,000');
                }
            };

        }

        // LINE SERIES
        if (series.type === 'line') {

            series.axis = 'right';

            series.style = {
                strokeStyle: '#7cb342',
                lineWidth: 2
            };

            series.marker = {
                radius: 4
            };

            series.label = {
                field: 'B',
                display: 'over',
                padding: 8,
                renderer: function(v){
                    return v + '%';
                }
            };

            series.renderer = function(sprite, cfg, rendererData, index)
            {
                var rec = rendererData.store.getAt(index);
                var val = rec.get('B');

                if (val >= 80) {
                    cfg.fillStyle = '#d9534f';
                    cfg.strokeStyle = '#d9534f';
                } else {
                    cfg.fillStyle = '#7cb342';
                    cfg.strokeStyle = '#7cb342';
                }

                return cfg;
            };

        }

    });
}

 

Posted

Добрый день!

А как можно принудительно обновить Chart, чтобы сработали события series.renderer

Хочу чтобы при выделении столбика он раскрашивался в другой цвет,

для этого добавил в chart.beforeInit

переменную sender.select_index = 0; и series.renderer = function(sprite, cfg, rendererData, index) для BarSeries

 

function chart.beforeInit(sender, config)
{
    sender.select_index = 0;

    config.innerPadding = {
        left: 4,
        right: 10,
        top: 40
    };

    config.axes = [{
        type: 'numeric',
        position: 'left',
        fields: ['A'],
        title: 'Count',
        grid: true
    },{
        type: 'numeric',
        position: 'right',
        fields: ['B'],
        minimum: 0,
        maximum: 100,
        title: 'Percent',
        label: {
            renderer: function(v){
                return v + '%';
            }
        }
    },{
        type: 'category',
        position: 'bottom',
        fields: ['LL']
    }];

    Ext.Array.each(config.series || [], function(series){

        // BAR SERIES
        if (series.type === 'bar') {

            series.label = {
                field: 'A',
                display: 'outside',
                orientation: 'horizontal',
                padding: 10,
                renderer: function(v){
                    return Ext.util.Format.number(v,'0,000');
                }
            };
            series.renderer = function(sprite, cfg, rendererData, index)
            {
                cfg.fillStyle = 'green';
                cfg.strokeStyle = 'green';
                
                if (index === sender.select_index)
                {
                    cfg.fillStyle = 'blue';
                    cfg.strokeStyle = 'blue';
                }
                return cfg;
            };

        }

        // LINE SERIES
        if (series.type === 'line') {

            series.axis = 'right';

            series.style = {
                strokeStyle: '#7cb342',
                lineWidth: 2
            };

            series.marker = {
                radius: 4
            };

            series.label = {
                field: 'B',
                display: 'over',
                padding: 8,
                renderer: function(v){
                    return v + '%';
                }
            };

            series.renderer = function(sprite, cfg, rendererData, index)
            {
                var rec = rendererData.store.getAt(index);
                var val = rec.get('B');

                if (val >= 80) {
                    cfg.fillStyle = '#d9534f';
                    cfg.strokeStyle = '#d9534f';
                } else {
                    cfg.fillStyle = '#7cb342';
                    cfg.strokeStyle = '#7cb342';
                }

                return cfg;
            };

        }

    });
}

также добавил обработчик в ExtEvents

function chart.itemmousedown(chart, item, event, eOpts)
{
  chart.select_index = item.index;
  chart.redraw;
}

И вот при вызове chart.redraw; ничего не происходит

если же в легенде выключить серию и потом включить, то столбик выделяется, т.е. срабатывает series.renderer

 

 

Posted
1 hour ago, Sherzod said:

Этот пост может помочь:

 

я видел этот пост и у меня не получилось повторить, чтобы все работало

если рассматривать это событие, то здесь мне интересно только это, выделил жирным

function chart.boxready(sender, width, height, eOpts)
{
    this.series.items[0].addListener('itemmousedown', function(el) {
        var series = this.chart.series.get(0);
        series.highlight = true;
        series.unHighlightItem();
        series.cleanHighlights();
        series.highlightItem(el);
        series.highlight = false;

        var rec = MainForm.UniDBGrid1.getStore().findRecord('2', el.storeItem.data.LL);
        if (rec) {
            MainForm.UniDBGrid1.getSelectionModel().select(rec);
        };
    })
}

я преобразовал под свою задачу так, хотя можно сразу завязаться на событие function chart.itemmousedown(chart, item, event, eOpts)

function chart.boxready(sender, width, height, eOpts)
{         
  if (sender.series)
  {             
    Ext.each(sender.series, function(series, index)
    {
      series.addListener('itemmousedown', function(el) 
      {
        series.highlight = true;
        series.unHighlightItem();
        series.cleanHighlights();
        series.highlightItem(el);
        series.highlight = false;
      });
    }); 
  } 
}

но в любом случае этот код не работает, ругается 

series.unHighlightItem is not a function

series.cleanHighlights is not a function

series.highlightItem is not a function

Posted
On 3/21/2026 at 11:59 AM, AlexanderP said:

Sherzod получилось проверить ?

Пока безрезультатно.

Posted
On 3/21/2026 at 11:59 AM, AlexanderP said:

Sherzod получилось проверить ?

Решение:

1. 

function chart.beforeInit(sender, config) 
{
    config.innerPadding = {
        left: 4,
        right: 10,
        top: 40
    };

    config.axes = [{
        type: 'numeric',
        position: 'left',
        fields: ['A'],
        title: 'Count',
        grid: true
    }, {
        type: 'numeric',
        position: 'right',
        fields: ['B'],
        minimum: 0,
        maximum: 100,
        title: 'Percent',
        label: {
            renderer: function(v) {
                return v + '%';
            }
        }
    }, {
        type: 'category',
        position: 'bottom',
        fields: ['LL']
    }];

    Ext.Array.each(config.series || [], function(series) {

        // BAR SERIES
        if (series.type === 'bar') {

            series.label = {
                field: 'A',
                display: 'outside',
                orientation: 'horizontal',
                padding: 10,
                renderer: function(v) {
                    return Ext.util.Format.number(v, '0,000');
                }
            };

            series.renderer = function(sprite, cfg, rendererData, index) {
                var chart = sender;

                if (chart._selectedIndex !== undefined && chart._selectedIndex === index) {
                    cfg.fillStyle = '#ff9800'; // выбранный
                } else {
                    cfg.fillStyle = '#5fa2dd'; // обычный
                }

                return cfg;
            };

        }

        // LINE SERIES
        if (series.type === 'line') {

            series.axis = 'right';

            series.style = {
                strokeStyle: '#7cb342',
                lineWidth: 2
            };

            series.marker = {
                radius: 4
            };

            series.label = {
                field: 'B',
                display: 'over',
                padding: 8,
                renderer: function(v) {
                    return v + '%';
                }
            };

            series.renderer = function(sprite, cfg, rendererData, index) {
                var rec = rendererData.store.getAt(index);
                var val = rec.get('B');

                if (val >= 80) {
                    cfg.fillStyle = '#d9534f';
                    cfg.strokeStyle = '#d9534f';
                } else {
                    cfg.fillStyle = '#7cb342';
                    cfg.strokeStyle = '#7cb342';
                }

                return cfg;
            };

        }

    });
}

2. 

function chart.itemclick(chart, item, event, eOpts) 
{
    chart._selectedIndex = item.index;
    chart.getSeries().forEach(function(series) {
        series.getSprites().forEach(function(sprite) {
            sprite.setDirty(true);
        });
    });

    chart.redraw();
}

image.png.0bb14ed0be34e47c92b8632d27bd72c5.png

Posted
1 hour ago, Sherzod said:

Решение:

1. 

function chart.beforeInit(sender, config) 
{
    config.innerPadding = {
        left: 4,
        right: 10,
        top: 40
    };

    config.axes = [{
        type: 'numeric',
        position: 'left',
        fields: ['A'],
        title: 'Count',
        grid: true
    }, {
        type: 'numeric',
        position: 'right',
        fields: ['B'],
        minimum: 0,
        maximum: 100,
        title: 'Percent',
        label: {
            renderer: function(v) {
                return v + '%';
            }
        }
    }, {
        type: 'category',
        position: 'bottom',
        fields: ['LL']
    }];

    Ext.Array.each(config.series || [], function(series) {

        // BAR SERIES
        if (series.type === 'bar') {

            series.label = {
                field: 'A',
                display: 'outside',
                orientation: 'horizontal',
                padding: 10,
                renderer: function(v) {
                    return Ext.util.Format.number(v, '0,000');
                }
            };

            series.renderer = function(sprite, cfg, rendererData, index) {
                var chart = sender;

                if (chart._selectedIndex !== undefined && chart._selectedIndex === index) {
                    cfg.fillStyle = '#ff9800'; // выбранный
                } else {
                    cfg.fillStyle = '#5fa2dd'; // обычный
                }

                return cfg;
            };

        }

        // LINE SERIES
        if (series.type === 'line') {

            series.axis = 'right';

            series.style = {
                strokeStyle: '#7cb342',
                lineWidth: 2
            };

            series.marker = {
                radius: 4
            };

            series.label = {
                field: 'B',
                display: 'over',
                padding: 8,
                renderer: function(v) {
                    return v + '%';
                }
            };

            series.renderer = function(sprite, cfg, rendererData, index) {
                var rec = rendererData.store.getAt(index);
                var val = rec.get('B');

                if (val >= 80) {
                    cfg.fillStyle = '#d9534f';
                    cfg.strokeStyle = '#d9534f';
                } else {
                    cfg.fillStyle = '#7cb342';
                    cfg.strokeStyle = '#7cb342';
                }

                return cfg;
            };

        }

    });
}

2. 

function chart.itemclick(chart, item, event, eOpts) 
{
    chart._selectedIndex = item.index;
    chart.getSeries().forEach(function(series) {
        series.getSprites().forEach(function(sprite) {
            sprite.setDirty(true);
        });
    });

    chart.redraw();
}

image.png.0bb14ed0be34e47c92b8632d27bd72c5.png

 

Спасибо!

Отлично работает

 

 

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...