實現一個炫酷的隨機標簽排列效果(顏色隨機,大小隨機,成菱形排列的列表)


 

實現一個文字顏色隨機,字體大小成正態分布,整體呈菱形的排列的標簽列表;

如何實現一個如下圖隨機排布的標簽列表(vue語法):
dome示例: http://39.106.166.212/tag

首先假設我們可以拿到一個標簽列表的數組,這里將一步步實現如圖效果:

1、創建tag組件,編寫 隨機顏色方法 和 大小成正態分布的方法 實現顏色和大小隨機的文字標簽;

(1)編寫隨機顏色方法$RandomColor

通過隨機生成一個有效范圍內的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模式生成,降低明度防止與背景重合;

/*隨機顏色hsl*/
const $RandomColor2 = function() {
    return "hsl(" + 
        Math.round(Math.random() * 360) + "," + 
        Math.round(Math.random() * 100) + '%,' + 
        Math.round(Math.random() * 80) + '%)';
}
(2)編寫實現正態分布的方法$Normal

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組件完成

2、將數組隨機排列為菱形(中間多兩頭少的列表)

首先在created中從接口獲取到如下一個數組列表,這里我們不使用最大值參數,默認為剩余的一半;

(1)編寫隨機拆分一個數的方法$RandomSplit獲取一組和為列表長度的數組;
/*
 * 隨機拆分一個數
 * 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個數的和,

(2)編寫$NormalSort方法將上面獲取到的數隨機排列為兩端小中間大數組;

大概思路為先排序,然后每次去兩個數分別放置在兩端,放置的過程匯總計算兩端和,判斷大小選擇性放置,防止兩端排布不均勻

/*類正態排序*/
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;
}

我們該方法將上一步的數組重新排序為:

(3)最后將list數據按照上一步獲取的數據結構從新生成一個可供v-for使用的數據結構;
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> 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM