vue中集成文字云效果

<template>
<div>
<div id="tagscloud" class="word-cloud" ref="wordCloud">
<p :style="styleArray[index]" :class="item.color"
v-for="(item, index) in clouds"
@mouseover="mouseoverEvent($event, index)"
@mouseout="mouseoutEvent($event, index)"
@click="doSomething"
:key="index">
<span>{{item.featuretype}}</span>
<span>{{item.featurecontent}}</span>
</p>
</div>
</div>
</template>
<script>
export default {
props: {
clouds:{
type: Array,
default: []
}
},
data(){
return {
  mcList: [], // 存放每个云标签的可视宽度、高度(因vue数据驱动原因,故必须在dom生成之后获取)
  option:{  // 计算所需数值,没太搞明白
    radius: 90,
    d: 200,
    lasta: 1,
    lastb: 1,
    distr: true,
    tspeed: 20,
    size: 200,
    mouseX: 0,
    mouseY: 10,
    howElliptical: 1
  },
  triFunc: {

},
timer: null,
styleArray: [], // 存放每个云标签的css样式
}
},
mounted(){
this.init()
},
beforeDestroy () {  // 组件销毁,清除定时器(什么时候也不对自己再解释)
if(this.timer){
clearTimeout(this.timer)
this.timer = null
}
},
watch: {
clouds() {  // 子组件从父组件中获取值之后不会实时更新,可通过watch监听,做手动异步刷新
if(this.timer){
clearInterval(this.timer)
this.timer = null
}
this.$nextTick(() => {
this.init()
})
}
},
methods: {
doSomething(){
},
mouseoverEvent(e, index){  // 悬浮操作,未做处理(因对计算公式没研究透)
// this.mcList[index].on = true;
},
mouseoutEvent(e, index){  // 离开操作,同上
// this.mcList[index].on = false;
},
setTimer(){
this.timer = setInterval(()=>{
this.update();
}, 50)
},
init(){
this.mcList = []; // 因原插件基于dom操作,所以此处选择清除一下这个(其他部分因它而生,不及时清空,页面帅不过10s)
for(let i=0;i<this.clouds.length;i++){
this.mcList.push({
offsetWidth: this.$refs.wordCloud.children[i].offsetWidth,
offsetHeight: 30
});
}
this.sineCosine( 0,0,0 );
this.positionAll();
this.setTimer();
},
update(){ // 三角函数只是已完全忘记...(大概是在有限范围内取一个立体空间点,并基于z轴做一个透明效果)
let a,b,c = 0;
a = (Math.min(Math.max(-this.option.mouseY, -this.option.size), this.option.size) / this.option.radius) * this.option.tspeed;
b = (-Math.min(Math.max(-this.option.mouseX, -this.option.size), this.option.size) / this.option.radius) * this.option.tspeed;
this.option.lasta = a;
this.option.lastb = b;
if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) {
return;
}
this.sineCosine(a, b, c)
for(let i=0,len=this.mcList.length;i<len;i++){
if(this.mcList[i].on){
continue
}
let rx1 = this.mcList[i].cx;
let ry1 = this.mcList[i].cy * this.triFunc.ca + this.mcList[i].cz * (-this.triFunc.sa);
let rz1 = this.mcList[i].cy * this.triFunc.sa + this.mcList[i].cz * this.triFunc.ca;

let rx2 = rx1 * this.triFunc.cb + rz1 * this.triFunc.sb;
let ry2 = ry1;
let rz2 = rx1 * (-this.triFunc.sb) + rz1 * this.triFunc.cb;

let rx3 = rx2 * this.triFunc.cc + ry2 * (-this.triFunc.sc);
let ry3 = rx2 * this.triFunc.sc + ry2 * this.triFunc.cc;
let rz3 = rz2;

this.mcList[i].cx = rx3;
this.mcList[i].cy = ry3;
this.mcList[i].cz = rz3;
 
let per = this.option.d / (this.option.d + rz3);

this.mcList[i].x = (this.option.howElliptical * rx3 * per) - (this.option.howElliptical * 2);
this.mcList[i].y = ry3 * per;
this.mcList[i].scale = per;
let alpha = per;
alpha = (alpha - 0.6) * (10 / 6);
this.mcList[i].alpha = alpha * alpha * alpha - 0.2;
this.mcList[i].zIndex = Math.ceil(100 - Math.floor(this.mcList[i].cz));
}
this.doPosition()
},
positionAll(){ // 起点的计算
let phi = 0;
let theta = 0;
let max = this.mcList.length;
for (let i = 0; i < max; i++) {
if (this.option.distr) {
phi = Math.acos(-1 + (2 * (i + 1) - 1) / max);
theta = Math.sqrt(max * Math.PI) * phi;
} else {
phi = Math.random() * (Math.PI);
theta = Math.random() * (2 * Math.PI);
}
//坐标变换
this.mcList[i].cx = this.option.radius * Math.cos(theta) * Math.sin(phi)
this.mcList[i].cy = this.option.radius * Math.sin(theta) * Math.sin(phi) * 1.5
this.mcList[i].cz = this.option.radius * Math.cos(phi);
}
},
doPosition(){
let l = this.$refs.wordCloud.offsetWidth / 2;
let t = this.$refs.wordCloud.offsetHeight / 2;
this.styleArray = [];
for (let i=0,len=this.mcList.length; i<len; i++) {
if (this.mcList[i].on) {
continue;
}
this.styleArray.push({
left: this.mcList[i].cx + l - this.mcList[i].offsetWidth / 2 + 'px',
top: this.mcList[i].cy + t - this.mcList[i].offsetHeight / 2 + 'px',
filter: "alpha(opacity=" + 100 * this.mcList[i].alpha + ")",
zIndex: this.mcList[i].zIndex,
opacity: this.mcList[i].alpha,
})
}
},
sineCosine(a, b, c){
let PI = Math.PI / 180;
this.triFunc.sa = Math.sin(a * PI);
this.triFunc.ca = Math.cos(a * PI);
this.triFunc.sb = Math.sin(b * PI);
this.triFunc.cb = Math.cos(b * PI);
this.triFunc.sc = Math.sin(c * PI);
this.triFunc.cc = Math.cos(c * PI);
}
}
}
</script>
<style scoped>
.word-cloud{
position:relative;
margin:0.2rem auto 0;
width: 3rem;
height: 5rem;
text-align:center;
/* border: 1px solid pink; */
}
.word-cloud p{
position:absolute;
top:0px;
left:0px;
color:#fff;
font-family:Arial;
margin:0 10px 15px 0;
width:auto;
height:0.3rem;
line-height: 0.3rem;
text-align:center;
font-size: 0.16rem;
padding:1px 5px;
display:inline-block;
cursor: pointer;
white-space: nowrap;
}
.word-cloud .blue{
color:#00d3ff;
}
.word-cloud .yellow{
color:#f29712;
}
.word-cloud .green{
color:#00af5f;
}
</style>
posted @ 2019-07-19 18:07  安三金  阅读(1048)  评论(0编辑  收藏  举报