实现一个文字颜色随机,字体大小成正态分布,总体呈菱形的排列的标签列表;html
如何实现一个以下图随机排布的标签列表(vue语法):
dome示例: http://39.106.166.212/tagvue
首先假设咱们能够拿到一个标签列表的数组,这里将一步步实现如图效果:算法
经过随机生成一个有效范围内的rgb值便可实现;数组
/*随机颜色rgb*/
const $RandomColor = function(){
var r=Math.floor(Math.random()*256);
var g=Math.floor(Math.random()*256);
var b=Math.floor(Math.random()*256);
return "rgb("+r+','+g+','+b+")";
}
复制代码
为了防止与背景颜色重合也可hsl模式生成,下降明度防止与背景重合;bash
/*随机颜色hsl*/
const $RandomColor2 = function() {
return "hsl(" +
Math.round(Math.random() * 360) + "," +
Math.round(Math.random() * 100) + '%,' +
Math.round(Math.random() * 80) + '%)';
}
复制代码
js中只有随机分布,经过网上查找方法能够经过Box-muller算法将两个随机分布拼接为一个正态分布:
参考:
https://www.cnblogs.com/zztt/p/4025207.html
https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform,写成js为
入参为均值和方差:数据结构
/*利用Box-Muller方法极坐标形式 使用两个均匀分布产生一个正态分布*/
const $Normal = function(mean,sigma){
var u=0.0, v=0.0, w=0.0, c=0.0;
do{
//得到两个(-1,1)的独立随机变量
u=Math.random()*2-1.0;
v=Math.random()*2-1.0;
w=u*u+v*v;
}while(w==0.0||w>=1.0)
c=Math.sqrt((-2*Math.log(w))/w);
return mean+u*c*sigma;
}
复制代码
自此一个随机颜色和大小的tag组件完成app
首先在created中从接口获取到以下一个数组列表,这里咱们不使用最大值参数,默认为剩余的一半;dom
/*
* 随机拆分一个数
* params 总和,个数,最大值 {num}
*/
const $RandomSplit = function(total,nums,max) {
let rest = total;
let result = Array.apply(null, { length: nums })
.map((n, i) => nums - i)
.map(n => {
const v = 1 + Math.floor(Math.random() * (max | rest / n * 2 - 1));
rest -= v;
return v;
});
result[nums - 1] += rest;
return result;
}
复制代码
下图是将44随机拆分为8个数的和,字体
大概思路为先排序,而后每次去两个数分别放置在两端,放置的过程汇总计算两端和,判断大小选择性放置,防止两端排布不均匀ui
/*类正态排序*/
const $NormalSort = function(arr){
var temp = [], i = 0, l = arr.length,leftTo=0,rightTo=0,
sortArr = arr.sort(function(a,b){return b-a}); //先将数组从大到小排列获得 [7,6,5,5,4,3,2,1]
while(arr.length>1){
let a = arr.pop();
let b= arr.pop();
if(leftTo<rightTo){
temp[i] = b;
temp[l-(i+1)] = a;
}else{
temp[i] = b;
temp[l-(i+1)] = a;
}
i++;
}
return temp;
}
复制代码
咱们该方法将上一步的数组从新排序为:
computed:{
tags(){
this.list = $NormalSort($RandomSplit(this.tagList.length,8));//获取数据结构
let temp = this.tagList.sort(function(a,b){ //从新随机排序
return Math.random()>.5 ? -1 : 1;
}).concat();
return this.list.map((v,k) => {//根据list生成数据结构
return temp.splice(0,v);
})
}
},
复制代码
html代码
<div v-for="(item,index) in tags" :key="index" class="tag-body-tags-li">
<Tag v-for="(tag,index) in item" :key="tag.id" :tname="tag.name" ></Tag>
</div> 复制代码