/* * 3d标签云 * 功能:鼠标移入标签,当前标签静止放大 * 说明: * */ window.tagcloud = (function(win, doc) { // ns // 判断对象 function isobject (obj) { return object.prototype.tostring.call(obj) === '[object object]'; } // 构造函数 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 = 1 * self.radius; //随鼠标滚动变速作用区域 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; //是否为激活状态 self.lasta = 1; self.lastb = 1; self.mousex0 = self.ispeed * math.sin(self.direction * math.pi / 40); //鼠标与滚动圆心x轴初始距离 self.mousey0 = -self.ispeed * math.cos(self.direction * math.pi / 40); //鼠标与滚动圆心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; }); //鼠标在内移动 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; }; //鼠标移出子元素,当前元素继续滚动 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); }, 10); } //实例 tagcloud.boxs = []; //实例元素数组 // 静态方法们 tagcloud._set = function (element) { if (tagcloud.boxs.indexof(element) == -1) {//ie8不支持数组的indexof方法 return true; } }; //添加数组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: 10, //滚动半径, 单位px mspeed: "normal", //滚动最大速度, 取值: slow, normal(默认), fast ispeed: "normal", //滚动初速度, 取值: slow, normal(默认), fast direction: 90, //初始滚动方向, 取值角度(顺时针360): 0对应top, 90对应left, 135对应right-bottom(默认)... keep: true //鼠标移出组件后是否继续随鼠标滚动, 取值: false, true(默认) 对应 减速至初速度滚动, 随鼠标滚动 }; 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: 1.5, normal: 3, fast: 5 }; return speedmap[mspeed] || 3; }; tagcloud._getisspeed = function (ispeed) { //滚动初速度 var speedmap = { slow: 10, normal: 25, fast: 50 }; return speedmap[ispeed] || 25; }; tagcloud._getsc = function(a, b) { var l = math.pi / 180; //数组顺序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, // 反向引用构造器 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; //单元素数组 } }; 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);