Buzzword样式的右键菜单 Customized Context Menu as Buzzword
从 The Joy of Flex 的博客上,看到了一则关于 Buzzword的视频介绍。Buzzword是Adobe官方的一个线上文档编辑器。功能强大。
看到Buzzword的右键菜单很是好看,决定山寨一次,模仿一下。
通过模仿,我们可以了解如何制作一个Flex部件,自己来定义它的形状。
先上个Buzzword的右键菜单的视频截图,和模仿后的成品的截图。
左边的是视频截图,右边的是作者模仿。
Buzzword的那个Context Menu严格意义上来说,不是真正的,flash浏览器默认的那个右键菜单(就是有查看flash版本号选项的那个)。作者分析,那个Buzzword的这个context menu,不是基于flash.ui.ContextMenu来开发的。而是基于类似Canvas或者List一类的部件来进行开发的。作者是基于VBox来进行开发的。
这个Context Menu的特点就是,当鼠标沿着这个不规则的Context Menu四边游走的时候,被其盖在下面的部件,都能紧贴着Context Menu的边而被激活。也就是说,这个Context Menu的背景, 不是用一个这个不规则形状的截图来实现的。如果是这个形状的截图作为Context Menu的背景,那么作者放于这个Context Menu下面的Link Button 部件,就不会在鼠标放到该位置时,变成Mouse Over的状态。因为,这个按钮理应被正方形的截图所遮挡(之所以大家能看到它,是因为除了黑色的主体部分外,那个截图的画布背景是透明的)。
当然,如果不要求有上述这个功能,用截图也是可以的。但是这个部件的高度就不能方便地随意控制。
此次模仿的原理就是,自己写VBox的BorderSkin类。步骤如下,
1. 建立一个VBox的Border类,扩展mx.skins.Border类。覆盖 updateDisplayList方法。实现自己的graphics实例,也就是这个部件的外形了。
- package com.chestnut.view
- {
- import flash.display.Graphics;
- import flash.filters.DropShadowFilter;
- import mx.skins.Border;
- public class MyBorder extends Border
- {
- public function MyBorder()
- {
- super();
- }
- //覆盖updateDisplayList, 画自己所需要的图形
- override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
- {
- var g:Graphics = graphics;
- drawBorder(unscaledWidth, unscaledHeight, g, -5);
- }
- //覆盖drawBorder,画自定义的边
- public static function drawBorder(w:Number, h:Number, g:Graphics, inset:Number):void
- {
- var xSign:Number = 1;
- var ySign:Number = 1;
- var xShift:Number = 0;
- var yShift:Number = 0;
- var padding:Number = 20;
- var upperLeftControlOffset:Number = 5;
- var controlOffset:Number = 5;
- g.clear();
- g.beginFill(0x000000, 1);
- g.lineStyle(1, 0x000000, 1);
- //draw the menu
- g.moveTo(xShift+xSign*upperLeftControlOffset, yShift+ySign*inset);
- //..此处省略,这里就是Graphics,画出那个不规则图形的方法。代码因图形形状的不同而异,因此省略
- g.endFill();
- }
- }
- }
package com.chestnut.view
{
import flash.display.Graphics;
import flash.filters.DropShadowFilter;
import mx.skins.Border;
public class MyBorder extends Border
{
public function MyBorder()
{
super();
}
//覆盖updateDisplayList, 画自己所需要的图形
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
var g:Graphics = graphics;
drawBorder(unscaledWidth, unscaledHeight, g, -5);
}
//覆盖drawBorder,画自定义的边
public static function drawBorder(w:Number, h:Number, g:Graphics, inset:Number):void
{
var xSign:Number = 1;
var ySign:Number = 1;
var xShift:Number = 0;
var yShift:Number = 0;
var padding:Number = 20;
var upperLeftControlOffset:Number = 5;
var controlOffset:Number = 5;
g.clear();
g.beginFill(0x000000, 1);
g.lineStyle(1, 0x000000, 1);
//draw the menu
g.moveTo(xShift+xSign*upperLeftControlOffset, yShift+ySign*inset);
//..此处省略,这里就是Graphics,画出那个不规则图形的方法。代码因图形形状的不同而异,因此省略
g.endFill();
}
}
}
2. 在CSS定义中,定义自己的borderSkin类。
- /* CSS file */
- .contextMenu{
- borderSkin: ClassReference("com.chestnut.view.MyBorder");
- }
/* CSS file */
.contextMenu{
borderSkin: ClassReference("com.chestnut.view.MyBorder");
}
3. 加入自己的 menu item 部件。
- private function onInit():void
- {
- menuArray = ["Open","Open in New Window","Seperator", "Share...", "Duplicate", "Rename", "Show Info", "Seperator", "Delete"];
- for each(var str:String in menuArray)
- {
- //当关键字是sperator时,就插入一个横线,vb就是VBox
- if(str == "Seperator")
- {
- var hr:HRule = new HRule();
- hr.width = 150;
- hr.setStyle("strokeColor", "#FFFFFF");
- hr.height = 1;
- vb.addChild(hr);
- }
- //其他时候,就插入自定义的menu item, 作者基于canvas来实现的
- else
- {
- var mi:MenuItem = new MenuItem();
- mi.menuStr = str;
- vb.addChild(mi);
- }
- }
- //加一个装饰阴影
- var sf:DropShadowFilter = new DropShadowFilter();
- sf.distance = 5;
- sf.alpha = 0.4;
- sf.angle = 45;
- vb.filters = [sf];
- var cm:ContextMenu = new ContextMenu();
- }
private function onInit():void
{
menuArray = ["Open","Open in New Window","Seperator", "Share...", "Duplicate", "Rename", "Show Info", "Seperator", "Delete"];
for each(var str:String in menuArray)
{
//当关键字是sperator时,就插入一个横线,vb就是VBox
if(str == "Seperator")
{
var hr:HRule = new HRule();
hr.width = 150;
hr.setStyle("strokeColor", "#FFFFFF");
hr.height = 1;
vb.addChild(hr);
}
//其他时候,就插入自定义的menu item, 作者基于canvas来实现的
else
{
var mi:MenuItem = new MenuItem();
mi.menuStr = str;
vb.addChild(mi);
}
}
//加一个装饰阴影
var sf:DropShadowFilter = new DropShadowFilter();
sf.distance = 5;
sf.alpha = 0.4;
sf.angle = 45;
vb.filters = [sf];
var cm:ContextMenu = new ContextMenu();
}