diff --git a/2.html b/2.html new file mode 100644 index 0000000..547e1d0 --- /dev/null +++ b/2.html @@ -0,0 +1,117 @@ + + + + + + Document + + + +
+
生日祝福
+
运动健身
+
通勤路上
+
影视配乐
+
助眠放松
+
派对聚会
+
约会浪漫
+ +
+ + + + diff --git a/song-request-station.html b/song-request-station.html index 56e88d2..1c96940 100644 --- a/song-request-station.html +++ b/song-request-station.html @@ -7,9 +7,9 @@ + -
@@ -33,6 +33,9 @@
+ + +
@@ -40,19 +43,12 @@ diff --git a/static/css/song-request-station.css b/static/css/song-request-station.css index 3a5f82d..fd92c5d 100644 --- a/static/css/song-request-station.css +++ b/static/css/song-request-station.css @@ -7,7 +7,6 @@ width: 100%; background-color: #333333; /* 气泡浮动动画 */ - /* 呼吸效果动画 */ } .container .flexflex { display: flex; @@ -79,16 +78,6 @@ transform: translateY(-15px) translateX(-10px) rotate(-1deg); } } -@keyframes pulse { - 0% { - opacity: 0.8; - box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); - } - 100% { - opacity: 1; - box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15); - } -} .container .container-box { padding-top: 24px; height: 100vh; @@ -281,10 +270,130 @@ padding: 3px 0; margin-bottom: 40px; flex: 1; + z-index: 1; +} +.container .container-box .list-box .left-icon { + width: 121px; + height: 144px; + position: absolute; + top: 61px; + left: 0; + z-index: 1; +} +.container .container-box .list-box .right-icon { + width: 57px; + height: 84px; + position: absolute; + top: 20px; + left: 1120px; + z-index: 1; + transform: rotate(15deg); } .container .container-box .list-box .list { + z-index: 100; +} +.container .container-box .list-box .list-fill .fill-item { + width: 33px; + height: 23px; + border-radius: 8px; + background-color: rgba(255, 255, 255, 0.223529); + position: absolute; + cursor: pointer; +} +.container .container-box .list-box .list-fill .fill-item::after { + content: ""; + width: calc(100% - 6px); + height: calc(100% - 6px); + background: rgba(255, 255, 255, 0.5); + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + border-radius: 8px; + z-index: -1; +} +.container .container-box .list-box .list-fill .fill-item.item2 { + width: 48px; + height: 28px; +} +.container .container-box .list-box .list-fill .fill-item.item3 { + width: 63px; + height: 33px; +} +.container .container-box .list-box .list-fill .fill-item.item4 { + width: 78px; + height: 38px; +} +.container .container-box .list-box .list-fill .fill-item.item5 { + width: 93px; + height: 43px; +} +.container .container-box .list-box .list, +.container .container-box .list-box .list-fill { width: 1194px; height: 100%; + border-radius: 18px; + position: absolute !important; +} +.container .container-box .list-box::after { + content: ""; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: calc(100% - 6px); + height: calc(100% - 6px); background: linear-gradient(180deg, #7d4bf8 0%, #5241b0 100%); + z-index: -1; border-radius: 18px; } +.tag-item { + height: 60px; + line-height: 60px; + border-radius: 30px; + background: #d5e7f7; + position: absolute; + font-size: 20px !important; + color: #1c3e5e; + padding: 0 25px; + width: fit-content; + cursor: pointer; + box-shadow: 0px 0 0 3px rgba(255, 255, 255, 0.223529); + opacity: 1 !important; +} +.tag-item:hover { + font-weight: 650; + color: #583a05 !important; + background-color: #f19a04 !important; +} +.tag-item.item2 { + height: 50px; + line-height: 50px; + border-radius: 25px; + color: #1c3e5e; + padding: 0 20px; + font-size: 18px !important; + background: #d5e7f7; +} +.tag-item.item3 { + height: 47px; + line-height: 47px; + border-radius: 25px; + color: #1c3e5e; + padding: 0 16px; + font-size: 16px !important; + background: #d5e7f7; +} +.tag-item.item4 { + height: 30px; + line-height: 30px; + border-radius: 30px; + color: #1c3e5e; + padding: 0 10px; + font-size: 14px !important; + background: #d5e7f7; +} +.tag-item.red { + color: #62263c !important; + background: linear-gradient(180deg, #ff8eba 0%, #f4458c 100%); +} diff --git a/static/css/song-request-station.less b/static/css/song-request-station.less index c5b64ce..6dd223a 100644 --- a/static/css/song-request-station.less +++ b/static/css/song-request-station.less @@ -50,7 +50,6 @@ overflow: hidden; } - .bubble-tag { position: absolute; padding: 8px 18px; @@ -87,17 +86,17 @@ } } - /* 呼吸效果动画 */ - @keyframes pulse { - 0% { - opacity: 0.8; - box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); - } - 100% { - opacity: 1; - box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15); - } - } + // /* 呼吸效果动画 */ + // @keyframes pulse { + // 0% { + // opacity: 0.8; + // box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); + // } + // 100% { + // opacity: 1; + // box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15); + // } + // } .container-box { padding-top: 24px; @@ -313,12 +312,209 @@ padding: 3px 0; margin-bottom: 40px; flex: 1; + z-index: 1; + + .left-icon { + width: 121px; + height: 144px; + position: absolute; + top: 61px; + left: 0; + z-index: 1; + } + + .right-icon { + width: 57px; + height: 84px; + position: absolute; + top: 20px; + left: 1120px; + z-index: 1; + transform: rotate(15deg); + } + .list { + z-index: 100; + // background: linear-gradient(180deg, #7d4bf8 0%, #5241b0 100%); + } + + .list-fill { + .fill-item { + width: 33px; + height: 23px; + border-radius: 8px; + background-color: rgba(255, 255, 255, 0.223529); + position: absolute; + cursor: pointer; + + &::after { + content: ""; + width: calc(100% - 6px); + height: calc(100% - 6px); + background: rgba(255, 255, 255, 0.5); + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + border-radius: 8px; + z-index: -1; + } + + &.item2 { + width: 48px; + height: 28px; + } + + &.item3 { + width: 63px; + height: 33px; + } + + &.item4 { + width: 78px; + height: 38px; + } + + &.item5 { + width: 93px; + height: 43px; + } + } + } + + .list, + .list-fill { width: 1194px; height: 100%; + border-radius: 18px; + position: absolute !important; + } + + &::after { + content: ""; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: calc(100% - 6px); + height: calc(100% - 6px); background: linear-gradient(180deg, #7d4bf8 0%, #5241b0 100%); + z-index: -1; border-radius: 18px; } } } } + +.tag-item { + height: 60px; + line-height: 60px; + // border-radius: 8px; + border-radius: 30px; + // background-color: rgba(255, 255, 255, 0.223529); + background: #d5e7f7; + + position: absolute; + font-size: 20px !important; + color: #1c3e5e; + + padding: 0 25px; + width: fit-content; + cursor: pointer; + // transition: all 0.3s; + box-shadow: 0px 0 0 3px rgba(255, 255, 255, 0.223529); + opacity: 1 !important; + &:hover { + font-weight: 650; + color: rgb(88, 58, 5) !important; + background-color: rgba(241, 154, 4, 1) !important; + + // &::after { + // background-color: rgba(241, 154, 4, 1) !important; + // } + } + + // &.item2 { + // height: 60px; + // line-height: 60px; + // border-radius: 30px; + + // color: #1c3e5e; + // font-size: 20px !important; + + // // &::after { + // // background: #d5e7f7; + // // } + // } + + &.item2 { + height: 50px; + line-height: 50px; + border-radius: 25px; + + color: #1c3e5e; + padding: 0 20px; + font-size: 18px !important; + background: #d5e7f7; + // &::after { + // background: #d5e7f7; + // border-radius: 250px; + // } + } + + &.item3 { + height: 47px; + line-height: 47px; + border-radius: 25px; + + color: #1c3e5e; + padding: 0 16px; + font-size: 16px !important; + background: #d5e7f7; + + // &::after { + // background: #d5e7f7; + // border-radius: 25px; + // } + } + + &.item4 { + height: 30px; + line-height: 30px; + border-radius: 30px; + + color: #1c3e5e; + padding: 0 10px; + font-size: 14px !important; + background: #d5e7f7; + + // &::after { + // background: #d5e7f7; + // border-radius: 30px; + // } + } + + // &::after { + // content: ""; + // width: calc(100% - 6px); + // height: calc(100% - 6px); + // // background: linear-gradient(180deg, #ff8eba 0%, #f4458c 100%); + // background: #d5e7f7; + // position: absolute; + // top: 50%; + // left: 50%; + // transform: translate(-50%, -50%); + // // border-radius: 8px; + // border-radius: 30px; + // z-index: -1; + // } + + &.red { + color: #62263c !important; + background: linear-gradient(180deg, #ff8eba 0%, #f4458c 100%); + + &::after { + // background: linear-gradient(180deg, #ff8eba 0%, #f4458c 100%); + } + } +} diff --git a/static/img/left-icon.png b/static/img/left-icon.png new file mode 100644 index 0000000..23aee1b Binary files /dev/null and b/static/img/left-icon.png differ diff --git a/static/img/right-icon.png b/static/img/right-icon.png new file mode 100644 index 0000000..068ed19 Binary files /dev/null and b/static/img/right-icon.png differ diff --git a/static/js/music.json b/static/js/music.json new file mode 100644 index 0000000..429276d --- /dev/null +++ b/static/js/music.json @@ -0,0 +1,221 @@ +{ + "code": 200, + "data": [ + { + "tag": "彩虹泡泡", + "songs": [ + { + "name": "彩虹的秘密", + "path": "/music/rainbow_secret.mp3" + }, + { + "name": "泡泡飞舞", + "path": "/music/bubble_dance.mp3" + } + ] + }, + { + "tag": "星际漫游", + "songs": [ + { + "name": "银河漫游", + "path": "/music/galaxy_trip.mp3" + }, + { + "name": "星空遨游", + "path": "/music/stars_voyage.mp3" + } + ] + }, + { + "tag": "开心到飞起", + "songs": [ + { + "name": "无忧快乐", + "path": "/music/joyful_day.mp3" + } + ] + }, + { + "tag": "甜蜜时光", + "songs": [ + { + "name": "甜甜小记忆", + "path": "/music/sweet_memory.mp3" + }, + { + "name": "美好时刻", + "path": "/music/beautiful_moment.mp3" + } + ] + }, + { + "tag": "探险", + "songs": [ + { + "name": "勇闯秘境", + "path": "/music/adventure_secret.mp3" + } + ] + }, + { + "tag": "梦幻", + "songs": [ + { + "name": "漫步梦境", + "path": "/music/dream_walk.mp3" + }, + { + "name": "幻想奇缘", + "path": "/music/fantasy_story.mp3" + } + ] + }, + { + "tag": "幻想曲", + "songs": [ + { + "name": "魔法旋律", + "path": "/music/magical_melody.mp3" + } + ] + }, + { + "tag": "自由摇摆", + "songs": [ + { + "name": "随风而舞", + "path": "/music/dance_with_wind.mp3" + }, + { + "name": "自由律动", + "path": "/music/free_groove.mp3" + } + ] + }, + { + "tag": "夏日狂欢", + "songs": [ + { + "name": "阳光派对", + "path": "/music/sunshine_party.mp3" + }, + { + "name": "夏夜节奏", + "path": "/music/summer_rhythm.mp3" + } + ] + }, + { + "tag": "微风轻轻吹", + "songs": [ + { + "name": "轻柔微风", + "path": "/music/gentle_breeze.mp3" + } + ] + }, + { + "tag": "江湖", + "songs": [ + { + "name": "剑歌少年", + "path": "/music/hero_ballad.mp3" + } + ] + }, + { + "tag": "浪漫", + "songs": [ + { + "name": "心动时分", + "path": "/music/romantic_time.mp3" + }, + { + "name": "甜蜜心跳", + "path": "/music/love_heartbeat.mp3" + } + ] + }, + { + "tag": "阳光正好", + "songs": [ + { + "name": "晴天物语", + "path": "/music/cloudless_story.mp3" + } + ] + }, + { + "tag": "青草香", + "songs": [ + { + "name": "原野微风", + "path": "/music/field_breeze.mp3" + }, + { + "name": "绿色时光", + "path": "/music/green_time.mp3" + } + ] + }, + { + "tag": "赛博心跳", + "songs": [ + { + "name": "虚拟律动", + "path": "/music/cyber_heartbeat.mp3" + }, + { + "name": "脉动交响", + "path": "/music/cyber_beats.mp3" + } + ] + }, + { + "tag": "赛博空间", + "songs": [ + { + "name": "未来之眼", + "path": "/music/future_sight.mp3" + } + ] + }, + { + "tag": "节奏大师", + "songs": [ + { + "name": "极限节拍", + "path": "/music/ultimate_beat.mp3" + } + ] + }, + { + "tag": "民谣", + "songs": [ + { + "name": "悠然时光", + "path": "/music/folk_time.mp3" + } + ] + }, + { + "tag": "去旅行", + "songs": [ + { + "name": "旅途光影", + "path": "/music/journey_lights.mp3" + } + ] + }, + { + "tag": "学习BGM", + "songs": [ + { + "name": "静心阅读", + "path": "/music/study_focus.mp3" + } + ] + } + ] +} \ No newline at end of file diff --git a/static/js/tagcloud-2.2 - 副本.js b/static/js/tagcloud-2.2 - 副本.js new file mode 100644 index 0000000..29beb11 --- /dev/null +++ b/static/js/tagcloud-2.2 - 副本.js @@ -0,0 +1,326 @@ +/* +* 3d标签云 +* 功能:鼠标移入标签,当前标签静止放大 +* 说明:radius 控制滚动区域(横椭圆、纵椭圆、正圆) +* 版本:2.2 +* */ + +window.tagCloud = (function (win, doc) { + // 判断对象 + 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; // 平均字体大小 + + if (Number.isInteger(self.config.radius)) { + self._radiusX = self._radiusY = self.config.radius + } else if (self.config.radius instanceof Array) { + if (self.config.radius.length === 1) { + self._radiusX = self._radiusY = self.config.radius[0] + } else { + self._radiusX = self.config.radius[0] + self._radiusY = self.config.radius[1] + } + } + + self.radius = self._radiusX; // 滚动半径 + + _ratio = Math.round(self._radiusX * 10 / self._radiusY) / 10; // 滚动区域比例,保留一位小数 + if(_ratio < 1 ) { // 焦点在Y轴的椭圆 + self.ratioX = _ratio; + self.ratioY = 1; + self.radius = self._radiusY; // 滚动半径,选择长半径 + } else if(_ratio > 1 ) { // 焦点在X轴的椭圆 + self.ratioX = 1; + self.ratioY = _ratio; + } else { + self.ratioX = self.ratioY = 1; // 正圆 + } + + self.depth = 2 * self.radius; // 滚动深度 + self.size = 2 * 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 / 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; + }); + + // 鼠标在内移动 + 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'; + 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 = []; //实例元素数组 + // 静态方法们 + TagCloud._set = function (element) { + if (TagCloud.boxs.indexOf(element) === -1) { // ie8不支持数组的indexOf方法,所以自定义indexOf + return true; + } + }; + + //添加数组IndexOf方法 + if (!Array.prototype.indexOf) { + // Array.prototype.indexOf = function (elt /*, from*/) { + Array.prototype.indexOf = function (elt) { + 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, // 滚动纵轴半径, 默认60, 单位px,取值60,[60],[60, 60] + mspeed: "normal", // 滚动最大速度, 取值: slow, normal(默认), fast + ispeed: "normal", // 滚动初速度, 取值: slow, normal(默认), fast + direction: 135, // 初始滚动方向, 取值角度(顺时针360): 0对应top, 90对应left, 135对应right-bottom(默认)... + keep: true, // 鼠标移出组件后是否继续随鼠标滚动, 取值: false, true(默认) 对应 减速至初速度滚动, 随鼠标滚动 + multicolour: true // 是否为彩色字体,颜色随机,取值:true(默认),false + }; + + 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) * 2 / self.radius) * self.mspeed; + b = (Math.min(Math.max(-self.mouseX, -self.size), self.size) * 2 / 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 = 18; + 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.ratioX + (self.box.offsetWidth - self.items[j].offsetWidth) / 2 + "px"; + self.items[j].element.style.top = self.items[j].y / self.ratioY + (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 / 2 * 1.5 * Math.cos(item.angle.theta) * Math.sin(item.angle.phi); + item.y = self.radius / 2 * 1.5 * Math.sin(item.angle.theta) * Math.sin(item.angle.phi); + item.z = self.radius / 2 * 1.5 * Math.cos(item.angle.phi); + item.element.style.left = item.x * self.ratioX + ( self.box.offsetWidth - item.offsetWidth ) / 2 + "px"; + item.element.style.top = item.y / self.ratioY + ( self.box.offsetHeight - item.offsetHeight ) / 2 + "px"; + if (self.config.multicolour) { // 初始化文字颜色为彩色 + _color = self._randomNumBoth(0, 360); // 定义色相 (0 到 360) - 0 (或 360) 红,120绿,180青,240蓝,300紫 + _light = self._randomNumBoth(30, 60); // 定义亮度 0% 为暗, 50% 为普通, 100% 为白 + item.element.style.color = "hsl(" + _color + ", 100%, " + _light + "%)"; // 中间值为饱和度; 0%灰色,100%全色 + // item.element.style.color = 'rgb(' + parseInt(Math.random() * 255) + ',' + parseInt(Math.random() * 255) + ',' + parseInt(Math.random() * 255) + ')'; + } + items.push(item); + } + return items; //单元素数组 + }, + + // 取随机值,Min ≤ num ≤ Max + _randomNumBoth: function(Min, Max){ + var Range = Max - Min; + var Rand = Math.random(); + var num = Min + Math.round(Rand * Range); //四舍五入 + return num; + } + }; + + 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) \ No newline at end of file diff --git a/static/js/tagcloud-2.2.js b/static/js/tagcloud-2.2.js new file mode 100644 index 0000000..367b843 --- /dev/null +++ b/static/js/tagcloud-2.2.js @@ -0,0 +1,332 @@ +/* + * 3d标签云 + * 功能:鼠标移入标签,当前标签静止放大 + * 说明:radius 控制滚动区域(横椭圆、纵椭圆、正圆) + * 版本:2.2 + * */ + +window.tagCloud = (function (win, doc) { + // 判断对象 + 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; // 平均字体大小 + + if (Number.isInteger(self.config.radius)) { + self._radiusX = self._radiusY = self.config.radius; + } else if (self.config.radius instanceof Array) { + if (self.config.radius.length === 1) { + self._radiusX = self._radiusY = self.config.radius[0]; + } else { + self._radiusX = self.config.radius[0]; + self._radiusY = self.config.radius[1]; + } + } + + self.radius = self._radiusX; // 滚动半径 + + _ratio = Math.round((self._radiusX * 10) / self._radiusY) / 10; // 滚动区域比例,保留一位小数 + if (_ratio < 1) { + // 焦点在Y轴的椭圆 + self.ratioX = _ratio; + self.ratioY = 1; + self.radius = self._radiusY; // 滚动半径,选择长半径 + } else if (_ratio > 1) { + // 焦点在X轴的椭圆 + self.ratioX = 1; + self.ratioY = _ratio; + } else { + self.ratioX = self.ratioY = 1; // 正圆 + } + + self.depth = 2 * self.radius; // 滚动深度 + self.size = 2 * 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) / 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; + }); + + // 鼠标在内移动 + 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"; + 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); + }, 5); + } + + //实例 + TagCloud.boxs = []; //实例元素数组 + // 静态方法们 + TagCloud._set = function (element) { + if (TagCloud.boxs.indexOf(element) === -1) { + // ie8不支持数组的indexOf方法,所以自定义indexOf + return true; + } + }; + + //添加数组IndexOf方法 + if (!Array.prototype.indexOf) { + // Array.prototype.indexOf = function (elt /*, from*/) { + Array.prototype.indexOf = function (elt) { + 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, // 滚动纵轴半径, 默认60, 单位px,取值60,[60],[60, 60] + mspeed: "normal", // 滚动最大速度, 取值: slow, normal(默认), fast + ispeed: "normal", // 滚动初速度, 取值: slow, normal(默认), fast + direction: 135, // 初始滚动方向, 取值角度(顺时针360): 0对应top, 90对应left, 135对应right-bottom(默认)... + keep: true, // 鼠标移出组件后是否继续随鼠标滚动, 取值: false, true(默认) 对应 减速至初速度滚动, 随鼠标滚动 + multicolour: true, // 是否为彩色字体,颜色随机,取值:true(默认),false + }; + + 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, + slow2: 14, + 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) * 2) / self.radius) * self.mspeed; + b = ((Math.min(Math.max(-self.mouseX, -self.size), self.size) * 2) / 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 = 18; + 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.ratioX + (self.box.offsetWidth - self.items[j].offsetWidth) / 2 + "px"; + self.items[j].element.style.top = self.items[j].y / self.ratioY + (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 / 2) * 1.5 * Math.cos(item.angle.theta) * Math.sin(item.angle.phi); + item.y = (self.radius / 2) * 1.5 * Math.sin(item.angle.theta) * Math.sin(item.angle.phi); + item.z = (self.radius / 2) * 1.5 * Math.cos(item.angle.phi); + item.element.style.left = item.x * self.ratioX + (self.box.offsetWidth - item.offsetWidth) / 2 + "px"; + item.element.style.top = item.y / self.ratioY + (self.box.offsetHeight - item.offsetHeight) / 2 + "px"; + if (self.config.multicolour) { + // 初始化文字颜色为彩色 + _color = self._randomNumBoth(0, 360); // 定义色相 (0 到 360) - 0 (或 360) 红,120绿,180青,240蓝,300紫 + _light = self._randomNumBoth(30, 60); // 定义亮度 0% 为暗, 50% 为普通, 100% 为白 + item.element.style.color = "hsl(" + _color + ", 100%, " + _light + "%)"; // 中间值为饱和度; 0%灰色,100%全色 + // item.element.style.color = 'rgb(' + parseInt(Math.random() * 255) + ',' + parseInt(Math.random() * 255) + ',' + parseInt(Math.random() * 255) + ')'; + } + items.push(item); + } + return items; //单元素数组 + }, + + // 取随机值,Min ≤ num ≤ Max + _randomNumBoth: function (Min, Max) { + var Range = Max - Min; + var Rand = Math.random(); + var num = Min + Math.round(Rand * Range); //四舍五入 + return num; + }, + }; + + 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);