In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-21 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)06/02 Report--
Prepare general tool functions
GetRandomColor: random color
Const getRandomColor = () = > {
Const letters = '0123456789ABCDEF'
Let color ='#'
For (let I = 0; I
< 6; i++) { color += letters[Math.floor(Math.random() * 16)] } return color; }; translateY:填充Y轴偏移量 const translateY = (value) =>{
Return translateY (${value} px)
}
Declare state variables using useState Hook
Let's start writing component DynamicBarChart
Const DynamicBarChart = (props) = > {
Const [dataQueue, setDataQueue] = useState ([])
Const [activeItemIdx, setActiveItemIdx] = useState (0)
Const [highestValue, setHighestValue] = useState (0)
Const [currentValues, setCurrentValues] = useState ({})
Const [firstRun, setFirstRun] = useState (false)
/ other code.
}
Simple understanding of useState:
Const [attribute, method for manipulating attributes] = useState (default); variable parsing
DataQueue: the raw data array of the current operation
ActiveItemIdx: the "frame"
HighestValue: the data value of "number one"
CurrentValues: an array of processed data for rendering
FirstRun: first dynamic rendering time
Internal operation method and corresponding useEffect
Please use it with comments:
/ / run dynamically ~
Function start () {
If (activeItemIdx > 1) {
Return
}
NextStep (true)
}
/ / A pair of data to be processed in the next frame
Function setNextValues () {
/ / stop rendering when there is no number of frames (that is, it is over)
If (! dataQueue [activeItemIdx]) {
IterationTimeoutHolder = null
Return
}
/ / data array for each frame
Const roundData = dataQueue [activeItemIdx] .values
Const nextValues = {}
Let highestValue = 0
/ / process data for final rendering (various styles, colors)
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);} return c
});
/ / the operation of the attribute, which triggers useEffect
SetCurrentValues (nextValues)
SetHighestValue (highestValue)
SetActiveItemIdx (activeItemIdx + 1)
}
/ / trigger the next step, cycle
Function nextStep (firstRun = false) {
SetFirstRun (firstRun)
SetNextValues ()
}
Corresponding useEffect:
/ / fetch the original data
UseEffect () = > {
SetDataQueue (props.data)
}, [])
/ / trigger dynamics
UseEffect () = > {
Start ()
}, [dataQueue])
/ / set the trigger dynamic interval
UseEffect () = > {
IterationTimeoutHolder = window.setTimeout (nextStep, 1000)
Return () = > {
If (iterationTimeoutHolder) {
Window.clearTimeout (iterationTimeoutHolder)
}
}
}, [activeItemIdx])
UseEffect example:
UseEffect () = > {
Document.title = You clicked ${count} times
}, [count]); / / update only when count changes
Why return a function in effect?
This is the optional cleanup mechanism for effect. Each effect can return a cleanup function. This puts the logic of adding and removing subscriptions together.
Collate the data used to render the page
Const keys = Object.keys (currentValues)
Const {barGapSize, barHeight, showTitle} = props
Const maxValue = highestValue / 0.85
Const sortedCurrentValues = keys.sort ((a, b) = > currentValues.value-currentValues.value)
Const currentItem = dataQueue [activeItemIdx-1] | | {}
Keys: the index of each set of data
MaxValue: maximum width of chart
SortedCurrentValues: sorts each set of data, which affects dynamic rendering.
CurrentItem: raw data for each group
Start rendering the page
The general logic is:
According to different Props, the data after circular arrangement: sortedCurrentValues
Calculate the width and return the label, bar, value of each item
Based on the calculated height, transform is triggered.
{
{
ShowTitle & &
{currentItem.name}
}
{
SortedCurrentValues.map ((key, idx) = > {
Const currentValueData = currentValues [key]
Const value = currentValueData.value
Let width = Math.abs ((value / maxValue))
Let widthStr
If (isNaN (width) | |! width) {
WidthStr = '1px'
} else {
WidthStr = ${width}%
}
Return ({! currentValueData.label? Key: currentValueData.label} {currentValueData.value});)}
}
Define regular propTypes and defaultProps
DynamicBarChart.propTypes = {
ShowTitle: PropTypes.bool
IterationTimeout: PropTypes.number
Data: PropTypes.array
StartRunningTimeout: PropTypes.number
BarHeight: PropTypes.number
BarGapSize: PropTypes.number
Baseline: PropTypes.number
}
DynamicBarChart.defaultProps = {
ShowTitle: true
IterationTimeout: 200
Data: []
StartRunningTimeout: 0
BarHeight: 50
BarGapSize: 20
Baseline: null
}
Export {
DynamicBarChart
}
How to use
Import React, {Component} from "react"
Import {DynamicBarChart} from ". / DynamicBarChart"
Import helpers from ". / helpers"
Import mocks from ". / mocks"
Import "react-dynamic-charts/dist/index.css"
Export default class App extends Component {
Render () {
Return (
)
}
}
Batch generation of Mock data
Helpers.js:
Function getRandomNumber (min, max) {
Return Math.floor (Math.random () * (max-min + 1) + min)
}
Function generateData (iterations = 100, defaultValues = [], namePrefix = {}, maxJump = 100) {
Const arr = []
For (let I = 0; I {
If (I = 0 & & typeof v.value = 'number') {
Return v
}
Return {
... v
Value: I = 0? This.getRandomNumber (1, 1000): arr [I-1] .values [IDX] .value + this.getRandomNumber (0, maxJump)
}
});
Arr.push ({
Name: ${namePrefix.prefix | |''} ${(namePrefix.initialValue | | 0) + I}
Values
});
}
Return arr
}
Export default {
GetRandomNumber
GenerateData
}
Mocks.js:
Import helpers from'. / helpers'
Const defaultChart = [
{
Id: 1
Label: 'Google'
Value: helpers.getRandomNumber (0,50)
}
{
Id: 2
Label: 'Facebook'
Value: helpers.getRandomNumber (0,50)
}
{
Id: 3
Label: 'Outbrain'
Value: helpers.getRandomNumber (0,50)
}
{
Id: 4
Label: 'Apple'
Value: helpers.getRandomNumber (0,50)
}
{
Id: 5
Label: 'Amazon'
Value: helpers.getRandomNumber (0,50)
}
]
Export default {
DefaultChart
}
A beggar version of the dynamic ranking visualization is done.
Complete code
Import React, {useState, useEffect} from 'react'
Import PropTypes from 'prop-types'
Import'. / styles.scss'
Const getRandomColor = () = > {
Const letters = '0123456789ABCDEF'
Let color ='#'
For (let I = 0; I
< 6; i++) { color += letters[Math.floor(Math.random() * 16)] } return color; }; const translateY = (value) =>{
Return translateY (${value} px)
}
Const DynamicBarChart = (props) = > {
Const [dataQueue, setDataQueue] = useState ([])
Const [activeItemIdx, setActiveItemIdx] = useState (0)
Const [highestValue, setHighestValue] = useState (0)
Const [currentValues, setCurrentValues] = useState ({})
Const [firstRun, setFirstRun] = useState (false)
Let iterationTimeoutHolder = null
Function start () {
If (activeItemIdx > 1) {
Return
}
NextStep (true)
}
Function setNextValues () {
If (! dataQueue [activeItemIdx]) {
IterationTimeoutHolder = null
Return
}
Const roundData = dataQueue [activeItemIdx] .values; const nextValues = {}; let highestValue = 0 [c.id] = {... c, color: c.color | | (currentValues [c.id] | | {}). Color | | getRandomColor ()}; if (Math.abs (c.value) > highestValue) {highestValue = Math.abs (c.value);} return c;}); console.table (highestValue); www.kaifx.cnsetCurrentValues (nextValues) SetHighestValue (highestValue); setActiveItemIdx (activeItemIdx + 1)
}
Function nextStep (firstRun = false) {
SetFirstRun (firstRun)
SetNextValues ()
}
UseEffect () = > {
SetDataQueue (props.data)
}, [])
UseEffect () = > {
Start ()
}, [dataQueue])
UseEffect () = > {
IterationTimeoutHolder = window.setTimeout (nextStep, 1000)
Return () = > {
If (iterationTimeoutHolder) {
Window.clearTimeout (iterationTimeoutHolder)
}
}
}, [activeItemIdx])
Const keys = Object.keys (currentValues)
Const {barGapSize, barHeight, showTitle, data} = props
Console.table ('data', data)
Const maxValue = highestValue / 0.85
Const sortedCurrentValues = keys.sort ((a, b) = > currentValues.value-currentValues.value)
Const currentItem = dataQueue [activeItemIdx-1] | | {}
Return (
{
{
ShowTitle & &
{currentItem.name}
}
{
SortedCurrentValues.map ((key, idx) = > {
Const currentValueData = currentValues [key]
Const value = currentValueData.value
Let width = Math.abs ((value / maxValue))
Let widthStr
If (isNaN (width) | |! width) {
WidthStr = '1px'
} else {
WidthStr = ${width}%
}
Return ({! currentValueData.label? Key: currentValueData.label} {currentValueData.value});})}
);
}
DynamicBarChart.propTypes = {
ShowTitle: PropTypes.bool
IterationTimeout: PropTypes.number
Data: PropTypes.array
StartRunningTimeout: PropTypes.number
BarHeight: PropTypes.number
BarGapSize: PropTypes.number
Baseline: PropTypes.number
}
DynamicBarChart.defaultProps = {
ShowTitle: true
IterationTimeout: 200
Data: []
StartRunningTimeout: 0
BarHeight: 50
BarGapSize: 20
Baseline: null
}
Export {
DynamicBarChart
}
Styles.scss
. live-chart {
Width: 100%
Padding: 20px
Box-sizing: border-box
Position: relative
Text-align: center
H2 {
Font-weight: 700
Font-size: 60px
Text-transform: uppercase
Text-align: center
Padding: 20px 10px
Margin: 0
}
.chart {
Position: relative
Margin: 20px auto
}
. chart-bars {
Position: relative
Width: 100%
}
. bar-wrapper {
Display: flex
Flex-wrap: wrap
Align-items: center
Position: absolute
Top: 0
Left: 0
Transform: translateY (0)
Transition: transform 0.5s linear
Padding-left: 200px
Box-sizing: border-box
Width: 100%
Justify-content: flex-start
Label {position: absolute; height: 100%; width: 200px; left: 0; padding: 0 10px; box-sizing: border-box; text-align: right; top: 50%; transform: translateY (- 50%); font-size: 16px; font-weight: 700; display: flex; justify-content: flex-end; align-items: center;}. Value {font-size: 16px; font-weight: 700; margin-left: 10px;}. Bar {width: 0% Transition: width 0.5s linear;}
}
}
Conclusion
I have always been interested in the visualization of dynamic rankings, but most of them are based on D3 or echarts.
This library is not only separated from the graphics library, but also uses the new features of React 16. It also made me fully understand the wonderful use of React Hook.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.