Jelajahi Sumber

动态词云

liyongli 4 tahun lalu
induk
melakukan
e5b10c5fdb
2 mengubah file dengan 413 tambahan dan 20 penghapusan
  1. 210 20
      src/view/index/index.vue
  2. 203 0
      src/view/test.html

+ 210 - 20
src/view/index/index.vue

@@ -140,17 +140,31 @@
       :height="client.height"
     ></canvas>
     <div v-if="baseData.word_cloud_url" class="title">词云</div>
-    <van-image v-if="baseData.word_cloud_url" :src="baseData.word_cloud_url">
+    <!-- <van-image v-if="baseData.word_cloud_url" :src="baseData.word_cloud_url">
       <template v-slot:loading>
         <van-loading type="spinner" size="20" />
       </template>
-    </van-image>
-    <!-- <canvas
-      id="keyCloud"
-      class="canvas"
-      :width="client.width"
-      :height="client.height"
-    ></canvas> -->
+    </van-image> -->
+    <div
+      ref="div1"
+      id="div1"
+      class="wordCloud__tagBall"
+      :style="{ width: client.width + 'px', height: client.height + 'px' }"
+    >
+      <span
+        v-for="(item, i) in contentEle"
+        :key="item.name"
+        class="wordCloud__tag"
+        :style="{
+          color: color[i % color.length],
+          opacity: item.style.opacity,
+          transform: item.style.transform,
+          zIndex: item.style.zIndex,
+          fontSize: item.style.fontSize + 'px'
+        }"
+        >{{ item.name }}</span
+      >
+    </div>
     <div v-if="douyin.length" class="title">抖音-评论排行</div>
     <canvas
       v-if="douyin.length"
@@ -264,6 +278,28 @@
   border: 1px solid #1989fa;
   color: #1989fa;
 }
+
+.wordCloud__tagBall {
+  margin: 50px 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;
+  cursor: pointer;
+}
+
+.wordCloud__tag:hover {
+  color: red !important;
+}
 </style>
 
 <script>
@@ -271,8 +307,8 @@ import { getAllPlatform, getPlatform, getList } from "@/api/getList.js";
 import filters from "@/utils/filters/index";
 import live from "@/view/index/components/live/index.vue";
 import {
-  Image as vanImage,
-  Loading as vanLoading,
+  // Image as vanImage,
+  // Loading as vanLoading,
   Popup as vanPopup,
   Button as vanButton,
   Dialog,
@@ -287,8 +323,8 @@ import btnGroup from "./components/btnGroup/index";
 
 export default {
   components: {
-    vanImage,
-    vanLoading,
+    // vanImage,
+    // vanLoading,
     vanPopup,
     vanButton,
     btnGroup,
@@ -315,12 +351,71 @@ export default {
       read: [],
       yangshi: [],
       cakeList: [],
+      direction: "-2", // 横向顺时针=-1;横向逆时针=1;纵向顺时针=-2;纵向逆时针=2
       show: false,
-      value1: 0,
-      option1: [
-        { text: "全部商品", value: 0 },
-        { text: "新款商品", value: 1 },
-        { text: "活动商品", value: 2 },
+      contentEle: [],
+      speed: 3000,
+      color: ["#2D4DB6", "#04B67C", "#D1AF07", "#E27914", "#CB4A4D", "#B02690"],
+      minFontSize: 12,
+      maxFontSize: 18,
+      list: [
+        
+        {
+          name: "云图",
+          value: 1000,
+        },
+        {
+          name: "是个啥",
+          value: 1000,
+        },
+        {
+          name: "他啥都不是",
+          value: 1000,
+        },
+        {
+          name: "他就是词云",
+          value: 1000,
+        },
+        {
+          name: "就是他呆子",
+          value: 1000,
+        },
+        {
+          name: "傻子和疯子",
+          value: 1000,
+        },
+        {
+          name: "营养快线",
+          value: 1000,
+        },
+        {
+          name: "哈哈哈到家",
+          value: 1000,
+        },
+        {
+          name: "瑞士军刀",
+          value: 1000,
+        },
+        {
+          name: "DW情侣对表",
+          value: 1000,
+        },
+        {
+          name: "清风抽纸",
+          value: 1000,
+        },
+        {
+          name: "这一刻更清晰",
+          value: 1000,
+        },
+        {
+          name: "债券评级",
+          value: 1000,
+        },
+        {
+          name: "呵呵旧宫style",
+          value: 1000,
+        },
       ],
     };
   },
@@ -458,6 +553,7 @@ export default {
           this.me.length && this.line(this.me, "value", "weiboMe");
           this.read.length && this.line(this.read, "value", "weiboRead");
           this.ori.length && this.line(this.ori, "value", "weiboOri");
+          this.cloud();
         });
       });
     },
@@ -673,16 +769,17 @@ export default {
       this.initCanvas[id] = chart;
     },
     showDetail(key) {
-      let val = "", nameText = "";
+      let val = "",
+        nameText = "";
       for (let i = 0; i < this.$parent.$parent.config.length; i++) {
         const v = this.$parent.$parent.config[i];
-        if(key !== v.name || v.topic_id !== this.baseData.topic_id) continue;
+        if (key !== v.name || v.topic_id !== this.baseData.topic_id) continue;
         val = v.value;
         nameText = v.content_desc;
         break;
       }
       Dialog.alert({
-        title: this.$route.query.title + '-' + nameText,
+        title: this.$route.query.title + "-" + nameText,
         message: val,
         confirmButtonColor: "#1989fa",
         messageAlign: "left",
@@ -723,6 +820,99 @@ export default {
       this[obj.type].length && this.line(this[obj.type], "value", id);
       call && call();
     },
+    cloud() {
+      const RADIUSX = (this.client.width - 50) / 2;
+      const RADIUSY = (this.client.height - 50) / 2;
+      let contentEle = [];
+      for (let i = 0; i < this.list.length; i += 1) {
+        const k = -1 + (2 * (i + 1) - 1) / this.list.length;
+        const a = Math.acos(k);
+        const b = a * Math.sqrt(this.list.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 fotnS = (this.maxFontSize - this.minFontSize) * Math.random();
+        const singleEle = {
+          name: this.list[i].name,
+          value: this.list[i].value,
+          x,
+          y,
+          z,
+          style: {
+            fontSize: fotnS + this.minFontSize,
+          },
+        };
+        contentEle.push(singleEle);
+      }
+      this.contentEle = contentEle;
+      this.animate();
+    },
+    animate() {
+      this.rotateX();
+      this.rotateY();
+      this.move();
+      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.client.width / 2;
+      const CY = this.client.height / 2;
+      this.contentEle = this.contentEle.map(singleEle => {
+        const { x, y, z } = singleEle;
+        const fallLength = 500;
+        const RADIUS = (this.client.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 {
+          name: singleEle.name,
+          value: singleEle.value,
+          x,
+          y,
+          z,
+          style,
+        };
+      });
+    },
   },
 };
 </script>

+ 203 - 0
src/view/test.html

@@ -0,0 +1,203 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <meta charset="utf-8" />
+  <title>3D词云</title>
+  <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
+  <style>
+    .wordCloud__tagBall {
+      margin: 50px 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;
+      cursor: pointer;
+    }
+
+    .wordCloud__tag:hover {
+      color: red !important;
+    }
+
+    .wordCloud__home {
+      display: flex;
+      justify-content: center;
+    }
+  </style>
+</head>
+
+<body>
+  <div id="main">
+    <div class="wordCloud__tagBall" style="width: 500px; height: 500px ">
+    </div>
+    <div class="wordCloud__home">
+      <button class="btn0" type="button">降低速度</button>
+      <button class="btn1" type="button">横向顺时针</button>
+      <button class="btn2" type="button">横向逆时针</button>
+      <button class="btn3" type="button">纵向顺时针</button>
+      <button class="btn4" type="button">纵向逆时针</button>
+      <button class="btn5" type="button">增加速度</button>
+    </div>
+  </div>
+  <script>
+    $(function () {
+      var myval
+      var width = 500
+      var height = 500
+      var contentEle = []
+      var data = ['云图', '是个啥', '他啥都不是', '他就是词云', '就是他呆子', '傻子和疯子', '营养快线', '哈哈哈到家', '瑞士军刀', 'DW情侣对表', '清风抽纸', '这一刻更清晰', '债券评级', '呵呵旧宫style', '云图', '是个啥', '他啥都不是', '他就是词云', '就是他呆子', '傻子和疯子', '营养快线', '哈哈哈到家', '瑞士军刀', 'DW情侣对表', '清风抽纸', '这一刻更清晰', '债券评级', '呵呵旧宫style']
+      var direction = '-1'
+      var speed = 3000
+      var color = ['#2D4DB6', '#04B67C', '#D1AF07', '#E27914', '#CB4A4D', '#B02690']
+      function innit() {
+        const RADIUSX = (width - 50) / 2
+        const RADIUSY = (height - 50) / 2
+        contentEle = []
+        for (let i = 0; i < data.length; i += 1) {
+          const k = -1 + (2 * (i + 1) - 1) / data.length
+          const a = Math.acos(k)
+          const b = a * Math.sqrt(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: {},
+          }
+          contentEle.push(singleEle)
+        }
+        animate()
+      }
+      function animate() {
+        rotateX()
+        rotateY()
+        move()
+        // window.requestAnimationFrame(animate)
+      }
+      function rotateX() {
+        const angleX = ['-1', '1'].includes(direction)
+          ? Math.PI / Infinity
+          : Math.PI / ((Number(direction) / 2) * Number(speed))
+        const cos = Math.cos(angleX)
+        const sin = Math.sin(angleX)
+        contentEle = 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,
+          }
+        })
+      }
+      function rotateY() {
+        const angleY = ['-2', '2'].includes(direction)
+          ? Math.PI / Infinity
+          : Math.PI / (Number(direction) * Number(speed))
+        const cos = Math.cos(angleY)
+        const sin = Math.sin(angleY)
+        contentEle = 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,
+          }
+        })
+      }
+      function move() {
+        const CX = width / 2
+        const CY = height / 2
+        contentEle = contentEle.map((singleEle) => {
+          const { x, y, z } = singleEle
+          const fallLength = 500
+          const RADIUS = (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,
+          }
+        })
+      }
+      function handleRotate(value) {
+        direction = value
+      }
+      function handleSpeed(value) {
+        const speedObj = {
+          fast: -50,
+          slow: 50,
+        }
+        speed += speedObj[value]
+        if (speed === 0) {
+          speed = 50
+        }
+      }
+      function init() {
+        var html_ = ''
+        for (var i = 0; i < data.length; i++) {
+          let color_ = color[i % color.length]
+          html_ += '<span class="wordCloud__tag" style="color:' + color_ + ';opacity:' + contentEle[i].style.opacity + ';transform:' + contentEle[i].style.transform + ';zIndex:' + contentEle[i].style.zIndex + '">' + data[i] + '</span>'
+        }
+        $('.wordCloud__tagBall').html(html_)
+      }
+
+
+      innit()
+    //   myval = setInterval(() => {
+        init()
+    //   }, 10)
+
+      //横向顺时针
+      $('.btn1').on('click', function () {
+        handleRotate('-1')
+      })
+      //横向逆时针
+      $('.btn2').on('click', function () {
+        handleRotate('1')
+      })
+      //纵向顺时针
+      $('.btn3').on('click', function () {
+        handleRotate('-2')
+      })
+      //纵向逆时针
+      $('.btn4').on('click', function () {
+        handleRotate('2')
+      })
+      //增加速度
+      $('.btn5').on('click', function () {
+        handleSpeed('fast')
+      })
+      //增加速度
+      $('.btn0').on('click', function () {
+        handleSpeed('slow')
+      })
+
+    })
+  </script>
+</body>
+
+</html>