flex 中不使用flex
In our first article, we went over the basics of data visualization, created a data set, and generated a display showing occurrences of keywords in the SitePoint forums. In the second part, we replaced the output with a spring graph—the better to illustrate relationships between keywords—and also added some font scaling to show the relative popularity of each keyword. In our final installment, we’ll add a few more pieces of information to the display and refactor our application in accordance with best practices. The instructions will build upon the finished code from the second tutorial, but you might want to download the Flex Builder project archive containing all the finished code.
在我们的第一篇文章中,我们介绍了数据可视化的基础知识,创建了数据集,并生成了显示在SitePoint论坛中出现关键字的显示。 在第二部分中,我们用弹簧图替换了输出(更好地说明了关键字之间的关系),并且还添加了一些字体缩放比例以显示每个关键字的相对受欢迎程度。 在最后一部分中,我们将向显示屏添加更多信息,并根据最佳实践重构我们的应用程序。 这些说明将以第二篇教程中的完成代码为基础,但是您可能要下载包含所有完成代码的Flex Builder项目档案 。
Again this week we have an Article Quiz sponsored by Adobe to test what you learn in the tutorial. Be sure to check it out when you’re done here!
本周,我们再次提供了由Adobe赞助的文章测验 ,以测试您在本教程中学到的知识。 完成此操作后,请务必检查一下!
At the end of the second article we were left with a spring graph that looked like this:
在第二篇文章的结尾,我们留下了一个看起来像这样的弹簧图:
Figure 1. Initial graph
图1.初始图
This allows us to see direct relationships between keywords, and also see their relative popularity. It does leave a few things to be desired though. To start with, we’ve no way of seeing the actual occurrence counts of each keyword, and since we’re scaling the font size in fixed increments, there can be a considerable difference in counts between keywords that display at the same size.
这使我们可以查看关键字之间的直接关系,也可以查看它们的相对受欢迎程度。 它确实有一些需要改进的地方。 首先,我们无法查看每个关键字的实际出现次数,并且由于我们以固定的增量缩放字体大小,因此,显示相同大小的关键字之间的次数可能会有相当大的差异。
Adding more text to the graph will probably make it a little messy, and the exact occurrence count is more of a secondary piece of data that people will drill down to if they’re interested in gleaning more information. With this in mind, a good way to proceed is to add a tooltip—this way the user can mouse over any keyword they’re interested in and see the info they want, without it clogging up the graph unnecessarily.
在图形中添加更多文本可能会使它有些混乱,并且确切的出现次数更多是人们对收集更多信息感兴趣时将钻取的次要数据。 考虑到这一点,一种不错的方法是添加工具提示-用户可以将鼠标悬停在他们感兴趣的任何关键字上并查看所需的信息,而不会不必要地阻塞图表。
The easy way to do this is to add the count to the toolTip attribute on our item renderer. Let’s try doing this now:
执行此操作的简单方法是将计数添加到项目渲染器的toolTip属性中。 让我们现在尝试这样做:
Example 1. (excerpt)
范例1。 (摘抄)
<sg:SpringGraph id="mySpringGraph" backgroundColor="#FFFFFF" lineColor="#6666ff" repulsionFactor="5" right="10" left="10" bottom="10" top="10"> <sg:itemRenderer> <mx:Component> <mx:VBox cornerRadius="5" backgroundColor="0x444444" paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5" toolTip="{data.data}"> <mx:Label text="{data.id}" fontSize="10" color="0xFFFFFF" textAlign="center" /> </mx:VBox> </mx:Component> </sg:itemRenderer></sg:SpringGraph>If you look at the toolTip attribute that we added to the VBox in our inline item renderer component, we’re passing it the data key in our object. This might appear confusing: just remember that what’s being passed to the item renderer is always given the reference data in Flex, and it just so happens that our Item class has a property called data, which we’re using to store the keyword occurrence count. If our property in the Item class was called occurrence_count, the code would look like this:
如果您查看我们在嵌入式项目渲染器组件中添加到VBox的toolTip属性,则将其data键传递给对象中。 这可能会出现困惑:只要记住什么东西被传递到项目渲染器总是给出的基准data在Flex中,它只是恰巧,我们的Item类有一个数据属性,我们使用存储关键字发生次数这。 如果我们在Item类中的属性被称为activation_count ,则代码将如下所示:
toolTip="{data.occurrence_count}"Save the above code—and when you mouse over a keyword in the resulting spring graph, you should see a tooltip like this:
保存上面的代码,当您将鼠标悬停在结果弹簧图中的关键字上时,您将看到类似以下的工具提示:
Figure 2. Simple tooltips
图2.简单的工具提示
This works, and proves that we can push our information through to the tooltip, but is neither attractive nor particularly helpful. Ideally we want prettier interface, and one big enough to contain some extra text like “Mentioned in 12345 Threads.”
这行得通,并证明我们可以将信息推送到工具提示,但是既没有吸引力,也没有特别帮助。 理想情况下,我们需要更漂亮的界面,并且界面要大到足以包含一些额外的文本,例如“在12345线程中提及”。
Before we begin though, a note on best practice. In part II, we simply created our item renderer inline—it was easier and allowed us to explore the concept without a lot of code architecture getting in the way. However, in the real world, it’s much better to create an independent class for the item renderer. Doing so provides us with encapsulation and allows us to reuse the same tooltip in multiple places, should we wish to. In the context of this spring graph application, it may make little sense to you to separate these elements, especially if you lack experience working with larger projects. In the long run, however, I guarantee you’ll find life much easier if you follow these principles. Remember, when it’s a tiny demo application it seems like a lot of work, but once your codebase reaches several hundred thousand lines of code, it will be much simpler to debug, refactor, or modify any part of your application if you’ve followed this sort of best practice.
在开始之前,请先介绍一下最佳做法。 在第二部分中,我们简单地内联创建了项目渲染器-更为简单,它使我们能够探索概念,而无需过多的代码体系结构。 但是,在现实世界中,最好为项目渲染器创建一个独立的类。 这样做为我们提供了封装,并允许我们在需要的地方重复使用相同的工具提示。 在此Spring graph应用程序的上下文中,分离这些元素可能对您没有多大意义,尤其是如果您缺乏处理大型项目的经验时。 但是从长远来看,如果您遵循这些原则,我保证您会发现生活变得更加轻松。 请记住,当它是一个很小的演示应用程序时,似乎需要做很多工作,但是一旦您的代码库达到数十万行代码,如果您遵循以下说明,它将可以更轻松地调试,重构或修改应用程序的任何部分这种最佳做法。
The whys and wherefores of architectural best practice are beyond the scope of this article, so for now I’ll just lay out a simple way to structure the code. If you’re new to this, I highly recommend you do some reading on Flex architecture and design patterns, and perhaps look into some of the frameworks like Mate and Swiz.
体系结构最佳实践的原因和理由超出了本文的范围,因此,现在,我将仅提出一种简单的方法来构造代码。 如果您还不熟悉它,我强烈建议您阅读有关Flex体系结构和设计模式的文章,并可能研究诸如Mate和Swiz之类的一些框架。
In order to separate out our item renderer, we need to create a new class. In your src directory you should have a subdirectory named com. Inside com, create a directory named sitepoint, then inside that create another directory named itemrenderers. This method of laying out folders is sometimes called reverse domain notation, and is just a handy way of separating code from different projects. As long as the paths are correct, Flex is unconcerned with where our code lives—we’re creating subdirectories purely to make it easier to manage as the codebase grows or as you combine code from different projects into one. In our case, you can see we already have a directory—adobe—inside our com directory; this is where the Adobe JSON serialization classes live. Already you can see how sticking to this domain notation automatically protects us from any naming clashes and keeps it all nice and clean.
为了分离项目渲染器,我们需要创建一个新类。 在src目录中,应该有一个名为com的子目录。 在com内部,创建一个名为sitepoint的目录,然后在内部创建另一个名为itemrenderers目录。 这种布置文件夹的方法有时称为反向域表示法 ,它只是将代码与不同项目分开的一种便捷方法。 只要路径正确,Flex都不关心代码的存放位置-我们纯粹是在创建子目录,以便随着代码库的增长或将来自不同项目的代码组合到一个中而更易于管理。 在我们的例子中,您可以看到我们的com目录中已经有一个目录adobe 。 这是Adobe JSON序列化类的所在地。 您已经知道遵守此域符号会如何自动保护我们免受任何命名冲突的影响,并使它们保持整洁。
Now inside the Flex Navigator pane, right-click the itemrenderers folder and choose New, then MXML Component. Call it KeywordRenderer.mxml and base it off VBox. You should end up with a new file whose contents look like this:
现在,在Flex Navigator窗格内,右键单击itemrenderers文件夹,然后选择New ,然后选择MXML Component 。 将其KeywordRenderer.mxml并将其基于VBox。 您应该得到一个新文件,其内容如下所示:
Example 2. src/com/sitepoint/itemrenderers/KeywordRenderer.mxml (excerpt)
例子2. src/com/sitepoint/itemrenderers/KeywordRenderer.mxml (摘录)
<?xml version="1.0" encoding="utf-8"?><mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300"></mx:VBox>The code we need to complete the renderer is similar to the inline version we built in the last tutorial—the complete file should look like this:
完成渲染器所需的代码与我们在上一教程中构建的内联版本相似,完整的文件应如下所示:
Example 3. src/com/sitepoint/itemrenderers/KeywordRenderer.mxml
例子3. src/com/sitepoint/itemrenderers/KeywordRenderer.mxml
<?xml version="1.0" encoding="utf-8"?><mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" cornerRadius="5" borderThickness="1" borderStyle="solid" backgroundColor="0x444444" paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5"> <mx:Label text="{data.id}" fontSize="{parentDocument.getFontSize(data.data)}" color="0xFFFFFF" textAlign="center" /></mx:VBox>Now that this is complete, we go back to our main .mxml file and make a couple of changes. Remove the inline component—everything inside and including the <sg:itemRenderer> tags. It should end up looking like this:
现在已经完成了,我们回到我们的主要.mxml文件,进行一些更改。 删除内联组件—内部所有组件,包括<sg:itemRenderer>标记。 它应该最终看起来像这样:
Example 4. src/SitePoint_DataViz_Tutorial_Part3.mxml (excerpt)
例子4. src/SitePoint_DataViz_Tutorial_Part3.mxml (摘录)
<sg:SpringGraph id="mySpringGraph" backgroundColor="#FFFFFF" lineColor="#6666ff" repulsionFactor="5" right="10" left="10" bottom="10" top="10" />Note that I’ve removed the end tag and added a trailing slash to the start tag, because we no longer need to nest anything inside it. We’ll also need to move the font stepping code (which we wrote in Part II) of the series to inside the item renderer class. This will prevent us from having to use the parentDocument call to the font function. It’s always a good idea to keep your components from being dependent on the rest of your code, so they can be reused without modification.
请注意,我已经删除了结束标记,并在开始标记上添加了斜杠,因为我们不再需要在其中嵌套任何内容。 我们还需要将系列的字体步进代码(我们在第二部分中编写的代码)移动到项目渲染器类的内部。 这将避免我们不得不使用对字体函数的parentDocument调用。 始终使您的组件不依赖于代码的其余部分始终是一个好主意,因此可以在不进行修改的情况下重用它们。
As our font method relies on data calculated in the main application, we’ll need to pass it in as a series of parameters. We can just copy and paste the getFontSize method into our new item renderer, and then add declarations for the public variables like so:
由于我们的字体方法依赖于主应用程序中计算出的数据,因此我们需要将其作为一系列参数传递。 我们可以将getFontSize方法复制并粘贴到新的项目渲染器中,然后为公共变量添加声明,如下所示:
Example 5. src/com/sitepoint/itemrenderers/KeywordRenderer.mxml (excerpt)
例子5. src/com/sitepoint/itemrenderers/KeywordRenderer.mxml (摘录)
public var dataMin:Number;public var dataMax:Number;public var fontMin:Number;public var fontMax:Number;public var fontLift:Number;To allow us to set these parameters, we’ll need to assign the itemRenderer in our main application file. Let’s add that to the setup method, just before the line where we assign the dataProvider-:
为了允许我们设置这些参数,我们需要在主应用程序文件中分配itemRenderer 。 让我们将其添加到setup方法中,就在分配dataProvider-的行之前:
Example 6. src/SitePoint_DataViz_Tutorial_Part3.mxml (excerpt)
例子6. src/SitePoint_DataViz_Tutorial_Part3.mxml (摘录)
var factory:ClassFactory = new ClassFactory(KeywordRenderer)factory.properties = {fontMin:fontMin, fontMax:fontMax, fontLift:fontLift, dataMin:dataMin, dataMax:dataMax};mySpringGraph.itemRenderer = factory; mySpringGraph.dataProvider = myGraph;Here we’re creating a ClassFactory and setting the parameters we need in an array (factory.properties), then assigning the factory as the item renderer for our spring graph. We need to do this in our script, since we’re unable to set parameters if we simply assign it as an attribute in our MXML tag.
在这里,我们将创建一个ClassFactory并在数组( factory.properties )中设置所需的参数,然后将工厂分配为弹簧图的项目渲染器。 我们需要在脚本中执行此操作,因为如果仅在MXML标签中将其分配为属性,则无法设置参数。
Your final KeywordRenderer.mxml should look like this:
您最终的KeywordRenderer.mxml应该如下所示:
Example 7. src/com/sitepoint/itemrenderers/KeywordRenderer.mxml (excerpt)
例子7. src/com/sitepoint/itemrenderers/KeywordRenderer.mxml (摘录)
<?xml version="1.0" encoding="utf-8"?><mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" cornerRadius="5" borderThickness="1" borderStyle="solid" backgroundColor="0x444444" paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5" buttonMode="true" mouseChildren="false" useHandCursor="true" click="this.searchForums()" toolTip=" " toolTipCreate="createCustomToolTip('Mentioned in '+formatter.format(data.data)+' threads', event)"> <mx:Script> <![CDATA[ import mx.events.ToolTipEvent; import com.sitepoint.tooltips.KeywordToolTip; private var sitePointSearchURL:String = "https://www.sitepoint.com/forums/search.php?q="; public var dataMin:Number; public var dataMax:Number; public var fontMin:Number; public var fontMax:Number; public var fontLift:Number; private function createCustomToolTip(title:String, event:ToolTipEvent) : void { var ktt:KeywordToolTip = new KeywordToolTip(); ktt.message = title; event.toolTip = ktt; } private function getFontSize(data:Number) : Number { var fontSize:Number = (data - dataMin) / fontLift; if (fontSize < fontMin) { return fontMin; } else if (fontSize > fontMax) { return fontMax; } else { return fontSize; } } private function searchForums() : void { navigateToURL(new URLRequest(sitePointSearchURL+data.id), "_self"); } ]]> </mx:Script> <mx:NumberFormatter id="formatter" /> <mx:Label text="{data.id}" fontSize="{getFontSize(data.data)}" color="0xFFFFFF" textAlign="center" /></mx:VBox>If you compile and reload your application, nothing will have changed … perfect! That’s exactly what you want! When refactoring, the goal is to keep the behavior of the application the same, while providing the warm fuzzy feeling of knowing you’ve architected your code properly for the future.
如果编译并重新加载您的应用程序,那么什么都不会改变……完美! 那正是您想要的! 重构时,目标是保持应用程序的行为不变,同时提供一种温暖的模糊感,让您知道自己已经为将来正确地构建了代码。
note: Performance Considerations 注意:性能注意事项When creating custom item renderers (especially for components like data grids) you need to take performance into account. For our simple purposes, the above item renderer is perfectly sufficient. If, however, you’re creating a renderer for a heavy data grid, for example, you’d be better off creating a pure ActionScript item renderer. This has no reliance on a container, as elements like Canvas and VBox can take a toll on performance when dozens or hundreds are created in rendering a grid.
在创建自定义项目渲染器时(尤其是对于数据网格之类的组件),您需要考虑性能。 为了我们的简单目的,上面的项目渲染器就足够了。 但是,如果要为繁重的数据网格创建渲染器,则最好创建一个纯ActionScript项目渲染器。 这不依赖于容器,因为在渲染网格时创建数十个或数百个时,诸如Canvas和VBox类的元素会影响性能。
翻译自: https://www.sitepoint.com/flex-data-visualization-part-3/
flex 中不使用flex