You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
4.7 KiB
187 lines
4.7 KiB
<template>
|
|
<!-- 词云 -->
|
|
<div class="tag-wrap">
|
|
<p v-for="(item, index) in data" :key="index" class="tag">
|
|
<span class="tag-name">{{ item.name }}</span>
|
|
<span class="tag-value">{{ item.count }}</span>
|
|
</p>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
const colors = [
|
|
"rgba(0,236,255,0.8)",
|
|
"#fcd338",
|
|
"rgba(0,236,255,0.9)",
|
|
"#fcd338",
|
|
"#fcd338",
|
|
"rgba(255,255,255,0.9)",
|
|
"#fff",
|
|
"#fff",
|
|
"#fff",
|
|
"rgba(255,255,255,0.8)",
|
|
];
|
|
const RADIUS = 166; // 3d球的半径
|
|
const FALLLENGTH = 420;
|
|
let CX = null;
|
|
let CY = null;
|
|
|
|
class Tag {
|
|
constructor(el, x, y, z) {
|
|
this.el = el;
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
}
|
|
move() {
|
|
const scale = FALLLENGTH / (FALLLENGTH - this.z);
|
|
const alpha = (this.z + RADIUS) / (2 * RADIUS);
|
|
const left = this.x + CX - this.el.offsetWidth / 2 + 30 + "px"; // 水平偏移
|
|
const top = this.y + CY - this.el.offsetHeight / 2 + 10 + "px"; // 竖直偏移
|
|
this.el.style.opacity = alpha;
|
|
this.el.style.zIndex = parseInt(scale * 100);
|
|
this.el.style.transform = `translate(${left},${top}) scale(${scale})`;
|
|
}
|
|
}
|
|
import { keyWords } from "@/api/common";
|
|
import { wordCloud } from "@/api/publicOpinion";
|
|
|
|
export default {
|
|
props: {},
|
|
data() {
|
|
return {
|
|
tagList: [],
|
|
data: [
|
|
{ name: "太仓市委", count: 200 },
|
|
{ name: "“交通先行”抢位长三角", count: 400 },
|
|
{ name: "太仓速度", count: 600 },
|
|
{ name: "最具幸福感城市", count: 2000 },
|
|
{ name: "振翅高飞", count: 350 },
|
|
{ name: "娄城防疫", count: 666 },
|
|
{ name: "城市更新", count: 899 },
|
|
{ name: "争当猛虎尖兵", count: 899 },
|
|
{ name: "家在太仓 情暖娄城", count: 899 },
|
|
{ name: "国土空间全域整治", count: 899 },
|
|
],
|
|
};
|
|
},
|
|
created() {
|
|
},
|
|
mounted() {
|
|
this.init();
|
|
this.animate();
|
|
},
|
|
methods: {
|
|
getDataList() {
|
|
wordCloud().then((res) => {
|
|
res.data.forEach((value) => {
|
|
this.data.push({
|
|
name: this.$filterDict("tc_cy_type", value.type),
|
|
count: 3,
|
|
});
|
|
});
|
|
});
|
|
},
|
|
init() {
|
|
const tags = document.querySelectorAll(".tag");
|
|
const wrap = document.querySelector(".tag-wrap");
|
|
|
|
const len = tags.length;
|
|
const valueList = Array.from(new Set(this.data.map((i) => i.count)));
|
|
const min = Math.min(...valueList);
|
|
CX = wrap.offsetWidth / 2;
|
|
CY = wrap.offsetHeight / 2;
|
|
|
|
tags.forEach((i, index) => {
|
|
const fontScale = (this.data[index].count / min) * 16;
|
|
i.style.fontSize = fontScale > 35 ? "35px" : fontScale + "px";
|
|
i.style.color = colors[parseInt(Math.random() * 10)];
|
|
|
|
const k = -1 + (2 * (index + 1) - 1) / len;
|
|
const a = Math.acos(k);
|
|
const b = a * Math.sqrt(len * Math.PI);
|
|
const x = RADIUS * 1.15 * Math.sin(a) * Math.cos(b);
|
|
const y = RADIUS * Math.sin(a) * Math.sin(b);
|
|
const z = RADIUS * Math.cos(a);
|
|
const tag = new Tag(i, x, y, z);
|
|
this.tagList.push(tag);
|
|
});
|
|
},
|
|
rotateX() {
|
|
const angleX = Math.PI / 300;
|
|
const cos = Math.cos(angleX);
|
|
const sin = Math.sin(angleX);
|
|
this.tagList.forEach((i) => {
|
|
const y1 = i.y * cos - i.z * sin;
|
|
const z1 = i.z * cos + i.y * sin;
|
|
i.y = y1;
|
|
i.z = z1;
|
|
});
|
|
},
|
|
rotateY() {
|
|
const angleY = Math.PI / 500;
|
|
const cos = Math.cos(angleY);
|
|
const sin = Math.sin(angleY);
|
|
this.tagList.forEach((i) => {
|
|
const x1 = i.x * cos - i.z * sin;
|
|
const z1 = i.z * cos + i.x * sin;
|
|
i.x = x1;
|
|
i.z = z1;
|
|
});
|
|
},
|
|
animate() {
|
|
this.rotateX();
|
|
this.rotateY();
|
|
this.tagList.forEach((i) => {
|
|
i.move();
|
|
});
|
|
requestAnimationFrame(this.animate);
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
.tag-wrap {
|
|
position: relative;
|
|
width: 100%;
|
|
height: 356px;
|
|
background-size: 100% 100%;
|
|
background: url("~@/assets/sentimeent/icon-正面.png") no-repeat center;
|
|
margin-top: 20px;
|
|
.tag {
|
|
opacity: 0;
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
text-decoration: none;
|
|
font-size: 34px;
|
|
cursor: pointer;
|
|
will-change: transform;
|
|
color: #fff;
|
|
span {
|
|
display: inline-block;
|
|
}
|
|
.tag-value {
|
|
opacity: 0;
|
|
height: 35px;
|
|
padding: 0 30px 0 20px;
|
|
color: #f6f600;
|
|
line-height: 35px;
|
|
margin-left: 5px;
|
|
visibility: middle;
|
|
font-size: 34px;
|
|
transition: all 0.2s;
|
|
background: linear-gradient(
|
|
90deg,
|
|
rgba(216, 255, 0, 0.7) 0%,
|
|
rgba(58, 51, 255, 0) 100%
|
|
);
|
|
}
|
|
&:hover {
|
|
.tag-value {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|