0

是否可以像下面的示例一样在 Flex中创建一个打包的气泡图?

打包气泡图示例

来源:http ://blog.tiger.com.pl/wp-content/uploads/2013/06/bubble2.jpg

我用谷歌搜索并没有找到任何东西。如果没有本地方法可以做到这一点,有人可以建议我自己如何绘制它吗?

4

1 回答 1

0

好吧,在搜索和搜索之后,我在这里找到了一个名为flare的库,您可以在Layout/Bubbles中看到我正在寻找的演示示例。但一切都是在 Actionscript 3 中完成的。然后我开始创建自己的类以在 Flex 中使用,我得到了它。这是我写的类的代码。

package classes
{
    import flare.animate.FunctionSequence;
    import flare.animate.Transition;
    import flare.animate.TransitionEvent;
    import flare.animate.Transitioner;
    import flare.display.TextSprite;
    import flare.query.methods.add;
    import flare.query.methods.div;
    import flare.query.methods.mul;
    import flare.util.Shapes;
    import flare.util.Strings;
    import flare.vis.Visualization;
    import flare.vis.controls.DragControl;
    import flare.vis.controls.ExpandControl;
    import flare.vis.controls.HoverControl;
    import flare.vis.controls.IControl;
    import flare.vis.controls.TooltipControl;
    import flare.vis.data.Data;
    import flare.vis.data.DataList;
    import flare.vis.data.DataSprite;
    import flare.vis.data.NodeSprite;
    import flare.vis.events.SelectionEvent;
    import flare.vis.events.TooltipEvent;
    import flare.vis.operator.OperatorSwitch;
    import flare.vis.operator.encoder.PropertyEncoder;
    import flare.vis.operator.label.Labeler;
    import flare.vis.operator.layout.CircleLayout;
    import flare.vis.operator.layout.CirclePackingLayout;
    import flare.vis.operator.layout.DendrogramLayout;
    import flare.vis.operator.layout.ForceDirectedLayout;
    import flare.vis.operator.layout.IcicleTreeLayout;
    import flare.vis.operator.layout.IndentedTreeLayout;
    import flare.vis.operator.layout.Layout;
    import flare.vis.operator.layout.NodeLinkTreeLayout;
    import flare.vis.operator.layout.RadialTreeLayout;

    import flash.display.DisplayObjectContainer;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.text.TextFormat;
    import flash.text.TextFormatAlign;

    import mx.core.Container;
    import mx.core.UIComponent;
    import mx.core.mx_internal;
    import mx.events.ResizeEvent;


    public class PackedBubblesChart extends UIComponent {
        public static const DEFAULT_FLEX_SERIES_COLORS:Array = [
            0xe48701, 0xa5bc4e, 0x1b95d9, 0xcaca9e,
            0x6693b0, 0xf05e27, 0x86d1e4, 0xe4f9a0,
            0xffd512, 0x75b000, 0x0662b0, 0xede8c6,
            0xcc3300, 0xd1dfe7, 0x52d4ca, 0xc5e05d,
            0xe7c174, 0xfff797, 0xc5f68f, 0xbdf1e6,
            0x9e987d, 0xeb988d, 0x91c9e5, 0x93dc4a,
            0xffb900, 0x9ebbcd, 0x009797, 0x0db2c2
        ];
        // Constructor
        public function PackedBubblesChart() {
            addEventListener(Event.ADDED_TO_STAGE, addedToStage);
            addEventListener(Event.REMOVED_FROM_STAGE, removedFromStage);
        }

        protected function addedToStage(event: Event) : void {          
            (this.parent as Container).addEventListener(ResizeEvent.RESIZE, resizeBubbleChart);
            tryRender();
        }

        protected function removedFromStage(event: Event) : void {          
            clearNodes();
            (this.parent as Container).removeEventListener(ResizeEvent.RESIZE, resizeBubbleChart);          
        }

        protected function clearNodes() : void {
            if(vis) {
                for each(var sprite : DataSprite in _nodesInformation.nodes) {                  
                    sprite.parent.removeChild(sprite);                  
                }
                vis = null;                 
            }
        }

        protected function resizeBubbleChart(event:ResizeEvent) : void {
            _bounds = new Rectangle(0, 0, parent.width, parent.height);
            tryRender();
        }

        private var _init:Boolean = false;
        private var _bounds:Rectangle;

        public var labelField : String = "label";
        public var valueField : String = "value";

        public function get bounds():Rectangle { return _bounds; }
        public function set bounds(b:Rectangle):void {
            _bounds = b;
            resize();
        }

        private var _dataProvider : Array = [];
        private var _nodesInformation : Data = new Data();
        private var _nodeDefaultFormat : Object = 
            {
                name: "Bubbles",
                op: new CirclePackingLayout(8, false, "depth"),
                nodes:{
                        shape: Shapes.CIRCLE,
                        fillColor: 0x11aaaaaa,
                        lineColor: 0xdddddddd,
                        lineWidth: 4,                               
                        alpha: 1,
                        visible: true               
                },
                edges: {alpha:0, visible:false},
                ctrl: new DragControl(NodeSprite),
                canStraighten: true
            }

        public function get dataProvider() : Array {
            return _dataProvider;
        }

        public function set dataProvider(info : Array) : void {
            /*
            if(vis && _dataProvider && _dataProvider.length > 0) {
                for each(var sprite : DataSprite in _nodesInformation.nodes) {                  
                    sprite.parent.removeChild(sprite);                  
                }
                vis = null;
            }
            */
            _dataProvider = info;
            tryRender();
        }

        protected function tryRender() : void {
            if(parent) _bounds = new Rectangle(0,0,parent.width, parent.height);
            if(_dataProvider && _dataProvider.length > 0 && _bounds) {
                clearNodes();
                _nodesInformation = createNodes(_dataProvider.length);
                _nodesInformation.nodes.setProperties(_nodeDefaultFormat.nodes);
                var index : uint = 0;
                for each(var item : Object in _dataProvider) {
                    var labelText : String = item[labelField];
                    var valueNumber : Number = item[valueField];
                    _nodesInformation.nodes[index].data.label = labelText;
                    _nodesInformation.nodes[index].buttonMode = true;
                    _nodesInformation.nodes[index].size = item[valueField];
                    _nodesInformation.nodes[index].props.value = valueNumber;
                    _nodesInformation.nodes[index].props.name =labelText;
                    _nodesInformation.nodes[index].props.name_value = labelText+"\n("+valueNumber+")";
                    _nodesInformation.nodes[index].fillColor =  0xff000000 + DEFAULT_FLEX_SERIES_COLORS[index % 28];
                    index++;
                }
                _nodesInformation.nodes.sortBy("props.value");

                // create the visualization
                vis = new Visualization(_nodesInformation);
                vis.bounds = bounds;
                vis.operators.add(_nodeDefaultFormat.op);
                vis.setOperator("nodes", new PropertyEncoder(_nodeDefaultFormat.nodes, "nodes"));                        
                vis.operators.add(new Labeler("props.name_value", Data.NODES,new TextFormat("Arial",12,0,true,null,null,null,null, TextFormatAlign.CENTER),null));
                vis.controls.add(new TooltipControl(DataSprite, null,
                    function(evt:TooltipEvent):void {
                        var d:DataSprite = evt.node;                    
                        TextSprite(evt.tooltip).htmlText = Strings.format(_tipText, d.props.name, d.props.value);
                    }
                ));
                init();
            }           
        }
        public static function createNodes(n:uint):Data {
            var g:Data = new Data();
            for (var i:uint=0; i < n; i++) {
                var node:NodeSprite = g.addNode();
                node.data.label = String(i);
            }
            return g;
        }

        public function set toolTipFormat(value : String) : void {
            _tipText = value;
        }
        private var _tipText:String = "<b>Label</b>: {0}<br/><b>Value</b>: {1}";

        private var vis:Visualization;
        private var os:OperatorSwitch;
        private var shape:String = null;

        public function init():void {           
            vis.controls.add(new HoverControl(NodeSprite,
                // by default, move highlighted items to front
                HoverControl.MOVE_AND_RETURN,
                // highlight node border on mouse over
                function(e:SelectionEvent):void {
                    e.node.lineWidth = 10;
                    e.node.lineColor = 0x88ff0000;
                },
                // remove highlight on mouse out
                function(e:SelectionEvent):void {
                    e.node.lineWidth = 4;
                    e.node.lineColor = _nodeDefaultFormat.nodes.lineColor;
                }));

            vis.controls.add(_nodeDefaultFormat.ctrl);
            vis.update();
            addChild(vis);
        }

        public function resize():void
        {
            if (vis) {
                vis.bounds = bounds;
                vis.update();
            }
        }

    }
}

这是一个在 flex 中使用它的应用示例

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                minWidth="955" minHeight="600" creationComplete="init(event)" layout="vertical"
                verticalAlign="middle">
    <mx:Script>
        <![CDATA[
            import classes.PackedBubblesChart;

            import mx.events.FlexEvent;
            import mx.events.ResizeEvent;
            protected var companies : Array = [];
            protected var otherCompanies : Array = [];

            protected var bubbleChart : PackedBubblesChart = new PackedBubblesChart();
            protected function init(event:FlexEvent):void {
                companies.push({company_name:"Sunray Management Group", count:92});
                companies.push({company_name:"Chevron", count:145});
                companies.push({company_name:"Nabors", count:35});
                companies.push({company_name:"Milicom", count:23});
                companies.push({company_name:"gNostos", count:200});
                companies.push({company_name:"Cisco", count:43});
                otherCompanies.push({company_name:"Chevron", count:145});
                otherCompanies.push({company_name:"Nabors", count:35});
                otherCompanies.push({company_name:"Milicom", count:23});
                otherCompanies.push({company_name:"gNostos", count:200});
                companies.push({company_name:"Sunray Management Group", count:92});
                companies.push({company_name:"Chevron", count:145});
                companies.push({company_name:"Nabors", count:35});
                companies.push({company_name:"Milicom", count:23});
                companies.push({company_name:"gNostos", count:200});
                companies.push({company_name:"Cisco", count:43});
                otherCompanies.push({company_name:"Chevron", count:145});
                otherCompanies.push({company_name:"Nabors", count:35});
                otherCompanies.push({company_name:"Milicom", count:23});
                otherCompanies.push({company_name:"gNostos", count:200});
                companies.push({company_name:"Sunray Management Group", count:92});
                companies.push({company_name:"Chevron", count:145});
                companies.push({company_name:"Nabors", count:35});
                companies.push({company_name:"Milicom", count:23});
                companies.push({company_name:"gNostos", count:200});
                companies.push({company_name:"Cisco", count:43});
                otherCompanies.push({company_name:"Chevron", count:145});
                otherCompanies.push({company_name:"Nabors", count:35});
                otherCompanies.push({company_name:"Milicom", count:23});
                otherCompanies.push({company_name:"gNostos", count:200});
                companies.push({company_name:"Sunray Management Group", count:92});
                companies.push({company_name:"Chevron", count:145});
                companies.push({company_name:"Nabors", count:35});
                companies.push({company_name:"Milicom", count:23});
                companies.push({company_name:"gNostos", count:200});
                companies.push({company_name:"Cisco", count:43});
                otherCompanies.push({company_name:"Chevron", count:145});
                otherCompanies.push({company_name:"Nabors", count:35});
                otherCompanies.push({company_name:"Milicom", count:23});
                otherCompanies.push({company_name:"gNostos", count:200});

                bubbleChart.labelField = "company_name";
                bubbleChart.valueField = "count";
                bubbleChart.toolTipFormat = "<b>Company</b>: {0}<br/><b>Count</b>: {1}";
                bubbleChart.dataProvider = companies;
                canvas.addChild(bubbleChart);
            }

            protected function button_clickHandler(event:MouseEvent):void {             
                if(bubbleChart.dataProvider == companies) bubbleChart.dataProvider  = otherCompanies;
                else bubbleChart.dataProvider  = companies;
            }

        ]]>
    </mx:Script>
    <mx:Canvas id="canvas" width="100%" height="100%">

    </mx:Canvas>
    <mx:Button label="New data provider" click="button_clickHandler(event)"/>

</mx:Application>

好吧,我回答我自己的问题,因为我认为它可能对其他人有用。对不起我的英语不好。

结果就是这样……啊,美人。感谢 Flare 人。

在此处输入图像描述

于 2014-10-09T16:03:45.623 回答