原生方法組件封裝:詞云圖動態(tài)效果展示

/*
* 功能:鼠標移入標簽六孵,當前標簽靜止放大;不同方向進入詞云模塊计维,旋轉(zhuǎn)方向調(diào)整至對應(yīng)的方向
* 說明:
* */

window.tagcloud = (function(win, doc) { // ns
    // 判斷對象
    function isObject (obj) {
        return Object.prototype.toString.call(obj) === '[object Object]';
    }

    // 構(gòu)造函數(shù)
    function TagCloud (options) {
        var self = this;
        self.config = TagCloud._getConfig(options);
        self.box = self.config.element;   //組件元素
        self.fontsize = self.config.fontsize; //平均字體大小
        self.radius = self.config.radius; //滾動半徑
        self.depth = 2 * self.radius;   //滾動深度
        self.size = 2 * self.radius;    //隨鼠標滾動變速作用區(qū)域
        self.mspeed = TagCloud._getMsSpeed(self.config.mspeed);
        self.ispeed = TagCloud._getIsSpeed(self.config.ispeed);
        self.items = self._getItems();

        self.direction = self.config.direction;   //初始滾動方向
        self.keep = self.config.keep; //鼠標移出后是否保持之前滾動

        //初始化
        self.active = false;   //是否為激活狀態(tài)
        self.lasta = 1;
        self.lastb = 1;
        self.mouseX0 = self.ispeed * Math.sin(self.direction * Math.PI / 180);    //鼠標與滾動圓心x軸初始距離
        self.mouseY0 = -self.ispeed * Math.cos(self.direction * Math.PI / 180);   //鼠標與滾動圓心y軸初始距離
        self.mouseX = self.mouseX0;   //鼠標與滾動圓心x軸距離
        self.mouseY = self.mouseY0;   //鼠標與滾動圓心y軸距離
        self.index = -1;

        //鼠標移入
        TagCloud._on(self.box, 'mouseover', function () {
            self.active = true;
        });
        //鼠標移出
        TagCloud._on(self.box, 'mouseout', function () {
            self.active = false;
        });

        //鼠標在內(nèi)移動
        TagCloud._on(self.keep ? win : self.box, 'mousemove', function (ev) {
            var oEvent = win.event || ev;
            var boxPosition = self.box.getBoundingClientRect();
            self.mouseX = (oEvent.clientX - (boxPosition.left + self.box.offsetWidth / 2)) / 5;
            self.mouseY = (oEvent.clientY - (boxPosition.top + self.box.offsetHeight / 2)) / 5;
        });

        for (var j = 0, len = self.items.length; j < len; j++) {
            self.items[j].element.index=j;

            //鼠標移出子元素,當前元素靜止放大
            self.items[j].element.onmouseover = function(){
                self.index = this.index;
            };

            //鼠標移出子元素,當前元素繼續(xù)滾動
            self.items[j].element.onmouseout = function(){
                self.index = -1;
            };
        }

        //定時更新
        TagCloud.boxs.push(self.box);
        self.update(self);    //初始更新
        self.box.style.visibility = "visible";
        self.box.style.position = "relative";
        self.box.style.minHeight = 1.2 * self.size + "px";
        self.box.style.minWidth = 2.5 * self.size + "px";
        for (var j = 0, len = self.items.length; j < len; j++) {
            self.items[j].element.style.position = "absolute";
            self.items[j].element.style.zIndex = j + 1;
        }
        self.up = setInterval(function() {
            self.update(self);
        }, 30);
    }

    //實例
    TagCloud.boxs = []; //實例元素數(shù)組
    // 靜態(tài)方法們
    TagCloud._set = function (element) {
        if (TagCloud.boxs.indexOf(element) == -1) {//ie8不支持數(shù)組的indexOf方法
            return true;
        }
    };

    //添加數(shù)組IndexOf方法
    if (!Array.prototype.indexOf){
        Array.prototype.indexOf = function(elt /*, from*/){
            var len = this.length >>> 0;
            var from = Number(arguments[1]) || 0;
            from = (from < 0)
                ? Math.ceil(from)
                : Math.floor(from);
            if (from < 0)
                from += len;
            for (; from < len; from++){
                if (from in this && this[from] === elt)
                    return from;
            }
            return -1;
        };
    }


    TagCloud._getConfig = function (config) {
        var defaultConfig = {   //默認值
            fontsize: 16,       //基本字體大小, 單位px
            radius: 60,         //滾動半徑, 單位px
            mspeed: "normal",   //滾動最大速度, 取值: slow, normal(默認), fast
            ispeed: "normal",   //滾動初速度, 取值: slow, normal(默認), fast
            direction: 135,     //初始滾動方向, 取值角度(順時針360): 0對應(yīng)top, 90對應(yīng)left, 135對應(yīng)right-bottom(默認)...
            keep: true          //鼠標移出組件后是否繼續(xù)隨鼠標滾動, 取值: false, true(默認) 對應(yīng) 減速至初速度滾動, 隨鼠標滾動
        };

        if(isObject(config)) {
            for(var i in config) {
                if(config.hasOwnProperty(i)) {//hasOwnProperty()用來判斷一個屬性是定義在對象本身而不是繼承自原型鏈
                    defaultConfig[i] = config[i]; //用戶配置
                }
            }
        }

        return defaultConfig;// 配置 Merge
    };
    TagCloud._getMsSpeed = function (mspeed) {    //滾動最大速度
        var speedMap = {
            slow: 3,
            normal: 3,
            fast: 5
        };
        return speedMap[mspeed] || 3;
    };
    TagCloud._getIsSpeed = function (ispeed) {    //滾動初速度
        var speedMap = {
            slow: 25,
            normal: 25,
            fast: 50
        };
        return speedMap[ispeed] || 25;
    };
    TagCloud._getSc = function(a, b) {
        var l = Math.PI / 180;
        //數(shù)組順序0,1,2,3表示asin,acos,bsin,bcos
        return [
            Math.sin(a * l),
            Math.cos(a * l),
            Math.sin(b * l),
            Math.cos(b * l)
        ];
    };

    TagCloud._on = function (ele, eve, handler, cap) {
        if (ele.addEventListener) {
            ele.addEventListener(eve, handler, cap);
        } else if (ele.attachEvent) {
            ele.attachEvent('on' + eve, handler);
        } else {
            ele['on' + eve] = handler;
        }
    };

    // 原型方法
    TagCloud.prototype = {
        constructor: TagCloud, // 反向引用構(gòu)造器

        update: function () {
            var self = this, a, b;

            if (!self.active && !self.keep) {
                self.mouseX = Math.abs(self.mouseX - self.mouseX0) < 1 ? self.mouseX0 : (self.mouseX + self.mouseX0) / 2;   //重置鼠標與滾動圓心x軸距離
                self.mouseY = Math.abs(self.mouseY - self.mouseY0) < 1 ? self.mouseY0 : (self.mouseY + self.mouseY0) / 2;   //重置鼠標與滾動圓心y軸距離
            }

            a = -(Math.min(Math.max(-self.mouseY, -self.size), self.size) / self.radius ) * self.mspeed;
            b = (Math.min(Math.max(-self.mouseX, -self.size), self.size) / self.radius ) * self.mspeed;

            if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) { return; }

            self.lasta = a;
            self.lastb = b;

            var sc = TagCloud._getSc(a, b);

            for (var j = 0, len = self.items.length; j < len; j++) {

                var rx1 = self.items[j].x,
                    ry1 = self.items[j].y*sc[1] + self.items[j].z*(-sc[0]),
                    rz1 = self.items[j].y*sc[0] + self.items[j].z*sc[1];

                var rx2 = rx1 * sc[3] + rz1 * sc[2],
                    ry2 = ry1,
                    rz2 = rz1 * sc[3] - rx1 * sc[2];

                if(self.index==j){

                    self.items[j].scale = 1; //取值范圍0.6 ~ 3
                    self.items[j].fontsize = 16;
                    self.items[j].alpha = 1;
                    self.items[j].element.style.zIndex = 99;
                }else{
                    var per = self.depth / (self.depth + rz2);
                    self.items[j].x = rx2;
                    self.items[j].y = ry2;
                    self.items[j].z = rz2;

                    self.items[j].scale = per; //取值范圍0.6 ~ 3
                    self.items[j].fontsize = Math.ceil(per * 2) + self.fontsize - 6;
                    self.items[j].alpha = 1.5 * per - 0.5;
                    self.items[j].element.style.zIndex = Math.ceil(per*10-5);
                }
                self.items[j].element.style.fontSize = self.items[j].fontsize + "px";
                self.items[j].element.style.left = self.items[j].x + (self.box.offsetWidth - self.items[j].offsetWidth) / 2 + "px";
                self.items[j].element.style.top = self.items[j].y + (self.box.offsetHeight - self.items[j].offsetHeight) / 2 + "px";
                self.items[j].element.style.filter = "alpha(opacity=" + 100 * self.items[j].alpha + ")";
                self.items[j].element.style.opacity = self.items[j].alpha;
            }
        },

        _getItems: function () {
            var self = this,
                items = [],
                element = self.box.children, // children 全部是Element
                length = element.length,
                item;

            for (var i = 0; i < length; i++) {
                item = {};
                item.angle = {};
                item.angle.phi = Math.acos(-1 + (2 * i + 1) / length);
                item.angle.theta = Math.sqrt((length + 1) * Math.PI) * item.angle.phi;
                item.element = element[i];
                item.offsetWidth = item.element.offsetWidth;
                item.offsetHeight = item.element.offsetHeight;
                item.x = self.radius * 1.5 * Math.cos(item.angle.theta) * Math.sin(item.angle.phi);
                item.y = self.radius * 1.5 * Math.sin(item.angle.theta) * Math.sin(item.angle.phi);
                item.z = self.radius * 1.5 * Math.cos(item.angle.phi);
                item.element.style.left = item.x + (self.box.offsetWidth - item.offsetWidth) / 2 + "px";
                item.element.style.top = item.y + (self.box.offsetHeight - item.offsetHeight) / 2 + "px";
                items.push(item);
            }

            return items;   //單元素數(shù)組
        }
    };

    if (!doc.querySelectorAll) {//ie7不支持querySelectorAll,所以要重新定義
        doc.querySelectorAll = function (selectors) {
            var style = doc.createElement('style'), elements = [], element;
            doc.documentElement.firstChild.appendChild(style);
            doc._qsa = [];
            style.styleSheet.cssText = selectors + '{x-qsa:expression(document._qsa && document._qsa.push(this))}';
            window.scrollBy(0, 0);
            style.parentNode.removeChild(style);

            while (doc._qsa.length) {
                element = doc._qsa.shift();
                element.style.removeAttribute('x-qsa');
                elements.push(element);
            }
            doc._qsa = null;
            return elements;
        };
    }

    return function (options) { // factory
        options = options || {}; // 短路語法
        var selector = options.selector || '.tagcloud', //默認選擇class為tagcloud的元素
            elements = doc.querySelectorAll(selector),
            instance = [];
        for (var index = 0, len = elements.length; index < len; index++) {
            options.element = elements[index];
            if (!!TagCloud._set(options.element)) {
                instance.push(new TagCloud(options));
            }
        }
        return instance;
    };
})(window, document);

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瞧省,一起剝皮案震驚了整個濱河市深纲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖蛀骇,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異读拆,居然都是意外死亡擅憔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門檐晕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來暑诸,“玉大人蚌讼,你說我怎么就攤上這事「鲩牛” “怎么了篡石?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長西采。 經(jīng)常有香客問我凰萨,道長,這世上最難降的妖魔是什么械馆? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任胖眷,我火速辦了婚禮,結(jié)果婚禮上霹崎,老公的妹妹穿的比我還像新娘珊搀。我一直安慰自己,他們只是感情好仿畸,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布食棕。 她就那樣靜靜地躺著,像睡著了一般错沽。 火紅的嫁衣襯著肌膚如雪簿晓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天千埃,我揣著相機與錄音憔儿,去河邊找鬼。 笑死放可,一個胖子當著我的面吹牛谒臼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播耀里,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼蜈缤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了冯挎?” 一聲冷哼從身側(cè)響起底哥,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎房官,沒想到半個月后趾徽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡翰守,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年孵奶,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜡峰。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡了袁,死狀恐怖朗恳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情早像,我是刑警寧澤僻肖,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布肖爵,位于F島的核電站卢鹦,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏劝堪。R本人自食惡果不足惜冀自,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望秒啦。 院中可真熱鬧熬粗,春花似錦、人聲如沸余境。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽芳来。三九已至含末,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間即舌,已是汗流浹背佣盒。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留顽聂,地道東北人肥惭。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像紊搪,于是被迫代替她去往敵國和親蜜葱。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容