【前端特效】程式員給你的專屬告白,快來轉發給你心愛的那個她吧! 點擊打開視頻講解更加詳細 <template> <div class="content"> <img src="../assets/live.gif" alt="" /> <section class="cloud-bed"> <div ...
【前端特效】程式員給你的專屬告白,快來轉發給你心愛的那個她吧!
<template>
<div class="content">
<img src="../assets/live.gif" alt="" />
<section class="cloud-bed">
<div class="cloud-box">
<span
v-for="(item, index) in dataList"
:key="index"
@click="getDataInfo(item)"
:style="{ color: item.color, background: item.bgColor }"
>
{{ item.name }}
</span>
</div>
</section>
</div>
</template>
<script>
export default {
name: "word-cloud",
data() {
return {
timer: 50, // 球體轉動速率
radius: 0, // 詞雲球體面積大小
dtr: Math.PI / 180, //滑鼠滑過球體轉動速度
active: false, // 預設載入是否開啟轉動
lasta: 0, // 上下轉動
lastb: 0.5, // 左右轉動
distr: true,
tspeed: 0, // 滑鼠移動上去時球體轉動
mouseX: 0,
mouseY: 0,
tagAttrList: [],
tagContent: null,
cloudContent: null,
sinA: "",
cosA: "",
sinB: "",
cosB: "",
sinC: "",
cosC: "",
dataList: [
{
name: "金晨",
value: "1",
bgColor: "rgb(57, 193, 207,0.12)",
color: "#39c1cf",
},
{
name: "昆凌",
value: "8",
bgColor: "rgb(66, 105, 245,0.12)",
color: "#4269f5",
},
{
name: "劉亦菲",
value: "9",
bgColor: "rgb(184, 107, 215,0.12)",
color: "#b86bd7",
},
{
name: "林志玲",
value: "3",
bgColor: "rgb(243, 84, 83,0.12)",
color: "#f35453",
},
{
name: "林心如",
value: "6",
bgColor: "rgb(250, 116, 20,0.12)",
color: "#FA7414",
},
{
name: "李沁",
value: "10",
bgColor: "rgb(255, 171, 30,0.12)",
color: "#FFAB1E",
},
{
name: "林依晨",
value: "2",
bgColor: "rgb(136, 104, 217,0.12)",
color: "#8868D9",
},
{
name: "李宇春",
value: "5",
bgColor: "rgb(42, 184, 230,0.12)",
color: "#2AB8E6",
},
{
name: "賈靜雯",
value: "7",
bgColor: "rgb(117, 133, 162,0.12)",
color: "#7585A2",
},
],
};
},
mounted() {
this.$nextTick(() => {
this.radius = document.querySelector(".cloud-box").offsetWidth / 3;
this.initWordCloud();
});
},
beforeDestroy() {
clearInterval(this.timer);
},
methods: {
// 獲取點擊文本信息
getDataInfo(item) {
console.log(item, "item");
},
initWordCloud() {
this.cloudContent = document.querySelector(".cloud-box");
this.tagContent = this.cloudContent.getElementsByTagName("span");
for (let i = 0; i < this.tagContent.length; i++) {
let tagObj = {};
tagObj.offsetWidth = this.tagContent[i].offsetWidth;
tagObj.offsetHeight = this.tagContent[i].offsetHeight;
this.tagAttrList.push(tagObj);
}
this.sineCosine(0, 0, 0);
this.positionAll();
this.cloudContent.onmouseover = () => {
this.active = true;
};
this.cloudContent.onmouseout = () => {
this.active = false;
};
this.cloudContent.onmousemove = (ev) => {
let oEvent = window.event || ev;
this.mouseX =
oEvent.clientX -
(this.cloudContent.offsetLeft + this.cloudContent.offsetWidth / 2);
this.mouseY =
oEvent.clientY -
(this.cloudContent.offsetTop + this.cloudContent.offsetHeight / 2);
this.mouseX /= 5;
this.mouseY /= 5;
};
setInterval(this.update, this.timer);
},
positionAll() {
let phi = 0;
let theta = 0;
let max = this.tagAttrList.length;
let aTmp = [];
let oFragment = document.createDocumentFragment();
//隨機排序
for (let i = 0; i < this.tagContent.length; i++) {
aTmp.push(this.tagContent[i]);
}
aTmp.sort(() => {
return Math.random() < 0.5 ? 1 : -1;
});
for (let i = 0; i < aTmp.length; i++) {
oFragment.appendChild(aTmp[i]);
}
this.cloudContent.appendChild(oFragment);
for (let i = 1; i < max + 1; i++) {
if (this.distr) {
phi = Math.acos(-1 + (2 * i - 1) / max);
theta = Math.sqrt(max * Math.PI) * phi;
} else {
phi = Math.random() * Math.PI;
theta = Math.random() * (2 * Math.PI);
}
//坐標變換
this.tagAttrList[i - 1].cx =
this.radius * Math.cos(theta) * Math.sin(phi);
this.tagAttrList[i - 1].cy =
this.radius * Math.sin(theta) * Math.sin(phi);
this.tagAttrList[i - 1].cz = this.radius * Math.cos(phi);
this.tagContent[i - 1].style.left =
this.tagAttrList[i - 1].cx +
this.cloudContent.offsetWidth / 2 -
this.tagAttrList[i - 1].offsetWidth / 2 +
"px";
this.tagContent[i - 1].style.top =
this.tagAttrList[i - 1].cy +
this.cloudContent.offsetHeight / 2 -
this.tagAttrList[i - 1].offsetHeight / 2 +
"px";
}
},
update() {
let angleBasicA;
let angleBasicB;
if (this.active) {
angleBasicA =
(-Math.min(Math.max(-this.mouseY, -200), 200) / this.radius) *
this.tspeed;
angleBasicB =
(Math.min(Math.max(-this.mouseX, -200), 200) / this.radius) *
this.tspeed;
} else {
angleBasicA = this.lasta * 0.98;
angleBasicB = this.lastb * 0.98;
}
//預設轉動是後是否需要停下
// lasta=a;
// lastb=b;
// if(Math.abs(a)<=0.01 && Math.abs(b)<=0.01)
// {
// return;
// }
this.sineCosine(angleBasicA, angleBasicB, 0);
for (let j = 0; j < this.tagAttrList.length; j++) {
let rx1 = this.tagAttrList[j].cx;
let ry1 =
this.tagAttrList[j].cy * this.cosA +
this.tagAttrList[j].cz * -this.sinA;
let rz1 =
this.tagAttrList[j].cy * this.sinA +
this.tagAttrList[j].cz * this.cosA;
let rx2 = rx1 * this.cosB + rz1 * this.sinB;
let ry2 = ry1;
let rz2 = rx1 * -this.sinB + rz1 * this.cosB;
let rx3 = rx2 * this.cosC + ry2 * -this.sinC;
let ry3 = rx2 * this.sinC + ry2 * this.cosC;
let rz3 = rz2;
this.tagAttrList[j].cx = rx3;
this.tagAttrList[j].cy = ry3;
this.tagAttrList[j].cz = rz3;
let per = 350 / (350 + rz3);
this.tagAttrList[j].x = rx3 * per - 2;
this.tagAttrList[j].y = ry3 * per;
this.tagAttrList[j].scale = per;
this.tagAttrList[j].alpha = per;
this.tagAttrList[j].alpha =
(this.tagAttrList[j].alpha - 0.6) * (10 / 6);
}
this.doPosition();
this.depthSort();
},
doPosition() {
let len = this.cloudContent.offsetWidth / 2;
let height = this.cloudContent.offsetHeight / 2;
for (let i = 0; i < this.tagAttrList.length; i++) {
this.tagContent[i].style.left =
this.tagAttrList[i].cx +
len -
this.tagAttrList[i].offsetWidth / 2 +
"px";
this.tagContent[i].style.top =
this.tagAttrList[i].cy +
height -
this.tagAttrList[i].offsetHeight / 2 +
"px";
// this.tagContent[i].style.fontSize = Math.ceil(12 * this.tagAttrList[i].scale/2) + 8 + 'px';
this.tagContent[i].style.fontSize =
Math.ceil((12 * this.tagAttrList[i].scale) / 2) + 2 + "px";
this.tagContent[i].style.filter =
"alpha(opacity=" + 100 * this.tagAttrList[i].alpha + ")";
this.tagContent[i].style.opacity = this.tagAttrList[i].alpha;
}
},
depthSort() {
let aTmp = [];
for (let i = 0; i < this.tagContent.length; i++) {
aTmp.push(this.tagContent[i]);
}
aTmp.sort((item1, item2) => item2.cz - item1.cz);
for (let i = 0; i < aTmp.length; i++) {
aTmp[i].style.zIndex = i;
}
},
sineCosine(a, b, c) {
this.sinA = Math.sin(a * this.dtr);
this.cosA = Math.cos(a * this.dtr);
this.sinB = Math.sin(b * this.dtr);
this.cosB = Math.cos(b * this.dtr);
this.sinC = Math.sin(c * this.dtr);
this.cosC = Math.cos(c * this.dtr);
},
},
};
</script>
<style scoped>
.content {
width: 100%;
height: calc(100vh - 0px);
background-image: url(../assets/liveimg.jpeg);
/* 設置圖片寬、高 */
background-size: 100% 100%;
/*按比例縮放*/
background-repeat: no-repeat;
display: flex;
justify-content: space-around;
}
.cloud-bed {
width: 300px;
height: 200px;
}
.cloud-box {
position: relative;
margin: 20px auto 0px;
width: 100%;
height: 100%;
background: #00000000;
}
.cloud-box span {
position: absolute;
padding: 3px;
top: 0px;
font-weight: bold;
text-decoration: none;
left: 0px;
background-image: linear-gradient(to bottom, red, #fff);
background-clip: text;
color: transparent;
width: 50px;
height: 50px;
border-radius: 50%;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
/* line-height: 50px;
overflow:hidden;
white-space: nowrap;
text-overflow: ellipsis; */
}
</style>