天天看點

#夏日挑戰賽# HarmonyOS 實作一個文字雲元件

本文正在參加星光計劃3.0–夏日挑戰賽

前言

本篇文章分享一下我實作的一個文字雲元件,實作原理很簡單,通過文字出現的頻率,來動态生成文字大小,最後渲染即可

介紹

文字雲,可以根據文字出現的頻率,來展示不同的文字大小,并随機生成顔色

效果展示

#夏日挑戰賽# HarmonyOS 實作一個文字雲元件

使用

參數名稱 參數描述 參數類型 預設值
list 需要展示的資料 Array
width 元件寬度 Number 400
height 元件高度 Number 500
temp 步頻 Number 5
font-max 最大文字大小 Number 80
font-min 最小文字大小 Number 25
解釋一下:

步頻

,就是文字擴大的比例。

原理分析

1.随機顔色

在效果圖中我們可以看到,每個詞的顔色是不一樣的,這是通過随機顔色實作的

我們知道,顔色可以通過rgb擷取,rgb中有三個參數rgb(xxx,xxx,xxx),通過三個參數決定顔色,是以我們可以通過随機數來生成這三個參數

參數取值範圍: 0~255

getColor()

let r = Math.floor(Math.random() * 255);
        let g = Math.floor(Math.random() * 255);
        let b = Math.floor(Math.random() * 255);
        return "rgb(" + r + "," + g + "," + b + ")";
           
該方法用于擷取顔色,并且是通過随機數擷取,最後通過字元拼接得到一個完整的

rgb(xxx,xxx,xxx)

并傳回

2.文字大小

文字大小是用過temp(步頻)和num(詞頻)兩個參數控制的,num是固定的,步頻的可以使用者自定義。此外,為了防止詞頻過大,造成文字過大或者過小,影響使用者體驗,是以,增加最大文字和最小文字

getSize(num)

getSize (num) {
        let fontSize = num * this.temp;
        if(fontSize>this.fontMax) fontSize = this.fontMax
        if (fontSize<this.fontMin) fontSize = this.fontMin
        console.log(this.fontMin)
        return fontSize +'px' ;
    }
           

3.資料整合

通過循環,将上面擷取到的文字大小、文字顔色,push到list中的每一項中,此時我們的資料就有文字對應的樣式了

展示資料的時候我希望能将位置打亂,是以需要對數組随機排序,方法有很多,我是通過sort()方法來實作的

sort(a,b)為一個方法時,如果傳回值<0,則a會排到b前面,傳回值>0,則a會排到b後面
根據這個性質,我們隻需要随機生成傳回值,使它在正負數區間内即可
           

getList()

getList () {
        this.list.forEach(item => {
            let temp = item;
            temp.size = this.getSize(item.num)
            temp.color = this.getColor()
            this.textList.push(temp)
        })
        // 将數組順序打亂
        this.textList.sort(() => {
            return (Math.random()-0.5);
        });
    }
           

4.元件調用

元件調用這裡我就不介紹了,詳細使用可以看官方文檔。

這裡傳入的參數中list的格式,必須有text(文字)和num(頻率),類似這樣

[{text:'文本1',num:10}]

<element name='comp' src='../../common/component/wordCloud/index.hml'></element>
<div class="container">
    <comp list="{{userlist}}" width="400" height="500" temp="6" font-max="100" font-min="20"></comp>
</div>
           
小提示:我遇到的一些小問題,

fontMax

要用

-

分開,寫成

font-max

,不然傳不過去...

完整代碼

index.js

// @ts-nocheck
// comp.js
export default {
    props: {
        // 需要展示的資料 格式 :[{text:'文本1',num:10}]
        list: {
            type: Array,
            default: []
        },
        width: {
            type: Number,
            default: 400
        },
        height: {
            type: Number,
            default: 500
        },
        // 接收步頻
        temp: {
            type: Number,
            default: 5
        },
        fontMax:{
            type:Number,
            default:80,
        },
        fontMin:{
            type:Number,
            default:25
        }
    },
    onInit(){
        this.getList()
    },
    data() {
        return {
            textList: []
        };
    },
    //随機擷取顔色
    getColor () {
        let r = Math.floor(Math.random() * 255);
        let g = Math.floor(Math.random() * 255);
        let b = Math.floor(Math.random() * 255);
        return "rgb(" + r + "," + g + "," + b + ")";
    },
    //計算文字大小。通過(詞頻*步頻)計算字型大小
    getSize (num) {
        let fontSize = num * this.temp;
        if(fontSize>this.fontMax) fontSize = this.fontMax
        if (fontSize<this.fontMin) fontSize = this.fontMin
        console.log(this.fontMin)
        return fontSize+'px' ;
    },
    //将使用者的資料存儲到容器中
    getList () {
        this.list.forEach(item => {
            let temp = item;
            temp.size = this.getSize(item.num)
            temp.color = this.getColor()
            this.textList.push(temp)
        })
        // 将數組順序打亂
        this.textList.sort(() => {
            return (Math.random()-0.5);
        });
    }
}
           

index.hml

<div class="container"
         style="height:{{height}}px;width:{{width}}px;">
    <text class="box">
        <span for="{{textList}}"
              style="font-size:{{$item.size}}px;;color: {{$item.color}};">
            {{ $item.name }}
        </span>
    </text>
</div>
           

index.css

.container {
    border: 1px solid #ffcc00;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}
.box{
    margin: 10px;
}
           

補充

上篇文章實作了一個進度條元件progress,但是由于考試周,沒什麼時間實作,如何就留下了一些拓展思路。

最後實作完給大家看看最終效果

#夏日挑戰賽# HarmonyOS 實作一個文字雲元件

總結📝

不足點:樣式排版不是特别好,加上動畫效果應該會好看點

最後,通過自定義元件,加深對

HarmonyOS

的開發,共建鴻蒙生态!

附件連結:https://ost.51cto.com/resource/2169

繼續閱讀