天天看点

#夏日挑战赛# 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

继续阅读