正圆
套圆
半圆
as3.as代码
代码是改自wp的flash,并不是自己完全写的.所以关键算法并不是我写的.
栯圆的实现是在某一边旋转时进行压缩而成的,并不是实际意义上的计算出来;
本来后期是能自适应边框,如长方形就是栯圆,正方形就是圆.因为没有时间,就不改了.临时改来用用.ie中的自适应有问题,所以也修正.
现在as不依赖flash的五台的东西,完全是as代码画出来,设置的.所以,直接加载这个as就可以使用了,不需要在上面画什么东西.
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.Stage;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.display.LoaderInfo;
import flash.events.Event;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.events.MouseEvent;
import flash.net.navigateToURL;
[SWF(backgroundColor="#ffffff", frameRate="0", width="500", height="500")] //设置舞台信息,注意下面有些地方使用到舞台大小,修改时,需要同时修改var的值
public class as3 extends MovieClip {
// private vars
private var radius:Number = 0;//半径
private var mcList:Array;
private var dtr:Number = Math.PI/180;//1夹角=π/180弧度;
private var sina:Number;
private var cosa:Number;
private var sinb:Number;
private var cosb:Number;
private var sinc:Number;
private var cosc:Number;
private var originx:Number;
private var originy:Number;
private var colorBarA:Number;
private var colorBarB:Number;
private var swfBgColor:Number;
private var hoverColor:Number;
private var rollForce:Number;
private var lasta:Number;
private var lastb:Number;
private var holder:MovieClip;
private var active:Boolean;
private var bgTf:TextField = null;
private var debug:Boolean;
private var stageDefWidth:Number;//舞台原始大小
private var stageDefHeight:Number;//舞台原始大小
public function as3(){
stop();
var swfStage:Stage = this.stage;
stdOut.setStage(swfStage);//实例化浏览器提示
swfStage.scaleMode = StageScaleMode.NO_SCALE;
swfStage.align = StageAlign.TOP_LEFT;
addEventListener(Event.ENTER_FRAME, stageTest);//ie某种情况下获取stage大小有问题
}
private function stageTest(e:Event) {
if (stage && stage.stageWidth) {//成功获取stage大小后才开始
removeEventListener(Event.ENTER_FRAME,stageTest,false);
stageDefWidth = this.stage.stageWidth;
stageDefHeight = this.stage.stageHeight;
toDo();
}
}
private function toDo() {//开始处理
var tags = demoXmlHtml.cfg();
if (!/^\s*<[\s\S]+>\s*$/.test(this.loaderInfo.parameters.xmlHtml)) {//未设置配置,使用演示并提醒
demoXmlHtml.xmlTip();
} else tags = this.loaderInfo.parameters.xmlHtml;
try {
var xmlHtml:XML = new XML(tags);
} catch (e) {
stdOut.t ('加xmlHtml参数的值到XML容器时出错(一般是格式不符合xml规则):' + e + '\n\n 获取到的xmlHtml内容(请把获取到的xmlHtml值保存成xxx.xml使用浏览器打开即可了解错误原因)\n\n\n' + tags, this);
return;
}
init( xmlHtml );
}
private function init( o:XML ):void {//解析配置成功
swfBgColor = getNum(cssColor2As(o['@swfBgColor']), 0xffffff, 0x000000, 0xffffff);
colorBarA = getNum(cssColor2As(o['@colorBarA']), 0x000000, 0x000000, 0xffffff);
colorBarB = getNum(cssColor2As(o['@colorBarB']), 0xffffff, 0x000000, 0xffffff);
debug = Boolean(getNum(o['@debug'], 0, null, null));
rollForce = getNum(o['@rollForce'], 1, 1, null);
var defaultFontSize = 12;
mcList = [];
active = false;
lasta = 1;
lastb = 1;
holder = new MovieClip();//创建一个标签容器
addChild(holder);
if (!getNum(o['@swfBgColorTransparent'], 1, null, null)) {//需要设置背景时,使用textfield当背景色;swf设置透明时不使用
bgTf = new TextField();
bgTf.x = bgTf.y = 0;
bgTf.width = stageDefWidth;
bgTf.height = stageDefHeight;
bgTf.background = true;
bgTf.backgroundColor = swfBgColor;
this.cacheAsBitmap = true;
this.opaqueBackground = swfBgColor;
addChildAt(bgTf, 0);//加入到底层
}
var links = o.children();
var mcI = 0;
var largeWH = 0;//最大tag值
for each( var node:XML in links ){
if (node.name().toString().toLowerCase() != 'a') continue;//只允许a标签
var fs:Number = getFontSize( node["@style"], defaultFontSize);
var percC:Number = (++mcI) / links.length();//字色:字号处于大小间转化成色条滑点
var percHC:Number = 1 - percC;//hover字色,字号处于大小间转化成色条滑点,但是跟字色相反
var col:Number = getColor( node["@style"], 'color', getColorFromGradient( percC ));
var hoverCl:Number = getColor( node["@style"], 'border\\-color', getColorFromGradient( percHC ));
var mc:Tag = new Tag( node, col, hoverCl, fs, debug);
holder.addChild(mc);
mcList.push( mc );
radius = Math.max(Math.sqrt(mc.height*mc.height + mc.width *mc.width), radius);//选择最长半径,过长方形4点球半径 = 根号(长/2的平方+宽/2的平方)
//stdOut.t(mc.height,mc.width,radius);//打印计算过程
}
positionAll();
addEventListener(Event.ENTER_FRAME, updateTags);
stage.addEventListener(Event.MOUSE_LEAVE, mouseExitHandler);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
stage.addEventListener(Event.RESIZE, resizeHandler);
resizeHolder();
}
private function positionAll():void {//计算每个tag球面坐标
var phi:Number = 0;
var theta:Number = 0;
var max:Number = mcList.length;
mcList.sort( function(){ return Math.random()<0.5 ? 1 : -1; } );//打乱
//分布
for( var i:Number=1; i<max+1; i++){//p点球坐标转直角坐标 http://baike.baidu.com/view/84791.htm
phi = Math.acos(-1+(2*i - 1)/max);//点过原点与Z的夹角, -1+为了让tag分布在前后半球, -1防止=pi; 0<= phi <2 pi
theta = Math.sqrt(max*Math.PI)*phi;//点过原点与x的夹角 0<= theta <=pi
// Coordinate conversion
mcList[i-1].cx = radius * Math.cos(theta)*Math.sin(phi);
mcList[i-1].cy = radius * Math.sin(theta)*Math.sin(phi);
mcList[i-1].cz = radius * Math.cos(phi);
//stdOut.t(phi,theta,mcList[i-1].cx,mcList[i-1].cy,mcList[i-1].cz);//显示tag相关参数,角度是慢慢变小
}
}
private function updateTags( e:Event ):void {//定时刷新
var a:Number;
var b:Number;
if( active ){//动力臂
a = (-Math.min( Math.max( holder.mouseY, - stage.stageHeight/2 ), stage.stageHeight/2 ) / radius ) * rollForce;
b = (Math.min( Math.max( holder.mouseX, - stage.stageWidth/2 ), stage.stageWidth/2 ) / radius ) * rollForce;
} else {
a = lasta * 0.98;
b = lastb * 0.98;
}
lasta = a;
lastb = b;
var count = mcList.length;
// if a and b under threshold, skip motion calculations to free up the processor
if( Math.abs(a) > 0.01 || Math.abs(b) > 0.01 ){
sineCosine( a, b, a*b );//a左右移动力,b上下力,c是旋转力
// bewegen van de punten
for( var j:Number=0; j<mcList.length; j++ ) {//变换球面位移坐标,上移->右移->前移
// multiply positions by a x-rotation matrix,左右动
var rx1:Number = mcList[j].cx;
var ry1:Number = mcList[j].cy * cosa + mcList[j].cz * -sina;
var rz1:Number = mcList[j].cy * sina + mcList[j].cz * cosa;
// multiply new positions by a y-rotation matrix 上下动
var rx2:Number = rx1 * cosb + rz1 * sinb;
var ry2:Number = ry1;
var rz2:Number = rx1 * - sinb + rz1 * cosb;
// multiply new positions by a z-rotation matrix 绕z转
var rx3:Number = rx2 * cosc + ry2 * -sinc;
var ry3:Number = rx2 * sinc + ry2 * cosc;
var rz3:Number = rz2;
// set arrays to new positions
mcList[j].cx = rx3;
mcList[j].cy = ry3;
mcList[j].cz = rz3;
// add perspective
var per:Number = rz3*(stage.stageWidth +radius)/radius/(count+j);//景深跟z有关系,缩小关系与景深比,起大,容量起大
// setmc position, scale, alpha
mcList[j].scaleX = mcList[j].scaleY = per;//前层tag比后层大,缩放比xy移动不成正比,有效拉开之间空间
mcList[j].x = rx3 * per - mcList[j].width /2;//计算时是按0点计算,需要把textfield居中显示
mcList[j].y = ry3 * per - mcList[j].height/2;
mcList[j].alpha = per * (j)/count;
}
depthSort();
}
}
private function depthSort():void {//设置景深,立体效果
if (!mcList.length) return;
mcList.sortOn( "cz", Array.DESCENDING | Array.NUMERIC );//按景深排
var current:Number = 0;
for( var i:Number=0; i<mcList.length; i++ ){//重新调整tag到对应的层中
holder.setChildIndex( mcList[i], i );
if( mcList[i].active == true ){
current = i;
}
}
holder.setChildIndex( mcList[current], mcList.length-1 );//hover中的调整到最前
}
private function resizeHolder():void {//swf容器发生大小变化
var s:Stage = this.stage;
holder.x = s.stageWidth/2;//球居中放置
holder.y = s.stageHeight/2;
//调整球到容器新大小,对比初始化时的大小(stageDefWidth)来倍比
//holder.scaleX = holder.scaleY = Math.min(s.stageWidth / stageDefWidth, s.stageHeight / stageDefHeight);
if (bgTf) {//调整背景到swf容器大小
bgTf.width = this.stage.stageWidth;
bgTf.height = this.stage.stageHeight;
}
}
private function sineCosine( a:Number, b:Number, c:Number ):void {
sina = Math.sin(a * dtr);
cosa = Math.cos(a * dtr);
sinb = Math.sin(b * dtr);
cosb = Math.cos(b * dtr);
sinc = Math.sin(c * dtr);
cosc = Math.cos(c * dtr);
}
private function cssColor2As(str:String) {
return str.toString().replace('#', '0x');
}
private function getFontSize(str:String, defaultSize:Number):Number {
if (!str) return defaultSize;
str = ' ' + str + ' ';
var m = str.match(/[^\-\w]font\-size\s*\:\s*(\d+)[^\W]/i);
if (m) {
return Number(m[1]);
} else return defaultSize;
}
private function getNum (obj, defaultNum, minNum, maxNum):Number {
if (isNaN(defaultNum)) defaultNum = 0;
if ( /^\s*$/.test(obj) || (undefined == obj) || (null == obj) || isNaN(obj) ) return defaultNum;
obj = Number(obj);
if (isNaN(obj)) return defaultNum;
if ((minNum is Number) && (obj < minNum)) return minNum;
if ((maxNum is Number) && (obj > maxNum)) return maxNum;
return obj;
}
private function getColor(str:String, what:String /* 包含有特殊字符时需要传入前二个\\转义 如 border-color :border\\-color */, defCl:Number):Number {
if (!str) return defCl;
str = ' ' + str + ' ';
var re = new RegExp("[^\\-\\w]" + what + "\\s*\\:\\s*#([a-z0-9]{6})[^\\-\\w]", "i");
var m = str.match(re);
if (m) {
m = Number('0x' + m[1]);
return (m > 0xffffff) || (m < 0x000000) ? defCl : m;
} else return defCl;
}
private function mouseExitHandler( e:Event ):void { active = false; }
private function mouseMoveHandler( e:MouseEvent ):void { active = true; }
private function resizeHandler( e:Event ):void { resizeHolder(); }
private function getColorFromGradient( perc:Number ):Number {//色阶,利用perc做滑块取colorBarA到colorBarB二色中间色点值,perc应该为0->1
//3 << 4 == 3 * 2的4次方 = 48, 17 >> 3 == 17 /2的3次方 = 2 (小数直接去掉,即0x123456 >> 16 = 0x12(后面的4位去掉),其它移位相同,左移相当补0
var r:Number = ( perc * ( colorBarA >> 16 ) ) + ( (1-perc) * ( colorBarB >> 16 ) );//新色为0.x A点的R色+B点1-0.X色,下g/b相同,最后混色,为什么混色会这样不懂
var g:Number = ( perc * ( (colorBarA >> 8) % 256 ) ) + ( (1-perc) * ( (colorBarB >> 8) % 256 ) );
var b:Number = ( perc * ( colorBarA % 256 ) ) + ( (1-perc) * ( colorBarB % 256 ) );
var rgb = ( (r << 16) | (g << 8) | b );//== r*5536+g*256+b变成0xffffff进制
return rgb == swfBgColor ? rgb + 0xf : rgb;//防止取到背景色,不预防超过
}
}
}
/*
* 标签云类
*/
import flash.text.TextField;
import flash.events.Event;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.events.MouseEvent;
import flash.external.ExternalInterface;
import flash.display.DisplayObject;
internal class Tag extends TextField {
private var _node:XML;
private var _cx:Number;
private var _cy:Number;
private var _cz:Number;
private var _color:Number;
private var _hoverColor:Number;
private var _active:Boolean;
private var javascript:String = null;
private var _debug:Boolean = false;
public function Tag( node:XML, color:Number, hoverColor:Number, fontSize:Number, debug:Boolean){
super();
_debug = debug;
_node = node;
_color = color;
_hoverColor = hoverColor;
_active = false;
this.autoSize = TextFieldAutoSize.LEFT;
this.selectable = false;
this.textColor = color;
var format:TextFormat = new TextFormat();
format.bold = 0;
format.size = fontSize;
this.setTextFormat(format);
splitHref(node['@href']);
this.addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
this.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
this.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
private function splitHref (href:String) {
var href = href.replace(/^\s+|\s+$/g, '');
var a = '<a href="#1" target="_self">';
if ( ('' == href) || (0 == href.indexOf('#')) ) {//无链接|.
} else if (0 == href.indexOf('javascript:')) {//js
javascript = href.substr(11);
} else {//link
a = '<a href="' + href + '" target="' + (_node['@target'].toString() == '' ? '_self' : _node['@target']) + '" >';
}
this.htmlText = a + _node + '</a>';
}
private function mouseOverHandler( e:MouseEvent ):void {
this.textColor = _hoverColor;
_active = true;
}
private function mouseOutHandler( e:MouseEvent ):void {
this.textColor = _color;
_active = false;
}
private function mouseUpHandler( e:MouseEvent ):void {
if (javascript) {//回调js
if (ExternalInterface.available) {
try {
var re = ExternalInterface.call('(function(str){str = unescape(str); try{window.eval(str);} catch(e) {' + (_debug ? 'alert("swf运行js代码" + str + "出错" + e)' : '') + ';}; return 1024;})', escape(javascript));
if (_debug && (re != 1024)) {
stdOut.t('运行js代码' + javascript + '失败: ');
}
} catch (e) {
_debug && stdOut.t('运行js代码出错: ' + e);
}
} else {
_debug && stdOut.t('无法运行js代码,swf的ExternalInterface.available关闭');
}
}
}
public function set cx( n:Number ){ _cx = n }
public function get cx():Number { return _cx; }
public function set cy( n:Number ){ _cy = n }
public function get cy():Number { return _cy; }
public function set cz( n:Number ){ _cz = n }
public function get cz():Number { return _cz; }
public function get active():Boolean { return _active; }
}
/*
* 出错提示类,
*/
internal class stdOut {
private static var _stage:Object;
public static function setStage(thisStage:Object) {//使用前需要首次传入舞台对象
_stage = thisStage;
}
static function t(...txt:Array){//实现trace功能调用方式 stdOut.t(参数,参数....,参数)
if (!_stage || !txt.length) return;
var str = [];
for (var i = 0; i < txt.length; i++) str[str.length] = txt[i].toString();
var tf = new TextField();
tf.doubleClickEnabled = true;
tf.background = true;
tf.height = 100;
tf.width = 300;
tf.multiline = true;
tf.wordWrap = true;
tf.mouseWheelEnabled = true;
tf.backgroundColor = 0x000000;
tf.textColor = 0xff0000;
tf.text = '==双击关闭/中轮滚屏==\n\n' + str.join('\n');
tf.addEventListener(MouseEvent.DOUBLE_CLICK, function(e:Event){
_stage.removeChild(tf);
});
_stage.addChild(tf);
}
}
/*
* 配置
*/
internal class demoXmlHtml{
public static function cfg():String {//演示配置
var xml = '<?xml version=\"1.0\" encoding=\"utf-8\"?>'
+ '<tags swfBgColor=\"#9e9e9e\" colorBarA=\"#00ff00\" colorBarB=\"#0000ff\" rollForce=\"0.5\" swfBgColorTransparent=\"0\" debug=\"0\" >';
var dot = '';
for (var i = 0; i < 10; i++) {
dot += '*';
xml += '<a>' + dot + '</a>';
}
for (i = 0; i < 100; i++) {
xml += '<a>' + i + '</a>';
}
return xml + '</tags>';
}
public static function xmlTip():void {
stdOut.t (
'必须参数未设置,现在使用演示参数值如下\n'
+ cfg() + '\n\n'
+ '设置方式\n'
+ 'flashVars="&xmlHtml=" + encodeURIComponent(xml值):使用flashVars方式传递,属性名是xmlHtml,它的值在传入swf前必须经过 encodeURIComponent;\n'
+ 'xml值注意事项:\n'
+ '设置初始swf的高宽影响显现是正圆还是椭圆\n'
+ '拼写区分大小写,下面未提及属性无作用,提及的严格按照格式\n'
+ '<a ...></a>标签之间可以随意编写flash支持的html代码;\n'
+ '所有颜色必须使用#ffffff(css合法写法,会自动转化成0xffffff)六位这样完整格式\n'
+ '书写严格xml格式,如正确写法<img />,错误写法<img>\n'
+ '是否值使用0|1即可;\n'
+ '|后是默认值\n'
+ 'xml值格式如下\n'
+ '<?xml version="1.0" encoding="utf-8"?>\n'
+ '<tags swfBgColor="swf背景色|#ffffff" \n'
+ ' colorBarA="未指定字色时,字色自动有规律取色,色条起点A|#000000" colorBarB="未指定字色时,字色自动有规律取色,色条结束点B.注意背景色不应该处于A/B色间,防止自动取色取到背景色|#ffffff" \n'
+ ' swfBgColorTransparent="swf透明使用页面背景色,透明时设置swf的embed之类透明属性,这时swf用背景色|1" \n'
+ ' rollForce="滚动球角度力量|1" \n'
+ ' debug="显示调试信息|0">\n'
+ '<a href="#开头,属于锚占,不能点击|http://或相对网址,可点击|javascript:js代码,swf回调|不设置此属性" target="设置为网址href时打开位置|_blank" \n'
+ ' style="color:字色|无指定时色阶使用色阶;border-color:hover时字色|无指定时使用色阶;font-size:字体大小,磅|12pt;">随意flash支持html</a>\n'
+ '<a ...>更多a...</a>\n'
+ '</tags>\n');
}
}
html
<!DOCTYPE html>
<html>
<head></head>
<body>
<script type="text/javascript" src="swfobject.js"></script>
<div id="tag3DCloud" style="width:400px;height:400px;">ddd</div>
<script type="text/javascript">
var xmlHtml = '<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<tags yRadius=\"0.6\" swfBgColor=\"#ffaaff\" swfBgColorTransparent=\"0\" randomPosition=\"1\" colorBarA=\"#ff0000\" colorBarB=\"#00ff00\" >\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>..........<\/a>\n<a>...<\/a>\n<a>....<\/a>\n<a>.....<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<a>.<\/a>\n<\/tags>';
var soname = new SWFObject("tagcloud.swf?r=" + new Date().getTime(), "tagcloudflash", '100%', '100%', 9);
soname.addVariable("xmlHtml", encodeURIComponent(xmlHtml));
soname.write("tag3DCloud");
</script>
</body>
</html>