|
@@ -0,0 +1,302 @@
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <el-dialog title="词云" :visible.sync="dialogVisibleWordCloud" :append-to-body="true" width="650px"
|
|
|
+ :before-close="handleClose" class="dialog_diy dialog_diy3">
|
|
|
+ <div class="wordCloud__tagBall" :style="{ width: `500px`, height: `500px` }" @mouseenter="stop"
|
|
|
+ @mouseleave="start">
|
|
|
+ <span class="wordCloud__tag" v-for="(item, index) of data" :key="index"
|
|
|
+ :style="{ color: color[index % color.length], ...contentEle[index].style }"
|
|
|
+ :title="item.name ">{{ item.name }}</span>
|
|
|
+ <!-- + item.value -->
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+
|
|
|
+<script>
|
|
|
+export default {
|
|
|
+ name: 'cloudWork',
|
|
|
+ props: {
|
|
|
+ dialogVisibleWordCloud: {
|
|
|
+ type: Boolean,
|
|
|
+ },
|
|
|
+ // 测试数据
|
|
|
+ data: {
|
|
|
+ type: Array,
|
|
|
+ default: () => [
|
|
|
+ // {
|
|
|
+ // name: '安氏一类',
|
|
|
+ // value: 100
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: '安氏二类',
|
|
|
+ // value: 30
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: '安氏三类',
|
|
|
+ // value: 30
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: '安氏四类',
|
|
|
+ // value: 30
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: '安氏五类',
|
|
|
+ // value: 30
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: '安氏一类',
|
|
|
+ // value: 30
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: '安氏二类',
|
|
|
+ // value: 30
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: '安氏三类',
|
|
|
+ // value: 30
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: '安氏四类',
|
|
|
+ // value: 30
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: '安氏五类',
|
|
|
+ // value: 30
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: '安氏一类',
|
|
|
+ // value: 30
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: '安氏二类',
|
|
|
+ // value: 30
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: '安氏三类',
|
|
|
+ // value: 30
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: '安氏四类',
|
|
|
+ // value: 30
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: '安氏五类',
|
|
|
+ // value: 30
|
|
|
+ // }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data: () => ({
|
|
|
+ color: ['#2D4DB6', '#04B67C', '#D1AF07', '#E27914', '#CB4A4D', '#B02690'],
|
|
|
+ contentEle: [],
|
|
|
+ direction: '-1',
|
|
|
+ speed: 400,
|
|
|
+ animateID: null,
|
|
|
+ width:500,
|
|
|
+ height:500,
|
|
|
+ }),
|
|
|
+ watch: {
|
|
|
+ dialogVisibleWordCloud(newValue, oldValue) {
|
|
|
+ if(newValue){
|
|
|
+ this.contentEle = this.data.map(() => ({
|
|
|
+ x: 0,
|
|
|
+ y: 0,
|
|
|
+ z: 0,
|
|
|
+ style: {}
|
|
|
+ }));
|
|
|
+ this.innit();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ // this.contentEle = this.data.map(() => ({
|
|
|
+ // x: 0,
|
|
|
+ // y: 0,
|
|
|
+ // z: 0,
|
|
|
+ // style: {}
|
|
|
+ // }));
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.innit();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ handleClose(done) {
|
|
|
+ this.close();
|
|
|
+ // done()
|
|
|
+ },
|
|
|
+ close() {
|
|
|
+ this.$emit("update:dialogVisibleWordCloud", false)
|
|
|
+ },
|
|
|
+ innit() {
|
|
|
+ const RADIUSX = (this.width - 50) / 2;
|
|
|
+ const RADIUSY = (this.height - 50) / 2;
|
|
|
+ this.contentEle = [];
|
|
|
+ for (let i = 0; i < this.data.length; i += 1) {
|
|
|
+ const k = -1 + (2 * (i + 1) - 1) / this.data.length;
|
|
|
+ const a = Math.acos(k);
|
|
|
+ const b = a * Math.sqrt(this.data.length * Math.PI);
|
|
|
+ const x = RADIUSX * Math.sin(a) * Math.cos(b);
|
|
|
+ const y = RADIUSY * Math.sin(a) * Math.sin(b);
|
|
|
+ const z = RADIUSX * Math.cos(a);
|
|
|
+ const singleEle = {
|
|
|
+ x,
|
|
|
+ y,
|
|
|
+ z,
|
|
|
+ style: {}
|
|
|
+ };
|
|
|
+ this.contentEle.push(singleEle);
|
|
|
+ }
|
|
|
+ this.animate();
|
|
|
+ },
|
|
|
+ animate() {
|
|
|
+ this.rotateX();
|
|
|
+ this.rotateY();
|
|
|
+ this.move();
|
|
|
+ this.animateID = window.requestAnimationFrame(this.animate);
|
|
|
+ },
|
|
|
+ rotateX() {
|
|
|
+ const angleX = ['-1', '1'].includes(this.direction)
|
|
|
+ ? Math.PI / Infinity
|
|
|
+ : Math.PI / ((Number(this.direction) / 2) * Number(this.speed));
|
|
|
+ const cos = Math.cos(angleX);
|
|
|
+ const sin = Math.sin(angleX);
|
|
|
+
|
|
|
+ this.contentEle = this.contentEle.map((t) => {
|
|
|
+ const y1 = t.y * cos - t.z * sin;
|
|
|
+ const z1 = t.z * cos + t.y * sin;
|
|
|
+ return {
|
|
|
+ ...t,
|
|
|
+ y: y1,
|
|
|
+ z: z1
|
|
|
+ };
|
|
|
+ });
|
|
|
+ },
|
|
|
+ rotateY() {
|
|
|
+ const angleY = ['-2', '2'].includes(this.direction)
|
|
|
+ ? Math.PI / Infinity
|
|
|
+ : Math.PI / (Number(this.direction) * Number(this.speed));
|
|
|
+ const cos = Math.cos(angleY);
|
|
|
+ const sin = Math.sin(angleY);
|
|
|
+ this.contentEle = this.contentEle.map((t) => {
|
|
|
+ const x1 = t.x * cos - t.z * sin;
|
|
|
+ const z1 = t.z * cos + t.x * sin;
|
|
|
+ return {
|
|
|
+ ...t,
|
|
|
+ x: x1,
|
|
|
+ z: z1
|
|
|
+ };
|
|
|
+ });
|
|
|
+ },
|
|
|
+ move() {
|
|
|
+ const CX = this.width / 2;
|
|
|
+ const CY = this.height / 2;
|
|
|
+ this.contentEle = this.contentEle.map((singleEle) => {
|
|
|
+ const { x, y, z } = singleEle;
|
|
|
+ const fallLength = 500;
|
|
|
+ const RADIUS = (this.width - 50) / 2;
|
|
|
+ const scale = fallLength / (fallLength - z);
|
|
|
+ const alpha = (z + RADIUS) / (2 * RADIUS);
|
|
|
+ const left = `${x + CX - 15}px`;
|
|
|
+ const top = `${y + CY - 15}px`;
|
|
|
+ const transform = `translate(${left}, ${top}) scale(${scale})`;
|
|
|
+ const style = {
|
|
|
+ ...singleEle.style,
|
|
|
+ opacity: alpha + 0.5,
|
|
|
+ zIndex: parseInt(scale * 100, 10),
|
|
|
+ transform
|
|
|
+ };
|
|
|
+ return {
|
|
|
+ x,
|
|
|
+ y,
|
|
|
+ z,
|
|
|
+ style
|
|
|
+ };
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 鼠标移入暂停
|
|
|
+ stop() {
|
|
|
+ window.cancelAnimationFrame(this.animateID);
|
|
|
+ },
|
|
|
+ // 鼠标离开恢复
|
|
|
+ start() {
|
|
|
+ this.animate();
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+@media screen and (max-width: 1280px) {
|
|
|
+ .dialog_diy3>>>.el-dialog {
|
|
|
+ width: 100% !important;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.dialog_diy>>>.el-dialog {
|
|
|
+ margin-top: 10vh !important;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog_diy>>>.el-dialog__header {
|
|
|
+ background: #454545 !important;
|
|
|
+ padding: 15px 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog_diy>>>.el-dialog__title,
|
|
|
+.dialog_diy1>>>.el-dialog__title {
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog_diy>>>.el-dialog__headerbtn {
|
|
|
+ top: 19px;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog_diy>>>.el-dialog__headerbtn .el-dialog__close {
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog_diy>>>.el-dialog__headerbtn .el-dialog__close:hover {
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog_diy1>>>.el-dialog__body {
|
|
|
+ padding: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog_diy>>>.el-dialog__body,
|
|
|
+.dialog_diy>>>.el-dialog__footer {
|
|
|
+ background: #fafafa;
|
|
|
+}
|
|
|
+
|
|
|
+button {
|
|
|
+ margin: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.wordCloud__tagBall {
|
|
|
+ margin: 0px auto;
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+
|
|
|
+.wordCloud__tag {
|
|
|
+ display: block;
|
|
|
+ position: absolute;
|
|
|
+ left: 0px;
|
|
|
+ top: 0px;
|
|
|
+ color: green;
|
|
|
+ text-decoration: none;
|
|
|
+ font-size: 15px;
|
|
|
+ font-family: '微软雅黑';
|
|
|
+ font-weight: bold;
|
|
|
+}
|
|
|
+
|
|
|
+.wordCloud__tag :hover {
|
|
|
+ color: red;
|
|
|
+}
|
|
|
+
|
|
|
+.wordCloud__home {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+</style>
|