React+CSS?實現(xiàn)繪制豎狀柱狀圖
前言:
頁面結(jié)構(gòu)分為兩個部分,柱狀圖 + 文字為一部分,標注為為一部分。
先來看柱狀圖 + 文字這一部分。
寬度定為 width: 55
, height
高度使用百分比進行動態(tài)變化。整個部分使用 flex
布局。通過 justify-content: space-around;
屬性,對里面的項目進行排列。項目 item 同樣使用 flex 布局,這個是對 柱狀圖 + 文字 進行整體的排列。
<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> 選項三 <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; } } } } }
下方的標注部分,使用絕對定位,width = 100%,height = 100%,實現(xiàn)標注和漸變柱形部分的重疊。
這部分將 li 標簽的 width = 100%,間隔通過 top 來動態(tài)實現(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ù)值的計算,這里筆者是找到這一組數(shù)據(jù)里面的最大值
let maxValue = 0; data.forEach((dataItem) => { if (dataItem.value > maxValue) maxValue = dataItem.value; });
獲取最大值最近的100整數(shù)
let maxScaleNum = Math.ceil(maxValue / 100) * 100
計算每一個數(shù)據(jù)的 value,占最大值最近的100整數(shù)的百分比。
percent: (dataItem.value / maxScaleNum) * 100
標注的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> 選項三 <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'));
運行結(jié)果:
到此這篇關(guān)于React+CSS 實現(xiàn)繪制豎狀柱狀圖的文章就介紹到這了,更多相關(guān)React 柱狀圖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react-native?父函數(shù)組件調(diào)用類子組件的方法(實例詳解)
這篇文章主要介紹了react-native?父函數(shù)組件調(diào)用類子組件的方法,通過詳細步驟介紹了React 函數(shù)式組件之父組件調(diào)用子組件的方法,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-09-09關(guān)于React Native 無法鏈接模擬器的問題
許多朋友遇到React Native 無法鏈接模擬器的問題,怎么解決呢,本文給大家分享完整簡便解決方法及配置例題,對React Native 鏈接模擬器相關(guān)知識感興趣的朋友一起看看吧2021-06-06React render核心階段深入探究穿插scheduler與reconciler
這篇文章主要介紹了React render核心階段穿插scheduler與reconciler,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-11-11react同構(gòu)實踐之實現(xiàn)自己的同構(gòu)模板
這篇文章主要介紹了react同構(gòu)實踐之實現(xiàn)自己的同構(gòu)模板,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03從零開始最小實現(xiàn)react服務(wù)器渲染詳解
這篇文章主要介紹了從零開始最小實現(xiàn)react服務(wù)器渲染詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01