场景
场景是这样的,我们目前开发的云文档功能需要添加一个页宽功能,之前我们的页宽是写死的
- 默认: 180px padding
- 较宽: 240px padding
- 全宽: 300px padding
后来说不能够进行简单的写死赋值.然后去参考云文档的老前辈飞书,看看他们的页宽是怎么动态设置的,并且应用到我们自己的云文档上面。于是派生出这个前端需求
分析
一开始我想的是直接从源码上面打断点进行调试,也就是说 在飞书控制width 和 padding的地方打一个document的断点,然后 r
-> c
-> i
-> t
一层层变量调用栈向上排查,然后发现行不通。根本找不到计算页宽的地方。估计是 计算和赋值是两处函数的调用栈
所以只能用蒙特卡洛模拟,先随机采样一些点
模式\页宽 | 953 | 1366 | 2048 | 540 |
---|---|---|---|---|
默认 | 313 | 266 | 313 | 44 |
较宽 | 213 | 166 | 213 | 44 |
全宽 | 66 | 66 | 66 | 44 |
注: 表格中的是padding
我们可以发现这样几个规律
全宽
永远只有是66px和44px两种情况默认
模式 =较宽
模式 + 100- 540以上
全宽
>=较宽
> =默认
>=66px ,540 以下全宽
>=较宽
> =默认
>=44px
所以现在我们只需要得到默认模式是怎么计算padding的就可以大概推断出飞书云文档测量padding的行为
尝试
我们接着对飞书页宽paddding和width的点进行采样, 看看他们的关系是什么,x轴是padding,y轴是width
好,通过图我们可以判断,飞书的页宽行为是三个分段函数,前面的两个函数是固定的,那么我们只需要得到最后一个函数的方程即可,由图可知 大概是一个kx+b 的函数,那么我们只需要求的 这个斜率和截距即可。
const dataPoints = [
[201, 1235],
[103, 1041],
[507, 1847],
[394, 1622],
[370, 1573],
[453, 1741],
[233, 1301],
[293, 1420],
[120, 1071],
[66, 764],
[100, 1032],
[81, 995],
[90.5, 1014]
];
// 计算线性拟合函数的斜率和截距
function linearFit(data) {
let sumX = 0;
let sumY = 0;
let sumXY = 0;
let sumXX = 0;
const n = data.length;
for (let i = 0; i < n; i++) {
const [x, y] = data[i];
sumX += x;
sumY += y;
sumXY += x * y;
sumXX += x * x;
}
const slope = (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX);
const intercept = (sumY - slope * sumX) / n;
return { slope, intercept };
}
// 获取拟合结果
const fitResult = linearFit(dataPoints);
const { slope, intercept } = fitResult;
// 定义线性拟合函数
function linearFunction(x) {
return (x - intercept) / slope ;
}
// 示例:计算某个x值对应的拟合值
const yValue = 1286;
const fittedYValue = linearFunction(yValue);
console.log(`线性拟合函数为: y = ${slope.toFixed(2)}x + ${intercept.toFixed(2)}`);
console.log(`当y = ${yValue} 时,拟合的y值为: ${fittedYValue.toFixed(2)}`)
/**
线性拟合函数为: y = 2.12x + 790.85
VM52:52 当y = 1286 时,拟合的y值为: 233.91
*/
得到的结果如下 y = 2.12x + 790.85
, 然后我们可以对照实际的行为验证一下,平均差不到 5px,验证通过,然后我们可以简单梳理一下最终的行为
其中 x 是 实际的宽度, y是需要设置的边距.
需求完成,代码中引入方程式设置边距即可