UNPKG

vislite

Version:

灵活、快速、简单的数据可视化交互式跨端前端库

210 lines (162 loc) 6.69 kB
// 刻度尺刻度求解 import type { rulerOptionType } from '../types/ruler' // 需要注意的是,实际的间距个数可能是 num-1 或 num 或 num+1 或 1 export default function (maxValue: number, minValue: number, num: number, option?: rulerOptionType) { // 如果最大值最小值反了 if (maxValue < minValue) { const temp = minValue minValue = maxValue maxValue = temp } // 如果相等 else if (maxValue == minValue) { return [maxValue] } // 为了变成 -100 ~ 100 需要放大或者缩小的倍数 const times100 = (function (_value) { // 先确定基调,是放大还是缩小 const _times100_base = (_value < 100 && _value > -100) ? 10 : 0.1 // 记录当前缩放倍数 let _times100 = -1, _tiemsValue = _value while (_times100_base == 10 ? // 如果是放大,超过 -100 ~ 100 就应该停止 (_tiemsValue >= -100 && _tiemsValue <= 100) : // 如果是缩小,进入 -100 ~ 100 就应该停止 (_tiemsValue <= -100 || _tiemsValue >= 100) ) { _times100 += 1 _tiemsValue *= _times100_base } if (_times100_base == 10) { return Math.pow(10, _times100) } else { // 解决类似 0.1 * 0.1 = 0.010000000000000002 浮点运算不准确问题 let temp = "0." for (let i = 1; i < _times100; i++) { temp += "0"; } return +(temp + "1") } }) // 根据差值来缩放 (maxValue - minValue) // 求解出 -100 ~ 100 的最佳间距值 后直接转换原来的倍数 const distance100_oral = Math.ceil((maxValue - minValue) * times100 / num) const getResult = (changValue: number) => { // 校对一下 const distance100 = { 3: 2, 4: 5, 6: 5, 7: 5, 8: 10, 9: 10, 11: 10, 12: 10, 13: 15, 14: 15, 16: 15, 17: 15, 18: 20, 19: 20, 21: 20, 22: 20, 23: 25, 24: 25, 26: 25, 27: 25 }[distance100_oral + changValue] || (distance100_oral + changValue) const distance = distance100 / times100 // 最小值,也就是起点 const begin = Math.floor(minValue / distance) * distance const rulerArray = [] // 获取最终的刻度尺数组 rulerArray.push(begin) for (let index = 1; rulerArray[rulerArray.length - 1] < maxValue; index++) { rulerArray.push(begin + distance * index) } return rulerArray } let rulerArray = getResult(0) const balanceMax = () => { const rulerArray_temp = [] const changeDist = rulerArray[rulerArray.length - 1] - (option?.max as number) for (let index = 0; index < rulerArray.length; index++) { if (index + 1 < rulerArray.length && rulerArray[index + 1] - changeDist < minValue) { // 多余的 } else { rulerArray_temp.push(rulerArray[index] - changeDist) } } return rulerArray_temp } const balanceMin = () => { const rulerArray_temp = [] const changeDist = rulerArray[0] - (option?.min as number) for (let index = 0; index < rulerArray.length; index++) { rulerArray_temp[index] = rulerArray[index] - changeDist if (maxValue <= rulerArray_temp[index]) break } return rulerArray_temp } if (option) { // 上下界限制 if ('max' in option && 'min' in option && (option.max as number) >= maxValue && (option.min as number) <= minValue) { const isAnswer = () => { // 先判断原始的是否可行 if (rulerArray[0] >= (option.min as number) && rulerArray[rulerArray.length - 1] <= (option.max as number)) return true // 再判断max调整是否可行 const rulerArray_max = balanceMax() if (rulerArray_max[0] >= (option.min as number) && rulerArray_max[rulerArray_max.length - 1] <= (option.max as number)) { rulerArray = rulerArray_max return true } // 再判断max调整是否可行 const rulerArray_min = balanceMin() if (rulerArray_min[0] >= (option.min as number) && rulerArray_min[rulerArray_max.length - 1] <= (option.max as number)) { rulerArray = rulerArray_min return true } } if (isAnswer()) return rulerArray for (let changValue = 1; changValue < 100; changValue++) { rulerArray = getResult(changValue) if (isAnswer()) return rulerArray rulerArray = getResult(-changValue) if (isAnswer()) return rulerArray } } // 单界限制 if ('max' in option && (option.max as number) >= maxValue) { // 上越界了 if ((option.max as number) < rulerArray[rulerArray.length - 1]) { rulerArray = balanceMax() } } else if ('min' in option && (option.min as number) <= minValue) { // 下越界了 if ((option.min as number) > rulerArray[0]) { rulerArray = balanceMin() } } } // 对结果进行对齐 // 2023年11月15日 于南京 for (let index = 0; index < rulerArray.length; index++) { let valStr = rulerArray[index] + "" // 只有小数需要处理 if (/\./.test(valStr)) { // 1.0999999999999999 if (/9{7,}$/.test(valStr)) { valStr = valStr.replace(/9{7,}$/, '') rulerArray[index] = +(valStr.substring(0, valStr.length - 1) + ((+valStr[valStr.length - 1]) + 1)) } // 0.30000000000000004 else if (/0{7,}\d$/.test(valStr)) { rulerArray[index] = +(valStr.replace(/0{7,}\d$/, '')) } } } return rulerArray }