文章      动态     相关文章     最新文章     手机版动态     相关动态     |   首页|会员中心|保存桌面|手机浏览

it9hk2

http://fabua.ksxb.net/comit9hk2/

相关列表
文章列表
  • 暂无文章
推荐文章
联系方式
  • 联系人:赵先生
  • 电话:18903182452
外贸企业网站建设公司/北京搜索关键词优化
发布时间:2024-12-16        浏览次数:1        返回列表

原标题:「React Hook」160行代码实现动态炫酷的可视化图表 - 排行榜

外贸企业网站建设公司/北京搜索关键词优化

某天在逛社区时看到一帖子

react-dynamic-charts — A React Library for Visualizing Dynamic Data

这是一个国外大佬在其公司峰会的代码竞赛中写的一个库:react-dynamic-charts,用于根据动态数据创建动态图表可视化。

它的设计非常灵活,允许你控制内部的每个元素和事件。使用方法也非常简单,其源码也是非常精炼,值得学习。

但因其提供了不少API,不利于理解源码。所以以下实现有所精简

1.准备通用工具函数

1. getRandomColor:随机颜色

constgetRandomColor = =>{

constletters = '0123456789ABCDEF';

letcolor = '#';

for( leti = 0; i < 6; i++) {

color += letters[ Math.floor( Math.random * 16)]

}

returncolor;

};

2. translateY:填充Y轴偏移量

consttranslateY = (value) =>{

return`translateY(${value}px)`;

}

2.使用 useState Hook 生命状态变量

我们开始编写组件DynamicBarChart

constDynamicBarChart = (props) =>{

const[dataQueue, setDataQueue] = useState([]);

const[activeItemIdx, setActiveItemIdx] = useState( 0);

const[highestValue, setHighestValue] = useState( 0);

const[currentValues, setCurrentValues] = useState({});

const[firstRun, setFirstRun] = useState( false);

// 其它代码...

}

1. useState的简单理解

const[属性, 操作属性的方法] = useState(默认值);

2. 变量解析

dataQueue:当前操作的原始数据数组

activeItemIdx: 第几“帧”

highestValue: “榜首”的数据值

currentValues: 经过处理后用于渲染的数据数组

firstRun: 第一次动态渲染时间

3. 内部操作方法和对应useEffect

3.内部操作方法和对应 useEffect

请配合注释食用

// 动态跑起来

functionstart(){

if(activeItemIdx > 1) {

return;

}

nextStep( true);

}

// 对下一帧数据进行处理

functionsetNextValues(){

// 没有帧数时(即已结束),停止渲染

if(!dataQueue[activeItemIdx]) {

iterationTimeoutHolder = null;

return;

}

// 每一帧的数据数组

constroundData = dataQueue[activeItemIdx].values;

constnextValues = {};

lethighestValue = 0;

// 处理数据,用作最后渲染(各种样式,颜色)

roundData.map( (c) =>{

nextValues[c.id] = {

...c,

color: c.color || (currentValues[c.id] || {}).color || getRandomColor

};

if( Math.abs(c.value) > highestValue) {

highestValue = Math.abs(c.value);

}

returnc;

});

// 属性的操作,触发useEffect

setCurrentValues(nextValues);

setHighestValue(highestValue);

setActiveItemIdx(activeItemIdx + 1);

}

// 触发下一步,循环

functionnextStep(firstRun = false){

setFirstRun(firstRun);

setNextValues;

}

对应useEffect

// 取原始数据

useEffect( =>{

setDataQueue(props.data);

}, []);

// 触发动态

useEffect( =>{

start;

}, [dataQueue]);

// 设触发动态间隔

useEffect( =>{

iterationTimeoutHolder = window.setTimeout(nextStep, 1000);

return=>{

if(iterationTimeoutHolder) {

window.clearTimeout(iterationTimeoutHolder);

}

};

}, [activeItemIdx]);

useEffect示例

useEffect( =>{

document.title = `You clicked ${count}times`;

}, [count]); // 仅在 count 更改时更新

为什么要在 effect中返回一个函数

这是 effect可选的清除机制。每个 effect都可以返回一个清除函数。如此可以将添加和移除订阅的逻辑放在一起。

4.整理用于渲染页面的数据

constkeys = Object.keys(currentValues);

const{ barGapSize, barHeight, showTitle } = props;

constmaxValue = highestValue / 0.85;

constsortedCurrentValues = keys.sort( (a, b) =>currentValues[b].value - currentValues[a].value);

constcurrentItem = dataQueue[activeItemIdx - 1] || {};

keys: 每组数据的索引

maxValue: 图表最大宽度

sortedCurrentValues: 对每组数据进行排序,该项影响动态渲染。

currentItem: 每组的原始数据

5.开始渲染页面

大致的逻辑就是

根据不同Props,循环排列后的数据:sortedCurrentValues

计算宽度,返回每项的label、bar、value

根据计算好的高度,触发transform

{

{

showTitle &&

}

{

sortedCurrentValues.map((key, idx) => {

const currentValueData = currentValues[key];

const value = currentValueData.value

let width = Math.abs((value / maxValue * 100));

let widthStr;

if (isNaN(width) || !width) {

widthStr = '1px';

} else {

widthStr = `${width}%`;

}

return (

{

!currentValueData.label

? key

: currentValueData.label

}