HarmonyOS电阻色环工作台连载01:角色校验与阻值计算【共创稿事节】
电阻色环工具的难点并非把颜色换成数字,而是同一种颜色出现在不同位置时具有不同含义。金色放在倍率位置表示十分之一,放在误差位置表示百分之五;把所有位置共用一份数字映射,界面就可能给出形式完整却含义错误的结果。本篇为四环电阻建立按角色取值的规则,再把计算结果接入HarmonyOS页面。

先明确读取方向和四个角色
四环依次表示第一位有效数字、第二位有效数字、倍率和误差。计算式为前两位组成的整数乘以十的倍率指数,误差区间则由标称值乘以误差比例得到。工具要求用户先确认读取方向,再输入四个位置;本篇不从照片识别颜色,也不根据颜色间距自动判断方向。
初始样本为棕、黑、红、金。前两位组成十,红色倍率为十的二次方,因此标称值为一千欧姆;金色误差为百分之五,对应九百五十至一千零五十欧姆。页面中的1.00 kΩ是显示单位转换,计算层始终以欧姆保存数值,不会把千欧姆字符串继续参与乘法。
工程在entry/src/main/ets下设置model/BandRule.ets、service/Resistance.ets和pages/Index.ets。规则表放入模型文件,计算函数不读取页面控件,页面只维护颜色选择和提示。这样后续增加反向查色与五环模式时,可以扩展角色集合,而不必重写当前界面的每个按钮。
// model/BandRule.ets
export interface BandRule {
code: string;
label: string;
paint: string;
digit: number;
exponent: number;
tolerance: number;
}
export const RULES: BandRule[] = [
{ code: 'black', label: '黑', paint: '#222222', digit: 0, exponent: 0, tolerance: -1 },
{ code: 'brown', label: '棕', paint: '#805333', digit: 1, exponent: 1, tolerance: 1 },
{ code: 'red', label: '红', paint: '#CD4545', digit: 2, exponent: 2, tolerance: 2 },
{ code: 'orange', label: '橙', paint: '#EC8D36', digit: 3, exponent: 3, tolerance: -1 },
{ code: 'yellow', label: '黄', paint: '#E7C83D', digit: 4, exponent: 4, tolerance: -1 },
{ code: 'green', label: '绿', paint: '#429566', digit: 5, exponent: 5, tolerance: -1 },
{ code: 'blue', label: '蓝', paint: '#456EBD', digit: 6, exponent: 6, tolerance: -1 },
{ code: 'violet', label: '紫', paint: '#8D59A8', digit: 7, exponent: 7, tolerance: -1 },
{ code: 'gray', label: '灰', paint: '#888888', digit: 8, exponent: 8, tolerance: -1 },
{ code: 'white', label: '白', paint: '#F3F3F3', digit: 9, exponent: 9, tolerance: -1 },
{ code: 'gold', label: '金', paint: '#B7954C', digit: -1, exponent: -1, tolerance: 5 },
{ code: 'silver', label: '银', paint: '#ADB3B8', digit: -1, exponent: -2, tolerance: 10 }
];
export function findBand(code: string): BandRule {
for (const rule of RULES) {
if (rule.code === code) return rule;
}
throw new Error('颜色不在当前规则表中');
}
规则表采用明确的支持范围:有效数字支持黑至白,倍率额外支持金银,误差支持棕、红、金、银四种。其余颜色的误差字段写为负一,表示当前工具不接受该组合。这个值是字段自己的无效标记,不能把倍率中的负一次方也当成错误。后续扩充误差档位时,应同时补充规则说明和入口选项。
颜色代码是业务身份,中文色名负责显示,十六进制颜色值负责绘制。三者不能相互替代。换一套深色主题时,可以调整绘制颜色而保留代码;界面增加英文时,也不必修改计算输入。第一位使用黑色在当前设计中会被拒绝,零欧姆器件不通过四环普通电阻的入口处理。
在计算入口落实位置约束
计算函数接收四个颜色代码,先检查数量,再按位置取规则。第一位必须大于零,第二位允许为零;金银没有有效数字,因而不能出现在前两位。误差必须为正,随后计算上下限。函数返回结构化数值和色名,不返回拼好的整页文本,避免显示语言绑住后续算法。
// service/Resistance.ets
import { BandRule, findBand } from '../model/BandRule';
export interface ResistanceResult {
ohms: number;
tolerance: number;
low: number;
high: number;
labels: string[];
}
export function resistance(first: number, second: number,
exponent: number): number {
return (first * 10 + second) * Math.pow(10, exponent);
}
export function decodeFour(codes: string[]): ResistanceResult {
if (codes.length !== 4) throw new Error('四环需要四个颜色');
const first: BandRule = findBand(codes[0]);
const second: BandRule = findBand(codes[1]);
const multiplier: BandRule = findBand(codes[2]);
const tolerance: BandRule = findBand(codes[3]);
if (first.digit <= 0 || second.digit < 0) {
throw new Error('有效数字位置不接受当前颜色');
}
if (tolerance.tolerance <= 0) throw new Error('误差位置不接受当前颜色');
const ohms: number = resistance(first.digit, second.digit, multiplier.exponent);
if (!Number.isFinite(ohms) || ohms <= 0) throw new Error('阻值超出计算范围');
const delta: number = ohms * tolerance.tolerance / 100;
return { ohms, tolerance: tolerance.tolerance,
low: ohms - delta, high: ohms + delta,
labels: [first.label, second.label, multiplier.label, tolerance.label] };
}
export function formatOhms(value: number): string {
if (value >= 1000000) return `${(value / 1000000).toFixed(2)} MΩ`;
if (value >= 1000) return `${(value / 1000).toFixed(2)} kΩ`;
return `${Number(value.toFixed(4))} Ω`;
}
decodeFour是对外校验入口,较底层的resistance负责算术,调用者需要经过颜色规则校验后再使用它。表内倍率覆盖范围固定,因此有效输入的数值规模可控。格式化函数保留标称值的两位显示小数,范围以欧姆显示到至多四位小数;显示舍入不回写计算结果。需要导出精确编码时应保存色环代码,不能从舍入后的文本反推颜色。
本例没有把浮点计算结果直接写成严格相等的业务判断。金银倍率会引入小数,后续进行标准阻值比较时,应使用统一精度或相对误差规则。误差上下限本身描述的是参数容许范围,不能把该范围当成对某个实际器件测量值的确认。
页面保留输入,成功计算后一起更新结果
页面初始展示棕黑红金,按钮在红色和橙色倍率之间切换。一次点击同时更新色名、色带、标称值与区间,没有自动改变误差角色。这里使用两个确定倍率,是为了把规则入口和页面联动做完整;完整颜色选择器可以在下一篇加入,沿用同一个计算函数。
// pages/Index.ets
import { findBand } from '../model/BandRule';
import { decodeFour, formatOhms, ResistanceResult } from '../service/Resistance';
@Entry
@Component
struct Index {
@State codes: string[] = ['brown', 'black', 'red', 'gold'];
@State result: ResistanceResult = decodeFour(['brown', 'black', 'red', 'gold']);
@State message: string = '色名与数值同时显示';
private positions: number[] = [0, 1, 2, 3];
private roles: string[] = ['第一位', '第二位', '倍率', '误差'];
private changeMultiplier(): void {
const next: string[] = this.codes.slice();
next[2] = next[2] === 'red' ? 'orange' : 'red';
try {
const calculated: ResistanceResult = decodeFour(next);
this.codes = next;
this.result = calculated;
this.message = '色名与数值同时显示';
} catch (error) {
this.message = error instanceof Error ? error.message : '计算失败';
}
}
build() {
Scroll() {
Column({ space: 18 }) {
Text('电阻色环工作台').fontSize(26).fontWeight(FontWeight.Bold)
Text('四环电阻').fontSize(16)
Row({ space: 18 }) {
ForEach(this.positions, (position: number) => {
Text('').width(18).height(64)
.backgroundColor(findBand(this.codes[position]).paint)
}, (position: number) => position.toString())
}.padding(18).backgroundColor('#E7D5B4').borderRadius(24)
ForEach(this.positions, (position: number) => {
Row() {
Text(this.roles[position]).layoutWeight(1)
Text(this.result.labels[position])
}.width('100%').padding(12).backgroundColor('#FFFFFF')
}, (position: number) => position.toString())
Text(`${formatOhms(this.result.ohms)} ±${this.result.tolerance}%`)
.fontSize(30).fontColor('#18796C')
Text(`${Number(this.result.low.toFixed(4))}–${Number(this.result.high.toFixed(4))} Ω`)
.fontSize(18)
Button('切换倍率').onClick(() => { this.changeMultiplier(); })
Text(this.message).fontSize(14)
}.padding(20).width('100%').constraintSize({ maxWidth: 520 })
}.width('100%').height('100%').backgroundColor('#F4F9F6')
}
}

更新时先在局部变量中得到完整结果,再提交页面状态。发生校验异常时,旧输入和旧结果继续对应,提示文本说明本次失败原因。若以后换成允许编辑任意颜色的表单,则需要增加草稿输入和已确认结果两个层次,明确提示“待计算”,不能让新草稿的色带搭配旧阻值。
手机上的纵向布局把四个角色逐行展开,避免把四个下拉控件压在同一窄行里。色带只是辅助信息,色名和角色文字始终可读,不能要求使用者靠色觉完成全部操作。较宽窗口采用相同数据模型,后续可以将选择区和结果区并排放置,而计算入口继续只接收颜色代码。
调试围绕角色和单位展开
恢复初始输入后,标称值应为一千欧姆,误差百分之五,上下限分别为九百五十和一千零五十。点击切换倍率,第三环变橙,标称值变为一万欧姆,范围变为九千五百至一万零五百;再次点击回到初始状态。若误差百分比也跟着变化,应检查是否误用了第三环规则。
在函数入口另行检查棕黑金金,标称值应为一欧姆,上下限为零点九五和一点零五。这一条件专门区分合法的负倍率指数与非法数字角色。将首环改为金色,或者把第四环改为黑色,应进入不同位置的失败路径;输入不足四环时,数量检查先失败,不应尝试读取不存在的数组项。

这条工程主线把颜色、角色与数值分开:规则表表达可用组合,计算层产生统一欧姆数值,界面层再组织色名和显示单位。下一篇增加角色感知的选项过滤时,仍保留计算层的校验,因为界面筛选不能代替数据入口的约束。
规则扩展应保留已有输入的含义
规则表不是把所有器件规格一次性装进页面的清单,而是当前四环入口的明确约定。以后增加五环模式时,前三环将共同组成有效数字,原来第三环的倍率角色会后移。因此保存记录时除了四个颜色代码,还需要保存模式。缺少模式的数组即使长度足够,也不能直接套用另一个解码函数。旧记录应由对应模式读取,不随当前界面的选项自动改变解释方式。
误差的显示也要避免产生额外精度。标称值写成一千欧姆,误差写成百分之五,说明的是编码参数;把结果增加到很多小数位,并不会让器件参数变得更精确。页面应清楚区分标称值、上下限和后续可能接入的测量输入。测量数值有自己的单位、采集时间和来源,不能覆盖颜色解码得到的标称值。
调试输入时可将四个颜色代码、位置角色和计算后的欧姆数值分别观察。若界面显示一点零零千欧姆,而内部值只有一,则问题在单位转换之前;若内部是一千但显示一千千欧姆,则是格式化层重复转换。沿着这条数据链逐层检查,比在按钮事件中同时调整颜色、倍率和显示文本更容易找出错误,也能为下一篇的选择器过滤建立稳定的回归样本。
相关官方资料
更多推荐

所有评论(0)