flash版本的3d标签云图as3代码,已经修改成过._xml

正圆

flash版本的3d标签云图as3代码,已经修改成过._Math_02

套圆

flash版本的3d标签云图as3代码,已经修改成过._xml_03

半圆


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>