JS模擬實(shí)現(xiàn)Excel條件格式中的色階效果
本篇文章是模擬Excel條件格式第二篇“色階”的實(shí)現(xiàn)原理,上篇《前端模擬 Excel 條件格式—數(shù)據(jù)條效果實(shí)現(xiàn)》
需求背景
公司做的數(shù)據(jù)分析系統(tǒng)中想要將Excel中的條件格式功能搬過來。原因:純表格中的數(shù)據(jù)展示只有字符沒有樣式,比較難發(fā)現(xiàn)更多維度的信息,當(dāng)有了色階效果后分析人員可以更容易在數(shù)據(jù)中發(fā)現(xiàn)更多信息如:是否波動(dòng)劇烈、是否呈聚合趨勢(shì)、是否有規(guī)律等。
先看Excel的標(biāo)準(zhǔn)效果:

下面我們?cè)囍治鋈绾螌?shí)現(xiàn)這樣的效果。
需求分析
按列展示、要根據(jù)單元格的值自動(dòng)計(jì)算出對(duì)應(yīng)的色階值,將對(duì)應(yīng)的顏色填充到單元格中。 按此分析可以肯定的是這不是一個(gè)簡(jiǎn)單的CSS漸變可以實(shí)現(xiàn)的,這里會(huì)涉及到對(duì)色值之間的色階計(jì)算、單元格需要進(jìn)行計(jì)算來動(dòng)態(tài)生成樣式。
實(shí)現(xiàn)邏輯
與上一篇數(shù)據(jù)條的實(shí)現(xiàn)有個(gè)相同的前提,我們要知道每列數(shù)據(jù)的最大值max和最小值min,以及計(jì)算當(dāng)前值在最大最小值中的位置。
先來實(shí)現(xiàn)一個(gè)獲取色階顏色值的方法,關(guān)于色階的計(jì)算使用到的是線性插值的方式,有一個(gè)標(biāo)準(zhǔn)的公式,下面是 ChatGPT 回答:

實(shí)現(xiàn)代碼: 用到了一個(gè)顏色轉(zhuǎn)換庫:Color
getColor(value, min, max, colors) {
if (value < min) return colors[0]
if (value > max) return colors[colors.length - 1]
// 將 hex 顏色值轉(zhuǎn)換為 rgb 格式
colors = colors.map(c => Color(c).object())
const colorsLen = colors.length;
// 計(jì)算當(dāng)前值在最大最小值中的位置
const rang = max - min;
let weight = (value - min) / rang;
// 計(jì)算顏色列表的最后一個(gè)索引值
const endIndex = Math.max(Math.ceil((colorsLen - 1) * weight), 1);
// 獲取兩個(gè)顏色最小顏色(起始色)、最大顏色(結(jié)束色)
const minColor = colors[endIndex - 1]
const maxColor = colors[endIndex]
// 計(jì)算色階比例
weight = weight * (colorsLen - 1) - (endIndex - 1)
// 線性插值公式
const r = (1 - weight) * minColor.r + weight * maxColor.r
const g = (1 - weight) * minColor.g + weight * maxColor.g
const b = (1 - weight) * minColor.b + weight * maxColor.b
return `rgb(${r},${g},$)`
}完整代碼
代碼使用 Vue + ElementUI
template 部分
<template>
<el-table
:data="tableData"
border
stripe
style="width: 80%"
:cell-style="cellStyle"
>
<el-table-column
v-for="item in columns"
sortable
:key="item.prop"
:prop="item.prop"
:label="item.label"
>
<template slot-scope="scope">
<span class="cell-value">{{ scope.row[item.prop] }}</span>
</template>
</el-table-column>
</el-table>
</template>script 部分
import Color from 'color';
import { tableColumns, tableData } from './mock-data.js';
export default {
name: 'color-scale',
data() {
return {
// 數(shù)據(jù)mock部分放在下方
columns: tableColumns,
tableData: tableData(),
// 紅黃綠
colors: ['#f8696b', '#ffeb84', '#63be7b'],
// 綠黃紅
colors2: ['#63be7b', '#ffeb84', '#f8696b']
}
},
methods: {
getColor(value, min, max, colors) {
// 同上...
},
cellStyle({ row, column }) {
const { property } = column;
if (property !== 'car') {
const obj = this.columns.find(item => item.prop === property);
const min = obj.min;
const max = obj.max;
const cellVal = row[property]
const colors = property === 'order' ? this.colors2 : this.colors
return {
background: this.getColor(cellVal, min, max, colors)
}
}
return {}
}
}
}mock 數(shù)據(jù)
不重要,感興趣可以參考
// mock-data.js
export const tableColumns = [
{
prop: 'car',
label: '車型',
min: 1,
max: 20
},
{
prop: 'order',
label: '訂單量',
min: 10,
max: 30
},
{
prop: 'sale',
label: '銷售額',
min: 100,
max: 120
},
{
prop: 'aggregate',
label: '呈聚合狀',
min: 10,
max: 104
},
{
prop: 'uneven',
label: '隨機(jī)數(shù)據(jù)',
min: 50,
max: 5000
}
];
export const tableData = function () {
const aggregateNums = [10, 20, 30, 40, 50, 60, 70, 80, 81, 82, 83, 84, 85, 86, 87, 100, 101, 102, 103, 104];
return Array.from({ length: 20 }, (_, index) => ({
car: `車型${index + 1}`,
order: index + 10,
sale: index + 100,
aggregate: aggregateNums[index],
uneven: getRandomIntInclusive(50, 5000) // 隨機(jī)
}))
}
export const getRandomIntInclusive = (min, max) => {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}最終效果

總結(jié)
- 實(shí)現(xiàn)此功能中最重要也是最難的點(diǎn)就是在于色階值的計(jì)算、線性插值公式的理解,這一步理解透了其他的就簡(jiǎn)單了。
- 善用 ChatGPT 手動(dòng)捂臉
以上就是JS模擬實(shí)現(xiàn)Excel條件格式中的色階效果的詳細(xì)內(nèi)容,更多關(guān)于JS模擬Excel色階的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
javascript下4個(gè)跨瀏覽器必備的函數(shù)
如果你的項(xiàng)目要用到 JavaScript,而你不使用任何 JavaScript 框架,那么對(duì)于那些常用且各個(gè)瀏覽器明顯不同的地方就需要用函數(shù)來封裝起來。2010-03-03
js實(shí)現(xiàn)轉(zhuǎn)盤抽獎(jiǎng)功能
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)轉(zhuǎn)盤抽獎(jiǎng)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
用瀑布流的方式在網(wǎng)頁上插入圖片的簡(jiǎn)單實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄闷俨剂鞯姆绞皆诰W(wǎng)頁上插入圖片的簡(jiǎn)單實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-09-09
JavaScript實(shí)現(xiàn)數(shù)字格式化的示例詳解
在處理數(shù)字時(shí),為了提高可讀性,我們通常會(huì)將整數(shù)部分的數(shù)字以千分位或百分位分隔,本文將詳細(xì)介紹如何使用JavaScript來實(shí)現(xiàn)數(shù)字的千分位和百分位分隔,需要的可以參考下2024-04-04

