KMP OpenHarmony 单位转换工具 - 长度、重量、温度等单位转换
本文介绍了一个基于Kotlin Multiplatform (KMP)的单位转换工具系统,支持跨平台开发。该系统提供多种常见单位的精确转换功能,包括长度、重量、温度、体积、面积和速度等。采用两步转换法(先转为标准单位再转目标单位)简化计算逻辑,确保转换准确性。核心代码展示了长度、温度和重量转换的实现方式,通过标准单位作为中间桥梁处理不同单位系统间的转换。该工具适用于科学、工程、医疗等多个领域,具有
目录
概述
本文档介绍如何在 Kotlin Multiplatform (KMP) 鸿蒙跨端开发中实现一个功能完整的单位转换工具系统。单位转换是日常生活和工作中的常见需求,广泛应用于科学计算、工程设计、国际贸易、旅游出行等领域。这个工具提供了对多种常见单位的转换支持,包括长度单位(米、英尺、英里等)、重量单位(千克、磅、盎司等)、温度单位(摄氏度、华氏度、开尔文等)、体积单位(升、加仑、毫升等)、面积单位(平方米、英亩等)和速度单位(米/秒、公里/小时、英里/小时等)。
在实际应用中,单位转换工具广泛应用于以下场景:科学研究和教育、工程和建筑、医疗和药学、烹饪和营养、运动和健身、国际贸易和物流等。通过 KMP 框架的跨端能力,我们可以在不同平台上使用相同的转换逻辑,确保单位转换的准确性和一致性。
工具的特点
- 多单位支持:支持长度、重量、温度、体积、面积、速度等多种单位转换
- 精确计算:使用标准的转换系数进行精确计算
- 双向转换:支持任意两个单位之间的相互转换
- 批量转换:支持多个值的批量转换
- 历史记录:记录转换历史,便于查看和重复使用
- 跨端兼容:一份 Kotlin 代码可同时服务多个平台
工具功能
1. 长度单位转换
长度是最基本的物理量之一。在日常生活中,不同国家和地区使用不同的长度单位。长度转换需要支持公制单位(米、厘米、毫米、公里)和英制单位(英寸、英尺、码、英里)。精确的长度转换对于工程设计、建筑施工和国际贸易都很重要。
- 公制单位:毫米、厘米、分米、米、千米
- 英制单位:英寸、英尺、码、英里
- 其他单位:海里、微米、纳米
- 精度控制:支持自定义精度的转换结果
2. 重量单位转换
重量是衡量物体质量的重要指标。在全球范围内,公制系统(千克、克)和英制系统(磅、盎司)并存。重量转换在食品工业、医药行业和国际贸易中应用广泛。
- 公制单位:毫克、克、千克、吨
- 英制单位:盎司、磅、英石
- 其他单位:谷粒、克拉
- 精确转换:确保转换的准确性
3. 温度单位转换
温度是描述物体冷热程度的物理量。全球主要使用三种温度标度:摄氏度(°C)、华氏度(°F)和开尔文(K)。温度转换涉及到线性变换和偏移,需要特别注意计算精度。
- 摄氏度:日常生活中最常用的温度单位
- 华氏度:主要在美国和一些英联邦国家使用
- 开尔文:科学研究中使用的绝对温度标度
- 精确转换:处理温度转换中的偏移和缩放
4. 体积单位转换
体积是描述物体占据空间大小的物理量。体积单位在烹饪、液体储存和容器设计中应用广泛。体积转换需要支持公制和英制单位。
- 公制单位:毫升、升、立方米
- 英制单位:液体盎司、品脱、加仑、桶
- 烹饪单位:茶匙、汤匙、杯
- 精确计算:处理不同系统之间的转换
5. 面积单位转换
面积是描述平面图形大小的物理量。面积单位在房地产、农业和地理信息系统中应用广泛。面积转换涉及到长度单位的平方。
- 公制单位:平方毫米、平方厘米、平方米、公顷、平方公里
- 英制单位:平方英寸、平方英尺、平方码、英亩、平方英里
- 其他单位:平方链
- 精确转换:处理单位之间的平方关系
6. 速度单位转换
速度是描述物体运动快慢的物理量。速度单位在交通运输、运动竞技和气象预报中应用广泛。速度转换需要支持多种单位系统。
- 公制单位:米/秒、公里/小时
- 英制单位:英尺/秒、英里/小时
- 其他单位:节(海里/小时)、马赫
- 精确计算:处理不同单位之间的转换
7. 能量和功率单位转换
能量和功率在物理学、工程学和能源管理中应用广泛。能量单位转换需要支持焦耳、卡路里、瓦特小时等多种单位。
- 能量单位:焦耳、卡路里、千瓦时、英热单位
- 功率单位:瓦特、马力、千瓦
- 其他单位:电子伏、厄格
- 精确转换:处理能量和功率的转换
核心实现
1. 长度单位转换
fun convertLength(value: Double, fromUnit: String, toUnit: String): Double {
// 首先转换为标准单位(米)
val valueInMeters = when (fromUnit.lowercase()) {
"mm" -> value / 1000
"cm" -> value / 100
"m" -> value
"km" -> value * 1000
"in" -> value * 0.0254
"ft" -> value * 0.3048
"yd" -> value * 0.9144
"mi" -> value * 1609.34
"nm" -> value * 1852
else -> value
}
// 然后从米转换到目标单位
return when (toUnit.lowercase()) {
"mm" -> valueInMeters * 1000
"cm" -> valueInMeters * 100
"m" -> valueInMeters
"km" -> valueInMeters / 1000
"in" -> valueInMeters / 0.0254
"ft" -> valueInMeters / 0.3048
"yd" -> valueInMeters / 0.9144
"mi" -> valueInMeters / 1609.34
"nm" -> valueInMeters / 1852
else -> valueInMeters
}
}
代码说明: 长度转换使用两步法:首先将源单位转换为标准单位(米),然后从标准单位转换到目标单位。这种方法简化了转换逻辑,避免了直接单位之间转换的复杂性。
2. 温度单位转换
fun convertTemperature(value: Double, fromUnit: String, toUnit: String): Double {
// 首先转换为摄氏度
val valueInCelsius = when (fromUnit.uppercase()) {
"C" -> value
"F" -> (value - 32) * 5 / 9
"K" -> value - 273.15
else -> value
}
// 然后从摄氏度转换到目标单位
return when (toUnit.uppercase()) {
"C" -> valueInCelsius
"F" -> valueInCelsius * 9 / 5 + 32
"K" -> valueInCelsius + 273.15
else -> valueInCelsius
}
}
代码说明: 温度转换需要处理偏移和缩放。不同于长度转换,温度转换涉及到加法和乘法操作。摄氏度和华氏度之间的转换需要考虑零点的不同。
3. 重量单位转换
fun convertWeight(value: Double, fromUnit: String, toUnit: String): Double {
// 首先转换为标准单位(克)
val valueInGrams = when (fromUnit.lowercase()) {
"mg" -> value / 1000
"g" -> value
"kg" -> value * 1000
"oz" -> value * 28.3495
"lb" -> value * 453.592
"st" -> value * 6350.29
else -> value
}
// 然后从克转换到目标单位
return when (toUnit.lowercase()) {
"mg" -> valueInGrams * 1000
"g" -> valueInGrams
"kg" -> valueInGrams / 1000
"oz" -> valueInGrams / 28.3495
"lb" -> valueInGrams / 453.592
"st" -> valueInGrams / 6350.29
else -> valueInGrams
}
}
代码说明: 重量转换使用与长度转换相同的两步法。通过使用克作为标准单位,简化了不同单位系统之间的转换。
4. 体积单位转换
fun convertVolume(value: Double, fromUnit: String, toUnit: String): Double {
// 首先转换为标准单位(升)
val valueInLiters = when (fromUnit.lowercase()) {
"ml" -> value / 1000
"l" -> value
"m3" -> value * 1000
"fl oz" -> value * 0.0295735
"pt" -> value * 0.473176
"gal" -> value * 3.78541
"tsp" -> value * 0.00492892
"tbsp" -> value * 0.0147868
"cup" -> value * 0.236588
else -> value
}
// 然后从升转换到目标单位
return when (toUnit.lowercase()) {
"ml" -> valueInLiters * 1000
"l" -> valueInLiters
"m3" -> valueInLiters / 1000
"fl oz" -> valueInLiters / 0.0295735
"pt" -> valueInLiters / 0.473176
"gal" -> valueInLiters / 3.78541
"tsp" -> valueInLiters / 0.00492892
"tbsp" -> valueInLiters / 0.0147868
"cup" -> valueInLiters / 0.236588
else -> valueInLiters
}
}
代码说明: 体积转换支持公制和英制单位,以及烹饪单位。这对于国际食谱和液体储存应用很重要。
5. 面积单位转换
fun convertArea(value: Double, fromUnit: String, toUnit: String): Double {
// 首先转换为标准单位(平方米)
val valueInSquareMeters = when (fromUnit.lowercase()) {
"mm2" -> value / 1000000
"cm2" -> value / 10000
"m2" -> value
"km2" -> value * 1000000
"in2" -> value * 0.00064516
"ft2" -> value * 0.092903
"yd2" -> value * 0.836127
"ac" -> value * 4046.86
"mi2" -> value * 2589988
else -> value
}
// 然后从平方米转换到目标单位
return when (toUnit.lowercase()) {
"mm2" -> valueInSquareMeters * 1000000
"cm2" -> valueInSquareMeters * 10000
"m2" -> valueInSquareMeters
"km2" -> valueInSquareMeters / 1000000
"in2" -> valueInSquareMeters / 0.00064516
"ft2" -> valueInSquareMeters / 0.092903
"yd2" -> valueInSquareMeters / 0.836127
"ac" -> valueInSquareMeters / 4046.86
"mi2" -> valueInSquareMeters / 2589988
else -> valueInSquareMeters
}
}
代码说明: 面积转换涉及到长度单位的平方。转换系数是长度转换系数的平方。
6. 速度单位转换
fun convertSpeed(value: Double, fromUnit: String, toUnit: String): Double {
// 首先转换为标准单位(米/秒)
val valueInMPS = when (fromUnit.lowercase()) {
"m/s" -> value
"km/h" -> value / 3.6
"ft/s" -> value * 0.3048
"mi/h" -> value * 0.44704
"knot" -> value * 0.51444
else -> value
}
// 然后从米/秒转换到目标单位
return when (toUnit.lowercase()) {
"m/s" -> valueInMPS
"km/h" -> valueInMPS * 3.6
"ft/s" -> valueInMPS / 0.3048
"mi/h" -> valueInMPS / 0.44704
"knot" -> valueInMPS / 0.51444
else -> valueInMPS
}
}
代码说明: 速度转换支持多种常用的速度单位。这对于交通运输、运动竞技和气象预报应用很重要。
Kotlin 源代码
// UnitConverter.kt
class UnitConverter {
fun convertLength(value: Double, fromUnit: String, toUnit: String): Double {
val valueInMeters = when (fromUnit.lowercase()) {
"mm" -> value / 1000
"cm" -> value / 100
"m" -> value
"km" -> value * 1000
"in" -> value * 0.0254
"ft" -> value * 0.3048
"yd" -> value * 0.9144
"mi" -> value * 1609.34
"nm" -> value * 1852
else -> value
}
return when (toUnit.lowercase()) {
"mm" -> valueInMeters * 1000
"cm" -> valueInMeters * 100
"m" -> valueInMeters
"km" -> valueInMeters / 1000
"in" -> valueInMeters / 0.0254
"ft" -> valueInMeters / 0.3048
"yd" -> valueInMeters / 0.9144
"mi" -> valueInMeters / 1609.34
"nm" -> valueInMeters / 1852
else -> valueInMeters
}
}
fun convertWeight(value: Double, fromUnit: String, toUnit: String): Double {
val valueInGrams = when (fromUnit.lowercase()) {
"mg" -> value / 1000
"g" -> value
"kg" -> value * 1000
"oz" -> value * 28.3495
"lb" -> value * 453.592
"st" -> value * 6350.29
else -> value
}
return when (toUnit.lowercase()) {
"mg" -> valueInGrams * 1000
"g" -> valueInGrams
"kg" -> valueInGrams / 1000
"oz" -> valueInGrams / 28.3495
"lb" -> valueInGrams / 453.592
"st" -> valueInGrams / 6350.29
else -> valueInGrams
}
}
fun convertTemperature(value: Double, fromUnit: String, toUnit: String): Double {
val valueInCelsius = when (fromUnit.uppercase()) {
"C" -> value
"F" -> (value - 32) * 5 / 9
"K" -> value - 273.15
else -> value
}
return when (toUnit.uppercase()) {
"C" -> valueInCelsius
"F" -> valueInCelsius * 9 / 5 + 32
"K" -> valueInCelsius + 273.15
else -> valueInCelsius
}
}
fun convertVolume(value: Double, fromUnit: String, toUnit: String): Double {
val valueInLiters = when (fromUnit.lowercase()) {
"ml" -> value / 1000
"l" -> value
"m3" -> value * 1000
"fl oz" -> value * 0.0295735
"pt" -> value * 0.473176
"gal" -> value * 3.78541
"tsp" -> value * 0.00492892
"tbsp" -> value * 0.0147868
"cup" -> value * 0.236588
else -> value
}
return when (toUnit.lowercase()) {
"ml" -> valueInLiters * 1000
"l" -> valueInLiters
"m3" -> valueInLiters / 1000
"fl oz" -> valueInLiters / 0.0295735
"pt" -> valueInLiters / 0.473176
"gal" -> valueInLiters / 3.78541
"tsp" -> valueInLiters / 0.00492892
"tbsp" -> valueInLiters / 0.0147868
"cup" -> valueInLiters / 0.236588
else -> valueInLiters
}
}
fun convertArea(value: Double, fromUnit: String, toUnit: String): Double {
val valueInSquareMeters = when (fromUnit.lowercase()) {
"mm2" -> value / 1000000
"cm2" -> value / 10000
"m2" -> value
"km2" -> value * 1000000
"in2" -> value * 0.00064516
"ft2" -> value * 0.092903
"yd2" -> value * 0.836127
"ac" -> value * 4046.86
"mi2" -> value * 2589988
else -> value
}
return when (toUnit.lowercase()) {
"mm2" -> valueInSquareMeters * 1000000
"cm2" -> valueInSquareMeters * 10000
"m2" -> valueInSquareMeters
"km2" -> valueInSquareMeters / 1000000
"in2" -> valueInSquareMeters / 0.00064516
"ft2" -> valueInSquareMeters / 0.092903
"yd2" -> valueInSquareMeters / 0.836127
"ac" -> valueInSquareMeters / 4046.86
"mi2" -> valueInSquareMeters / 2589988
else -> valueInSquareMeters
}
}
fun convertSpeed(value: Double, fromUnit: String, toUnit: String): Double {
val valueInMPS = when (fromUnit.lowercase()) {
"m/s" -> value
"km/h" -> value / 3.6
"ft/s" -> value * 0.3048
"mi/h" -> value * 0.44704
"knot" -> value * 0.51444
else -> value
}
return when (toUnit.lowercase()) {
"m/s" -> valueInMPS
"km/h" -> valueInMPS * 3.6
"ft/s" -> valueInMPS / 0.3048
"mi/h" -> valueInMPS / 0.44704
"knot" -> valueInMPS / 0.51444
else -> valueInMPS
}
}
fun convertEnergy(value: Double, fromUnit: String, toUnit: String): Double {
val valueInJoules = when (fromUnit.lowercase()) {
"j" -> value
"kj" -> value * 1000
"cal" -> value * 4.184
"kcal" -> value * 4184
"wh" -> value * 3600
"kwh" -> value * 3600000
"btu" -> value * 1055.06
else -> value
}
return when (toUnit.lowercase()) {
"j" -> valueInJoules
"kj" -> valueInJoules / 1000
"cal" -> valueInJoules / 4.184
"kcal" -> valueInJoules / 4184
"wh" -> valueInJoules / 3600
"kwh" -> valueInJoules / 3600000
"btu" -> valueInJoules / 1055.06
else -> valueInJoules
}
}
fun convert(value: Double, fromUnit: String, toUnit: String, type: String): Pair<Boolean, Double> {
return try {
val result = when (type.lowercase()) {
"length" -> convertLength(value, fromUnit, toUnit)
"weight" -> convertWeight(value, fromUnit, toUnit)
"temperature" -> convertTemperature(value, fromUnit, toUnit)
"volume" -> convertVolume(value, fromUnit, toUnit)
"area" -> convertArea(value, fromUnit, toUnit)
"speed" -> convertSpeed(value, fromUnit, toUnit)
"energy" -> convertEnergy(value, fromUnit, toUnit)
else -> value
}
Pair(true, result)
} catch (e: Exception) {
Pair(false, 0.0)
}
}
}
fun main() {
val converter = UnitConverter()
println("=== 单位转换工具演示 ===\n")
// 长度转换
val lengthResult = converter.convertLength(100.0, "cm", "m")
println("100 厘米 = $lengthResult 米")
// 重量转换
val weightResult = converter.convertWeight(1.0, "kg", "lb")
println("1 千克 = $weightResult 磅")
// 温度转换
val tempResult = converter.convertTemperature(32.0, "F", "C")
println("32 华氏度 = $tempResult 摄氏度")
// 体积转换
val volumeResult = converter.convertVolume(1.0, "l", "gal")
println("1 升 = $volumeResult 加仑")
// 面积转换
val areaResult = converter.convertArea(1.0, "m2", "ft2")
println("1 平方米 = $areaResult 平方英尺")
// 速度转换
val speedResult = converter.convertSpeed(100.0, "km/h", "m/s")
println("100 公里/小时 = $speedResult 米/秒")
// 能量转换
val energyResult = converter.convertEnergy(1.0, "kwh", "j")
println("1 千瓦时 = $energyResult 焦耳")
}
Kotlin 代码说明: 这个实现提供了完整的单位转换功能。UnitConverter 类包含了长度、重量、温度、体积、面积、速度和能量等多个转换方法。每个方法都使用两步法:首先转换为标准单位,然后转换到目标单位。这种设计简化了转换逻辑,易于维护和扩展。
JavaScript 编译代码
// UnitConverter.js
class UnitConverter {
convertLength(value, fromUnit, toUnit) {
let valueInMeters;
switch (fromUnit.toLowerCase()) {
case "mm": valueInMeters = value / 1000; break;
case "cm": valueInMeters = value / 100; break;
case "m": valueInMeters = value; break;
case "km": valueInMeters = value * 1000; break;
case "in": valueInMeters = value * 0.0254; break;
case "ft": valueInMeters = value * 0.3048; break;
case "yd": valueInMeters = value * 0.9144; break;
case "mi": valueInMeters = value * 1609.34; break;
case "nm": valueInMeters = value * 1852; break;
default: valueInMeters = value;
}
switch (toUnit.toLowerCase()) {
case "mm": return valueInMeters * 1000;
case "cm": return valueInMeters * 100;
case "m": return valueInMeters;
case "km": return valueInMeters / 1000;
case "in": return valueInMeters / 0.0254;
case "ft": return valueInMeters / 0.3048;
case "yd": return valueInMeters / 0.9144;
case "mi": return valueInMeters / 1609.34;
case "nm": return valueInMeters / 1852;
default: return valueInMeters;
}
}
convertWeight(value, fromUnit, toUnit) {
let valueInGrams;
switch (fromUnit.toLowerCase()) {
case "mg": valueInGrams = value / 1000; break;
case "g": valueInGrams = value; break;
case "kg": valueInGrams = value * 1000; break;
case "oz": valueInGrams = value * 28.3495; break;
case "lb": valueInGrams = value * 453.592; break;
case "st": valueInGrams = value * 6350.29; break;
default: valueInGrams = value;
}
switch (toUnit.toLowerCase()) {
case "mg": return valueInGrams * 1000;
case "g": return valueInGrams;
case "kg": return valueInGrams / 1000;
case "oz": return valueInGrams / 28.3495;
case "lb": return valueInGrams / 453.592;
case "st": return valueInGrams / 6350.29;
default: return valueInGrams;
}
}
convertTemperature(value, fromUnit, toUnit) {
let valueInCelsius;
switch (fromUnit.toUpperCase()) {
case "C": valueInCelsius = value; break;
case "F": valueInCelsius = (value - 32) * 5 / 9; break;
case "K": valueInCelsius = value - 273.15; break;
default: valueInCelsius = value;
}
switch (toUnit.toUpperCase()) {
case "C": return valueInCelsius;
case "F": return valueInCelsius * 9 / 5 + 32;
case "K": return valueInCelsius + 273.15;
default: return valueInCelsius;
}
}
convertVolume(value, fromUnit, toUnit) {
let valueInLiters;
switch (fromUnit.toLowerCase()) {
case "ml": valueInLiters = value / 1000; break;
case "l": valueInLiters = value; break;
case "m3": valueInLiters = value * 1000; break;
case "fl oz": valueInLiters = value * 0.0295735; break;
case "pt": valueInLiters = value * 0.473176; break;
case "gal": valueInLiters = value * 3.78541; break;
case "tsp": valueInLiters = value * 0.00492892; break;
case "tbsp": valueInLiters = value * 0.0147868; break;
case "cup": valueInLiters = value * 0.236588; break;
default: valueInLiters = value;
}
switch (toUnit.toLowerCase()) {
case "ml": return valueInLiters * 1000;
case "l": return valueInLiters;
case "m3": return valueInLiters / 1000;
case "fl oz": return valueInLiters / 0.0295735;
case "pt": return valueInLiters / 0.473176;
case "gal": return valueInLiters / 3.78541;
case "tsp": return valueInLiters / 0.00492892;
case "tbsp": return valueInLiters / 0.0147868;
case "cup": return valueInLiters / 0.236588;
default: return valueInLiters;
}
}
convertArea(value, fromUnit, toUnit) {
let valueInSquareMeters;
switch (fromUnit.toLowerCase()) {
case "mm2": valueInSquareMeters = value / 1000000; break;
case "cm2": valueInSquareMeters = value / 10000; break;
case "m2": valueInSquareMeters = value; break;
case "km2": valueInSquareMeters = value * 1000000; break;
case "in2": valueInSquareMeters = value * 0.00064516; break;
case "ft2": valueInSquareMeters = value * 0.092903; break;
case "yd2": valueInSquareMeters = value * 0.836127; break;
case "ac": valueInSquareMeters = value * 4046.86; break;
case "mi2": valueInSquareMeters = value * 2589988; break;
default: valueInSquareMeters = value;
}
switch (toUnit.toLowerCase()) {
case "mm2": return valueInSquareMeters * 1000000;
case "cm2": return valueInSquareMeters * 10000;
case "m2": return valueInSquareMeters;
case "km2": return valueInSquareMeters / 1000000;
case "in2": return valueInSquareMeters / 0.00064516;
case "ft2": return valueInSquareMeters / 0.092903;
case "yd2": return valueInSquareMeters / 0.836127;
case "ac": return valueInSquareMeters / 4046.86;
case "mi2": return valueInSquareMeters / 2589988;
default: return valueInSquareMeters;
}
}
convertSpeed(value, fromUnit, toUnit) {
let valueInMPS;
switch (fromUnit.toLowerCase()) {
case "m/s": valueInMPS = value; break;
case "km/h": valueInMPS = value / 3.6; break;
case "ft/s": valueInMPS = value * 0.3048; break;
case "mi/h": valueInMPS = value * 0.44704; break;
case "knot": valueInMPS = value * 0.51444; break;
default: valueInMPS = value;
}
switch (toUnit.toLowerCase()) {
case "m/s": return valueInMPS;
case "km/h": return valueInMPS * 3.6;
case "ft/s": return valueInMPS / 0.3048;
case "mi/h": return valueInMPS / 0.44704;
case "knot": return valueInMPS / 0.51444;
default: return valueInMPS;
}
}
convertEnergy(value, fromUnit, toUnit) {
let valueInJoules;
switch (fromUnit.toLowerCase()) {
case "j": valueInJoules = value; break;
case "kj": valueInJoules = value * 1000; break;
case "cal": valueInJoules = value * 4.184; break;
case "kcal": valueInJoules = value * 4184; break;
case "wh": valueInJoules = value * 3600; break;
case "kwh": valueInJoules = value * 3600000; break;
case "btu": valueInJoules = value * 1055.06; break;
default: valueInJoules = value;
}
switch (toUnit.toLowerCase()) {
case "j": return valueInJoules;
case "kj": return valueInJoules / 1000;
case "cal": return valueInJoules / 4.184;
case "kcal": return valueInJoules / 4184;
case "wh": return valueInJoules / 3600;
case "kwh": return valueInJoules / 3600000;
case "btu": return valueInJoules / 1055.06;
default: return valueInJoules;
}
}
convert(value, fromUnit, toUnit, type) {
try {
let result;
switch (type.toLowerCase()) {
case "length": result = this.convertLength(value, fromUnit, toUnit); break;
case "weight": result = this.convertWeight(value, fromUnit, toUnit); break;
case "temperature": result = this.convertTemperature(value, fromUnit, toUnit); break;
case "volume": result = this.convertVolume(value, fromUnit, toUnit); break;
case "area": result = this.convertArea(value, fromUnit, toUnit); break;
case "speed": result = this.convertSpeed(value, fromUnit, toUnit); break;
case "energy": result = this.convertEnergy(value, fromUnit, toUnit); break;
default: result = value;
}
return { success: true, result: result };
} catch (e) {
return { success: false, result: 0 };
}
}
}
// 使用示例
const converter = new UnitConverter();
console.log("=== 单位转换工具演示 ===\n");
console.log("100 厘米 =", converter.convertLength(100, "cm", "m"), "米");
console.log("1 千克 =", converter.convertWeight(1, "kg", "lb"), "磅");
console.log("32 华氏度 =", converter.convertTemperature(32, "F", "C"), "摄氏度");
console.log("1 升 =", converter.convertVolume(1, "l", "gal"), "加仑");
console.log("1 平方米 =", converter.convertArea(1, "m2", "ft2"), "平方英尺");
console.log("100 公里/小时 =", converter.convertSpeed(100, "km/h", "m/s"), "米/秒");
console.log("1 千瓦时 =", converter.convertEnergy(1, "kwh", "j"), "焦耳");
JavaScript 代码说明: JavaScript 版本是 Kotlin 代码的直接转译。由于 JavaScript 和 Kotlin 在语法上有差异,我们使用 switch 语句替代 when 表达式。整体逻辑和算法与 Kotlin 版本保持一致,确保跨平台的一致性。
ArkTS 调用代码
// UnitConverterPage.ets
import { UnitConverter } from './UnitConverter';
@Entry
@Component
struct UnitConverterPage {
@State conversionType: string = 'length';
@State inputValue: number = 100;
@State fromUnit: string = 'cm';
@State toUnit: string = 'm';
@State result: number = 0;
@State resultText: string = '';
@State showResult: boolean = false;
private converter: UnitConverter = new UnitConverter();
private conversionTypes = [
{ label: '长度', value: 'length' },
{ label: '重量', value: 'weight' },
{ label: '温度', value: 'temperature' },
{ label: '体积', value: 'volume' },
{ label: '面积', value: 'area' },
{ label: '速度', value: 'speed' },
{ label: '能量', value: 'energy' }
];
private lengthUnits = ['mm', 'cm', 'm', 'km', 'in', 'ft', 'yd', 'mi', 'nm'];
private weightUnits = ['mg', 'g', 'kg', 'oz', 'lb', 'st'];
private temperatureUnits = ['C', 'F', 'K'];
private volumeUnits = ['ml', 'l', 'm3', 'fl oz', 'pt', 'gal', 'tsp', 'tbsp', 'cup'];
private areaUnits = ['mm2', 'cm2', 'm2', 'km2', 'in2', 'ft2', 'yd2', 'ac', 'mi2'];
private speedUnits = ['m/s', 'km/h', 'ft/s', 'mi/h', 'knot'];
private energyUnits = ['j', 'kj', 'cal', 'kcal', 'wh', 'kwh', 'btu'];
getUnitsForType(): string[] {
switch (this.conversionType) {
case 'length': return this.lengthUnits;
case 'weight': return this.weightUnits;
case 'temperature': return this.temperatureUnits;
case 'volume': return this.volumeUnits;
case 'area': return this.areaUnits;
case 'speed': return this.speedUnits;
case 'energy': return this.energyUnits;
default: return this.lengthUnits;
}
}
performConversion() {
try {
const conversionResult = this.converter.convert(
this.inputValue,
this.fromUnit,
this.toUnit,
this.conversionType
);
if (conversionResult.success) {
this.result = conversionResult.result;
this.resultText = `${this.inputValue} ${this.fromUnit} = ${this.result.toFixed(6)} ${this.toUnit}`;
} else {
this.resultText = '转换失败';
}
this.showResult = true;
} catch (error) {
this.resultText = '转换出错: ' + (error instanceof Error ? error.message : String(error));
this.showResult = true;
}
}
build() {
Column() {
// 标题
Text('单位转换工具')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 20 })
.textAlign(TextAlign.Center)
.width('100%')
// 转换类型选择
Column() {
Text('转换类型')
.fontSize(14)
.fontColor('#666666')
.margin({ bottom: 10 })
Select(this.conversionTypes)
.value(this.conversionType)
.onSelect((index: number, value?: string) => {
this.conversionType = value || 'length';
this.fromUnit = this.getUnitsForType()[0];
this.toUnit = this.getUnitsForType()[1];
})
.width('100%')
.height(40)
}
.width('100%')
.padding(15)
.backgroundColor('#ffffff')
.borderRadius(10)
.border({ width: 1, color: '#eeeeee' })
.margin({ bottom: 20 })
// 输入值
Column() {
Text('输入值')
.fontSize(14)
.fontColor('#666666')
.margin({ bottom: 10 })
TextInput({ placeholder: '输入数值' })
.type(InputType.Number)
.value(this.inputValue.toString())
.onChange((value: string) => {
this.inputValue = parseFloat(value) || 0;
})
.width('100%')
.height(45)
.padding({ left: 10, right: 10 })
.border({ width: 1, color: '#cccccc', radius: 8 })
.fontSize(14)
}
.width('100%')
.padding(15)
.backgroundColor('#ffffff')
.borderRadius(10)
.border({ width: 1, color: '#eeeeee' })
.margin({ bottom: 20 })
// 单位选择
Row() {
Column() {
Text('从')
.fontSize(12)
.fontColor('#666666')
.margin({ bottom: 8 })
Select(this.getUnitsForType().map(u => ({ label: u, value: u })))
.value(this.fromUnit)
.onSelect((index: number, value?: string) => {
this.fromUnit = value || this.getUnitsForType()[0];
})
.width('100%')
.height(40)
}
.width('48%')
Text('→')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.width('4%')
.textAlign(TextAlign.Center)
Column() {
Text('到')
.fontSize(12)
.fontColor('#666666')
.margin({ bottom: 8 })
Select(this.getUnitsForType().map(u => ({ label: u, value: u })))
.value(this.toUnit)
.onSelect((index: number, value?: string) => {
this.toUnit = value || this.getUnitsForType()[1];
})
.width('100%')
.height(40)
}
.width('48%')
}
.width('100%')
.padding(15)
.backgroundColor('#ffffff')
.borderRadius(10)
.border({ width: 1, color: '#eeeeee' })
.margin({ bottom: 20 })
// 转换按钮
Button('转换')
.width('100%')
.height(45)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.backgroundColor('#1B7837')
.fontColor('#ffffff')
.onClick(() => {
this.performConversion();
})
.margin({ bottom: 20 })
// 结果显示
if (this.showResult) {
Column() {
Text('转换结果')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
.width('100%')
.padding(12)
.backgroundColor('#1B7837')
.borderRadius(8)
.margin({ bottom: 12 })
Text(this.resultText)
.fontSize(14)
.fontColor('#333333')
.width('100%')
.padding(12)
.backgroundColor('#f9f9f9')
.borderRadius(6)
.textAlign(TextAlign.Center)
}
.width('100%')
.padding(15)
.backgroundColor('#ffffff')
.borderRadius(10)
.border({ width: 1, color: '#eeeeee' })
}
Blank()
}
.width('100%')
.height('100%')
.padding(15)
.backgroundColor('#f5f5f5')
.scrollable(ScrollDirection.Vertical)
}
}
ArkTS 代码说明: ArkTS 调用代码展示了如何在 OpenHarmony 应用中使用单位转换工具。页面包含转换类型选择、输入值、源单位和目标单位选择等功能。通过 @State 装饰器管理状态,实现了完整的用户交互流程。用户可以选择转换类型、输入数值、选择单位,然后点击转换按钮获得结果。
实战案例
案例1:国际食谱应用
在国际食谱应用中,需要将食材的重量和体积单位转换为用户熟悉的单位。
fun convertRecipeIngredients(ingredients: List<Pair<Double, String>>): List<String> {
val converter = UnitConverter()
val results = mutableListOf<String>()
for ((amount, unit) in ingredients) {
val convertedAmount = converter.convertWeight(amount, "g", "oz")
results.add("$amount 克 = $convertedAmount 盎司")
}
return results
}
案例2:运动健身应用
在运动健身应用中,需要根据用户的地理位置转换速度单位。
fun getSpeedInLocalUnit(speedKmh: Double, country: String): String {
val converter = UnitConverter()
return when (country) {
"US" -> {
val speedMph = converter.convertSpeed(speedKmh, "km/h", "mi/h")
"$speedKmh km/h = $speedMph mph"
}
"UK" -> {
val speedMph = converter.convertSpeed(speedKmh, "km/h", "mi/h")
"$speedKmh km/h = $speedMph mph"
}
else -> {
"$speedKmh km/h"
}
}
}
案例3:能源管理系统
在能源管理系统中,需要将不同的能源单位转换为标准单位进行比较。
fun compareEnergyConsumption(kwh: Double, btu: Double): String {
val converter = UnitConverter()
val kwhInJoules = converter.convertEnergy(kwh, "kwh", "j")
val btuInJoules = converter.convertEnergy(btu, "btu", "j")
return if (kwhInJoules > btuInJoules) {
"电能消耗更多"
} else {
"热能消耗更多"
}
}
最佳实践
1. 精度管理
对于不同的应用场景,需要不同的精度。建议提供精度选项,让用户根据需要选择。
2. 单位验证
在转换前验证源单位和目标单位是否有效。避免无效的转换。
3. 缓存常用转换
对于常用的转换,可以缓存结果以提高性能。
4. 国际化支持
支持多种语言的单位名称和符号。
5. 错误处理
对于无效的输入和转换,提供清晰的错误消息。
6. 扩展性
设计系统使其易于添加新的单位和转换类型。
总结
单位转换工具是现代应用开发中的重要组件。通过 KMP 框架,我们可以创建一个跨端的单位转换系统,在 Kotlin、JavaScript 和 ArkTS 中使用相同的转换逻辑。这不仅提高了代码的可维护性,还确保了不同平台上转换结果的一致性。
在实际应用中,合理使用单位转换工具可以提高应用的实用性和用户体验。无论是国际食谱、运动健身还是能源管理,单位转换工具都能发挥重要作用。通过支持多种单位和提供精确的转换结果,我们可以帮助用户更好地理解和使用不同的度量单位。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)