jjzjj

javascript - ExtJS - 堆积条形图条件着色

coder 2025-01-04 原文

EXTJS 4 - 我正在尝试为 StackedBarChart 中的“系列”自定义渲染器函数。我想有条件地为条形图着色。

renderer: function(sprite, record, curAttr, index, store) {
                        return Ext.apply(curAttr, {
                              fill: color
                        });
                        return curAttr;
},

我的问题是,如何找出它当前呈现的是哪个元素。我想为我的数据存储/系列中每条记录的第一个元素赋予白色。

谢谢。

最佳答案

我找到了一种方法来准确检测当前正在渲染的元素。首先,您需要以下覆盖,它解决了 renderer parameters 的几个问题.它应该不会影响正常的条形图,但我没有测试过。

Ext.override(Ext.chart.series.Bar,{
    drawSeries: function() {
        var me = this,
            chart = me.chart,
            store = chart.getChartStore(),
            surface = chart.surface,
            animate = chart.animate,
            stacked = me.stacked,
            column = me.column,
            enableShadows = chart.shadow,
            shadowGroups = me.shadowGroups,
            shadowGroupsLn = shadowGroups.length,
            group = me.group,
            seriesStyle = me.seriesStyle,
            items, ln, i, j, baseAttrs, sprite, rendererAttributes, shadowIndex, shadowGroup,
            bounds, endSeriesStyle, barAttr, attrs, anim;

        // ---- start edit ----
        var currentCol, currentStoreIndex;
        // ---- end edit ----


        if (!store || !store.getCount()) {
            return;
        }

        //fill colors are taken from the colors array.
        delete seriesStyle.fill;
        endSeriesStyle = Ext.apply(seriesStyle, this.style);
        me.unHighlightItem();
        me.cleanHighlights();

        me.getPaths();
        bounds = me.bounds;
        items = me.items;

        baseAttrs = column ? {
            y: bounds.zero,
            height: 0
        } : {
            x: bounds.zero,
            width: 0
        };
        ln = items.length;
        // Create new or reuse sprites and animate/display
        for (i = 0; i < ln; i++) {
            sprite = group.getAt(i);
            barAttr = items[i].attr;

            if (enableShadows) {
                items[i].shadows = me.renderShadows(i, barAttr, baseAttrs, bounds);
            }

            // ---- start edit ----
            if (stacked && items[i].storeItem.index != currentStoreIndex) {
              //console.log("i: %o, barsLen: %o, j: %o, items[i]: %o",i,bounds.barsLen,i / bounds.barsLen,items[i]);
              currentStoreIndex = items[i].storeItem.index;
              currentCol = 0;
            }
            else {
              ++currentCol;
            }
            // ---- end edit ----

            // Create a new sprite if needed (no height)
            if (!sprite) {
                attrs = Ext.apply({}, baseAttrs, barAttr);
                attrs = Ext.apply(attrs, endSeriesStyle || {});
                sprite = surface.add(Ext.apply({}, {
                    type: 'rect',
                    group: group
                }, attrs));
            }
            if (animate) {
                // ---- start edit ----
                rendererAttributes = me.renderer(sprite, items[i].storeItem, barAttr, (stacked? currentStoreIndex : i), store, (stacked? currentCol : undefined));
                // ---- end edit ----
                sprite._to = rendererAttributes;
                anim = me.onAnimate(sprite, { to: Ext.apply(rendererAttributes, endSeriesStyle) });
                if (enableShadows && stacked && (i % bounds.barsLen === 0)) {
                    j = i / bounds.barsLen;
                    for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
                        anim.on('afteranimate', function() {
                            this.show(true);
                        }, shadowGroups[shadowIndex].getAt(j));
                    }
                }
            }
            else {
                // ---- start edit ----
                rendererAttributes = me.renderer(sprite, items[i].storeItem, Ext.apply(barAttr, { hidden: false }), (stacked? currentStoreIndex : i), store, (stacked? currentCol : undefined));
                // ---- end edit ----
                sprite.setAttributes(Ext.apply(rendererAttributes, endSeriesStyle), true);
            }
            items[i].sprite = sprite;
        }

        // Hide unused sprites
        ln = group.getCount();
        for (j = i; j < ln; j++) {
            group.getAt(j).hide(true);
        }
        // Hide unused shadows
        if (enableShadows) {
            for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
                shadowGroup = shadowGroups[shadowIndex];
                ln = shadowGroup.getCount();
                for (j = i; j < ln; j++) {
                    shadowGroup.getAt(j).hide(true);
                }
            }
        }
        me.renderLabels();
    }
});

这是 renderer() 的更改列表:

  • 第二个参数现在映射到正确的商店项目
  • 第四个参数现在是商店索引号而不是内部商品编号(否则在 IMO 中毫无值(value))
  • 添加了第六个参数,用于告知记录中的当前段索引,不计算记录中不属于轴的其他属性。
    示例:对于看起来像 {name: 'metric': segment1: 12, segment2: 22} 的记录,segment1 的索引将为 0 而不是 1,因为记录中的第一项不属于它的轴(它是类别名称)

因此,为了回答您的问题,现在您可以像这样使用渲染器:

renderer: function(sprite, record, attr, storeIndex, store, col) {
    // set the color to white for the first item in every record
    return (col == 0)? Ext.apply(attr, { fill: '#fff' }) : attr;
}

如果你想为一个命名项设置颜色,你也可以这样做:

// let's say that every record looks like this:
// {name: 'metric one', user1: 23, user2: 50, user3: 10}

renderer: function(sprite, record, attr, storeIndex, store, col) {
    // retrieve the segment property name from the record using its numeric index.
    // remember that 'col' doesn't take into account other fields that don't
    // belong to the axis, so in this case we have to add 1 to the index
    var uid = Ext.Object.getAt(record.data, col+1)[0];

    // set the color to red for 'user2'
    return (uid == 'user2')? Ext.apply(attr, { fill: '#f00' }) : attr;
}

对于最后一个,您将需要此函数,它允许您使用数字索引从对象中检索属性:

/**
 * Returns the key and its value at the idx position
 * @return {Array} Array containing [key, value] or null
 */
Ext.Object.getAt = function(obj, idx) {
    var keys = Ext.Object.getKeys(obj);
    if (idx < keys.length) {
        return [keys[idx],obj[keys[idx]]];
    }
    return null;
}

关于javascript - ExtJS - 堆积条形图条件着色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5822456/

有关javascript - ExtJS - 堆积条形图条件着色的更多相关文章

  1. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  2. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  3. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  4. ruby-on-rails - 使用包含多个关联和单独的条件 - 2

    我的Gallery模型中有以下查询:media_items.includes(:photo,:video).rank(:position_in_gallery)我的图库模型有_许多媒体项,每个都有一个照片或视频关联。到目前为止,一切正常。它返回所有media_items包括它们的photo或video关联,由media_item的position_in_gallery属性排序。但是我现在需要将此查询返回的照片限制为仅具有is_processing属性的照片,即nil。是否可以进行相同的查询,但条件是返回的照片等同于:.where(photo:'photo.is_processingIS

  5. ruby-on-rails - 在 haml View 中重构条件 - 2

    除了可访问性标准不鼓励使用这一事实指向当前页面的链接,我应该怎么做重构以下View代码?#navigation%ul.tabbed-ifcurrent_page?(new_profile_path)%li{:class=>"current_page_item"}=link_tot("new_profile"),new_profile_path-else%li=link_tot("new_profile"),new_profile_path-ifcurrent_page?(profiles_path)%li{:class=>"current_page_item"}=link_tot("p

  6. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  7. ruby-on-rails - 在具有 ActiveRecord 条件的相关模型中按字段排序 - 2

    我正在尝试按Rails相关模型中的字段进行排序。我研究的所有解决方案都没有解决如果相关模型被另一个参数过滤?元素模型classItem相关模型:classPriority我正在使用where子句检索项目:@items=Item.where('company_id=?andapproved=?',@company.id,true).all我需要按相关表格中的“位置”列进行排序。问题在于,在优先级模型中,一个项目可能会被多家公司列出。因此,这些职位取决于他们拥有的company_id。当我显示项目时,它是针对一个公司的,按公司内的职位排序。完成此任务的正确方法是什么?感谢您的帮助。PS-我

  8. ruby - 如果满足给定条件,则结束 ruby​​ 程序 - 2

    基本上,我只是试图在满足特定条件时停止程序运行其余行。unlessraw_information.firstputs"Noresultswerereturnedforthatquery"breakend然而,在程序运行之前我得到了这个错误:Invalidbreakcompileerror(SyntaxError)执行此操作的正确方法是什么? 最佳答案 abort("Noresultswerereturnedforthatquery")unlesscondition或unlessconditionabort("Noresultswer

  9. ruby-on-rails - 如果条件与 &&,是否有任何性能提升 - 2

    如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:

  10. ruby - 与条件正则表达式作斗争 - 2

    我有一个简单的问题,但我无法解决这个问题。我的字符串格式为ID:dddd,具有以下正则表达式:/^ID:([a-z0-9]*)$/或者如下:ID:1234Status:232,所以用下面的正则表达式:/^ID:([a-z0-9]*)Status:([a-z0-9]*)$/现在我想制作一个可以处理两者的正则表达式。我想到的第一件事是:/^ID:([a-z0-9]*)$|^ID:([a-z0-9]*)Status:([a-z0-9]*)$/它匹配,但我正在研究条件正则表达式,并认为应该可以按照(伪代码)ifthestringcontains/Status://^ID:([a-z0-9]*)

随机推荐