Buzzword样式的右键菜单 Customized Context Menu as Buzzword

The Joy of Flex 的博客上,看到了一则关于 Buzzword的视频介绍。Buzzword是Adobe官方的一个线上文档编辑器。功能强大。png-0532

看到Buzzword的右键菜单很是好看,决定山寨一次,模仿一下。

通过模仿,我们可以了解如何制作一个Flex部件,自己来定义它的形状。

先上个Buzzword的右键菜单的视频截图,和模仿后的成品的截图。

 

 

暴风截屏20081122164002  final

左边的是视频截图,右边的是作者模仿。

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();	
		}
	}
}

2. 在CSS定义中,定义自己的borderSkin类。

/* 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();
}

再说两句,是关于“山寨”文化的。现在中国的“山寨”文化盛行,好多人批评,中国人自己的创新能力都被“山寨”抹杀了。

作者,不反对“山寨”,但也不提倡“山寨”。这无非是个度的问题,过度和不足都不好。希望我们都能中性的看待“山寨”这个问题。师夷长技的时候,同时也要自省、创新。

Comments

vb和ContextMenu怎么联系起来呢

你好,我是flex初学者,你实现的右键菜单很炫呀, 可是看了你的代码,不太明白vb和ContextMenu怎么联系起来呢?var cm:ContextMenu = new ContextMenu(); 这句话后面还有代码吗?.contextMenu这个style class是用来修饰vb的吗?能把可以运行的代码都发给我看看吗?邮箱是tiao67@sohu.com, 谢谢啦!!

你好,能把你的这个例子发给我吗,谢谢! shangmw@1

你好,能把你的这个例子发给我吗,谢谢!
shangmw@163.com

漂亮!

漂亮!

谢谢

呵呵,看到你右边的那个广告了。在上海开张了没?

有些有意向的, 但预算太少. 所以特地明码实价, 呵呵

有些有意向的, 但预算太少. 所以特地明码实价, 呵呵