1
This commit is contained in:
@@ -0,0 +1,262 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>tabbar 角标遮挡 icon · 方案对照</title>
|
||||
<style>
|
||||
/* 375 逻辑宽:1rpx = 0.5px(浏览器不认 rpx,必须折算)。
|
||||
不设 box-sizing,与 uvue view 的默认(content-box)一致 ——
|
||||
这一点很关键:min-width 是「内容盒」最小值,角标实际宽 = 18 + 10 = 28px。 */
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 12px;
|
||||
background: #F3F4F6;
|
||||
color: #1F2937;
|
||||
font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
}
|
||||
|
||||
/* ===== 库组件 x-tabbar / x-badge 真实样式(抄自 uni_modules 源码) ===== */
|
||||
.xTabbar {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.xTabbarWrap {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.xTabbarItem {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* view 在 uvue 上默认是 flex column */
|
||||
.xBadge {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.xBadgeWrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.xBadge-countAndLabel {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
border-radius: 100px;
|
||||
padding: 0rpx 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* 角标尺寸 = hr-design.css 的 !important 覆盖值(36rpx 高 / 22.4rpx 字 / padding 10rpx) */
|
||||
.xBadge-countAndLabel {
|
||||
min-width: 18px;
|
||||
height: 18px;
|
||||
padding: 0 5px;
|
||||
border-radius: 9px;
|
||||
}
|
||||
|
||||
.xBadge-countAndLabelText {
|
||||
font-size: 11.2px;
|
||||
line-height: 1;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* hr-design.css:.xBadge { padding: 0 !important } —— 去掉库为「半出血」预留的内边距 */
|
||||
.xBadge {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* ---- A:库默认 + 取消出血(= 本轮修复前的状态,right:0) ---- */
|
||||
.A .xBadge-countAndLabel {
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: auto;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* ---- B:上一轮的错解(右移 20rpx)—— 假设角标宽 18px 才会成立,实际 28px ---- */
|
||||
.B .xBadge-countAndLabel {
|
||||
top: -2px;
|
||||
right: -10px;
|
||||
left: auto;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* ---- C:本轮定稿(左锚定 44rpx = 22px,宽度无关) ---- */
|
||||
.C .xBadge-countAndLabel {
|
||||
top: -2px;
|
||||
left: 22px;
|
||||
right: auto;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* 库默认「半出血」(仅供对照,需要上方留白) */
|
||||
.D .xBadge-countAndLabel {
|
||||
top: 5px;
|
||||
right: 0;
|
||||
left: auto;
|
||||
transform: translate(50%, -50%);
|
||||
}
|
||||
|
||||
.frame {
|
||||
width: 375px;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 1px 3px rgba(15, 23, 42, .1);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.frame .tip {
|
||||
font-size: 10.5px;
|
||||
color: #374151;
|
||||
padding: 6px 12px 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.sim {
|
||||
width: 375px;
|
||||
height: 76px;
|
||||
background: #F9FAFB;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* item 框辅助线:用于判断角标是否被裁 */
|
||||
.sim .xTabbarItem {
|
||||
outline: 1px dashed #93C5FD;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 13px;
|
||||
margin: 0 0 7px;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #111827;
|
||||
color: #A7F3D0;
|
||||
font-size: 10.5px;
|
||||
padding: 8px 10px;
|
||||
border-radius: 8px;
|
||||
margin: 0 0 12px;
|
||||
line-height: 1.55;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>底部 tabbar 角标 · 定位方案对照(375 逻辑宽,1rpx = 0.5px)</h2>
|
||||
<pre id="out">…</pre>
|
||||
<div id="host"></div>
|
||||
|
||||
<script>
|
||||
var ICON_PX = 24; /* hr-tabbar 传 icon-size="48rpx" = 24px */
|
||||
var FS = 13; /* hr-tabbar 传 font-size="26rpx" = 13px */
|
||||
|
||||
/* 按 x-tabbar 的真实结构生成一屏 tabbar:
|
||||
.xTabbarItem > .xBadge > .xBadgeWrap > [角标, icon盒(30px,padding 0 4px), 文字] */
|
||||
function tabbar(v) {
|
||||
var items = v.count === 3
|
||||
? [['首页', '#9CA3AF'], ['事件', '#2563EB'], ['我的', '#9CA3AF']]
|
||||
: [['扫码', '#9CA3AF'], ['仓库', '#9CA3AF'], ['事件', '#2563EB'], ['消息', '#9CA3AF'], ['我', '#9CA3AF']];
|
||||
var badgeIdx = v.count === 3 ? 1 : 2;
|
||||
|
||||
var out = [];
|
||||
items.forEach(function(it, i) {
|
||||
var badge = i === badgeIdx
|
||||
? '<div class="xBadge-countAndLabel" style="background:#DC2626">' +
|
||||
'<span class="xBadge-countAndLabelText" style="color:#fff">' + v.label + '</span></div>'
|
||||
: '';
|
||||
out.push(
|
||||
'<div class="xTabbarItem" style="height:60px">' +
|
||||
'<div class="xBadge">' +
|
||||
'<div class="xBadgeWrap">' + badge +
|
||||
/* icon 盒:库内写死 height:30px + padding:0px 4px */
|
||||
'<div style="height:30px;padding:0px 4px">' +
|
||||
'<span class="ic" style="display:block;width:' + ICON_PX + 'px;height:' + ICON_PX +
|
||||
'px;background:' + it[1] + ';border-radius:6px"></span>' +
|
||||
'</div>' +
|
||||
/* 文字:库内内联 fontSize=26rpx + paddingTop:4px */
|
||||
'<span class="lb" style="font-size:' + FS + 'px;color:' + it[1] + ';padding-top:4px">' +
|
||||
it[0] + '</span>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>');
|
||||
});
|
||||
return '<div class="xTabbar ' + v.cls + '"><div class="xTabbarWrap">' + out.join('') + '</div></div>';
|
||||
}
|
||||
|
||||
var variants = [
|
||||
{ cls: 'A', count: 3, label: '4', title: 'A 本轮修复前(right:0 + 取消出血)' },
|
||||
{ cls: 'B', count: 3, label: '4', title: 'B 上一轮的错解(right:-20rpx,按角标宽 18px 推算)' },
|
||||
{ cls: 'C', count: 3, label: '4', title: 'C 本轮定稿(left:44rpx,3 Tab)' },
|
||||
{ cls: 'C', count: 5, label: '4', title: 'C 本轮定稿(left:44rpx,5 Tab 仓管端)' },
|
||||
{ cls: 'C', count: 5, label: '99', title: 'C 本轮定稿(两位数角标,验证向右生长不回头)' },
|
||||
{ cls: 'D', count: 3, label: '4', title: 'D 库默认「半出血」(对照:需要上方留白)' }
|
||||
];
|
||||
|
||||
var html = '';
|
||||
variants.forEach(function(v, i) {
|
||||
html += '<div class="frame"><div class="tip">' + v.title + '</div><div class="sim">' +
|
||||
tabbar(v).replace('class="xTabbar ' + v.cls + '"', 'class="xTabbar ' + v.cls + '" id="tb' + i + '"') +
|
||||
'</div></div>';
|
||||
});
|
||||
document.getElementById('host').innerHTML = html;
|
||||
|
||||
function rect(el) {
|
||||
var r = el.getBoundingClientRect();
|
||||
return { l: +r.left.toFixed(1), t: +r.top.toFixed(1), r: +r.right.toFixed(1), b: +r.bottom.toFixed(1), w: +r.width.toFixed(1), h: +r.height.toFixed(1) };
|
||||
}
|
||||
|
||||
function report(v, i) {
|
||||
var root = document.getElementById('tb' + i);
|
||||
var badgeIdx = v.count === 3 ? 1 : 2;
|
||||
var item = root.querySelectorAll('.xTabbarItem')[badgeIdx];
|
||||
var wrap = rect(item.querySelector('.xBadgeWrap'));
|
||||
var bx = rect(item.querySelector('.xBadge'));
|
||||
var ic = rect(item.querySelector('.ic'));
|
||||
var bd = rect(item.querySelector('.xBadge-countAndLabel'));
|
||||
var it = rect(item);
|
||||
|
||||
var ox = Math.max(0, Math.min(ic.r, bd.r) - Math.max(ic.l, bd.l));
|
||||
var oy = Math.max(0, Math.min(ic.b, bd.b) - Math.max(ic.t, bd.t));
|
||||
var clipTop = Math.max(0, it.t - bd.t);
|
||||
var clipBot = Math.max(0, bd.b - it.b);
|
||||
var clipR = Math.max(0, bd.r - it.r);
|
||||
|
||||
return v.title + '\n' +
|
||||
' item(60px) ' + JSON.stringify(it) + '\n' +
|
||||
' .xBadgeWrap ' + JSON.stringify(wrap) + ' ← 角标的定位基准(半宽 ' + (wrap.w / 2).toFixed(1) + 'px)\n' +
|
||||
' .xBadge ' + JSON.stringify(bx) + (bx.t < it.t - 0.5 || bx.b > it.b + 0.5 ? ' ⚠ 超出 item' : ' ✓ 在 item 内') + '\n' +
|
||||
' icon ' + JSON.stringify(ic) + '\n' +
|
||||
' 角标 ' + JSON.stringify(bd) + ' ← 实际宽 ' + bd.w + 'px\n' +
|
||||
' ⇒ 角标压住 icon:' + ox.toFixed(1) + ' × ' + oy.toFixed(1) + ' px' +
|
||||
'(横向占 icon 的 ' + (ox / ic.w * 100).toFixed(0) + '%)\n' +
|
||||
' ⇒ 裁切检查:上溢 ' + clipTop.toFixed(1) + ' / 下溢 ' + clipBot.toFixed(1) + ' / 右溢 ' + clipR.toFixed(1) + ' px' +
|
||||
((clipTop === 0 && clipBot === 0 && clipR === 0) ? ' ✓ 不会被裁' : ' ⚠ 有被裁风险');
|
||||
}
|
||||
|
||||
var out = [];
|
||||
variants.forEach(function(v, i) { out.push(report(v, i)); });
|
||||
document.getElementById('out').textContent = out.join('\n\n');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user