React+CSS?實(shí)現(xiàn)繪制豎狀柱狀圖
前言:
頁(yè)面結(jié)構(gòu)分為兩個(gè)部分,柱狀圖 + 文字為一部分,標(biāo)注為為一部分。
先來(lái)看柱狀圖 + 文字這一部分。
寬度定為 width: 55, height 高度使用百分比進(jìn)行動(dòng)態(tài)變化。整個(gè)部分使用 flex 布局。通過(guò) justify-content: space-around; 屬性,對(duì)里面的項(xiàng)目進(jìn)行排列。項(xiàng)目 item 同樣使用 flex 布局,這個(gè)是對(duì) 柱狀圖 + 文字 進(jìn)行整體的排列。
<div className="crosswise_diagram_top">
{listData.map((item) => {
return (
<div className="crosswise_diagram_item" key={item.value}>
<div className="crosswise_diagram_item_precent">
<div
className="precent"
style={{
width: 55,
height: `${item.percent}%`
}}
>
<div>
選項(xiàng)三 <span>254</span>
</div>
</div>
</div>
<div className="crosswise_diagram_item_name">{item.name}</div>
</div>
)
})}
</div>.crosswise_diagram_top {
display: flex;
justify-content: space-around;
height: 100%;
.crosswise_diagram_item {
display: flex;
flex-direction: column;
width: 55px;
position: relative;
justify-content: end;
height: 100%;
.crosswise_diagram_item_name {
margin-top: 11px;
font-size: 16px;
font-weight: 400;
color: #07132b;
}
.crosswise_diagram_item_precent {
height: 100%;
display: contents;
.precent {
border-radius: 4px;
position: relative;
&::after {
content: '';
height: 102%;
border-right: 1px dashed #07132b;
position: absolute;
top: -2%;
}
> div {
position: absolute;
width: 66px;
text-align: center;
top: -2%;
height: 21px;
margin-top: -21px;
}
}
}
}
}下方的標(biāo)注部分,使用絕對(duì)定位,width = 100%,height = 100%,實(shí)現(xiàn)標(biāo)注和漸變柱形部分的重疊。
這部分將 li 標(biāo)簽的 width = 100%,間隔通過(guò) top 來(lái)動(dòng)態(tài)實(shí)現(xiàn)。
<div className="crosswise_diagram_bottom">
<ul className="crosswise_diagram_ul">
{scaleArray.map((item, itemIndex) => {
return (
<li
className="crosswise_diagram_li"
style={{ top: `${(100 / 5) * itemIndex}%` }}
key={item}
>
<span className="crosswise_diagram_name">{item}</span>
<span className="crosswise_diagram_precent" />
</li>
)
})}
</ul>
</div>.crosswise_diagram_bottom {
position: absolute;
top: -36px;
left: -55px;
height: 100%;
width: 100%;
.crosswise_diagram_ul {
width: 100%;
.crosswise_diagram_li {
width: 100%;
position: absolute;
display: flex;
flex-direction: row;
.crosswise_diagram_name {
position: relative;
top: -9px;
width: 45px;
font-size: 12px;
font-weight: bold;
color: #a6b1bf;
}
.crosswise_diagram_precent {
width: 90%;
height: 100%;
border-top: 1px dashed #d7dbe0;
color: #a6b1bf;
}
}
}
}關(guān)于數(shù)值的計(jì)算,這里筆者是找到這一組數(shù)據(jù)里面的最大值
let maxValue = 0;
data.forEach((dataItem) => {
if (dataItem.value > maxValue) maxValue = dataItem.value;
});獲取最大值最近的100整數(shù)
let maxScaleNum = Math.ceil(maxValue / 100) * 100
計(jì)算每一個(gè)數(shù)據(jù)的 value,占最大值最近的100整數(shù)的百分比。
percent: (dataItem.value / maxScaleNum) * 100
標(biāo)注的top,使用 for 循環(huán)生成。
const multiple = Math.floor(maxScaleNum / scaleNum)
const newArray = new Array()
for (let i = 0; i <= maxScaleNum; i += multiple) {
newArray.push(i)
}
setScaleArray(newArray.reverse())整體代碼:
import React, { useState, useEffect } from 'react';
import ReactDom from 'react-dom';
const Test = ({ data, scaleNum = 5 }) => {
const [listData, setListData] = useState(
[]
)
const [scaleArray, setScaleArray] = useState([])
useEffect(() => {
if (scaleNum <= 0) {
return
}
let maxValue = 0
data.forEach((dataItem) => {
if (dataItem.value > maxValue) maxValue = dataItem.value
})
let maxScaleNum = Math.ceil(maxValue / 100) * 100
if (maxValue <= 0) {
setScaleArray(new Array(scaleNum).fill(0))
setListData(
data.map((dataItem) => {
return {
name: dataItem.name,
percent: 0,
value: 0
}
})
)
return
}
setListData(
data.map((dataItem) => {
return {
name: dataItem.name,
percent: (dataItem.value / maxScaleNum) * 100,
value: dataItem.value
}
})
)
const multiple = Math.floor(maxScaleNum / scaleNum)
const newArray = new Array()
for (let i = 0; i <= maxScaleNum; i += multiple) {
newArray.push(i)
}
setScaleArray(newArray.reverse())
}, [data, scaleNum])
return (
<section className="crosswise_diagram">
<div className="crosswise_diagram_top">
{listData.map((item) => {
return (
<div className="crosswise_diagram_item" key={item.value}>
<div className="crosswise_diagram_item_precent">
<div
className="precent"
style={{
width: 55,
height: `${item.percent}%`
}}
>
<div>
選項(xiàng)三 <span>254</span>
</div>
</div>
</div>
<div className="crosswise_diagram_item_name">{item.name}</div>
</div>
)
})}
</div>
<div className="crosswise_diagram_bottom">
<ul className="crosswise_diagram_ul">
{scaleArray.map((item, itemIndex) => {
return (
<li
className="crosswise_diagram_li"
style={{ top: `${(100 / 5) * itemIndex}%` }}
key={item}
>
<span className="crosswise_diagram_name">{item}</span>
<span className="crosswise_diagram_precent" />
</li>
)
})}
</ul>
</div>
</section>
)
}
ReactDom.render(<Test style={{ width: 440 }}
scaleNum={6}
data={[
{
name: '西瓜',
value: 40
},
{
name: '菠蘿',
value: 56
},
{
name: '香蕉',
value: 47
}
]} />, document.getElementById('app'));運(yùn)行結(jié)果:

到此這篇關(guān)于React+CSS 實(shí)現(xiàn)繪制豎狀柱狀圖的文章就介紹到這了,更多相關(guān)React 柱狀圖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React實(shí)現(xiàn)二級(jí)聯(lián)動(dòng)效果(樓梯效果)
這篇文章主要為大家詳細(xì)介紹了React實(shí)現(xiàn)二級(jí)聯(lián)動(dòng)效果,樓梯效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
react項(xiàng)目?jī)?yōu)化配置的操作詳解
這篇文章主要介紹了react項(xiàng)目?jī)?yōu)化配置,主要包括優(yōu)化配置CDN,優(yōu)化路由懶加載,結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06
在react-router4中進(jìn)行代碼拆分的方法(基于webpack)
這篇文章主要介紹了在react-router4中進(jìn)行代碼拆分的方法(基于webpack),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
React?Hooks項(xiàng)目實(shí)戰(zhàn)
React?Hooks是React?16.8版本引入的新特性,它使得在函數(shù)組件中也能夠使用狀態(tài)(state)和其他React特性,本文就來(lái)詳細(xì)介紹一下React?Hooks項(xiàng)目實(shí)戰(zhàn),感興趣的可以了解一下2023-11-11
全棧輕量級(jí)搭配之Remix Prisma Sqlite使用分析
這篇文章主要為大家介紹了全棧輕量級(jí)搭配之Remix Prisma Sqlite使用示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05

