继续编辑:布局、动画与分享

沿用已经能显示数据的仪表,分别练习排列图标、让圆弧随速度过渡,再导出文件或连接电脑编辑。每个例子都说明需要改哪里,以及改完应当看到什么。

布局与样式

先练习把速度旁边加一个图标。下面的完整例子只显示固定数字 78,目的是让布局变化容易观察;它还没有接入实际速度。

外层 HStack 把图标与右侧内容左右排列。右侧 VStack 再把数字和单位上下排列。所以你看到的是两个层次:整行左右排,文字内部上下排。

依次试三个修改:把外层 spacing={12} 改为 24,图标与文字会更远;把内层 spacing={4} 改为 12,数字与单位会更远;把内层 alignment="leading" 改为 "trailing",两行文字会按右侧对齐。

注意两种 Stack 的对齐方向:HStack 的 alignment 管上下对齐,VStack 管左右对齐。不要把 x/y 当成间距:它们只是视觉偏移,不会让旁边的内容重新让位。

布局确定后,再把固定的 78 换成第一篇速度示例中的读取表达式,并在数据设置选择速度。这样每次练习只改变一件事。

function main() {
  return (
    <HStack spacing={12} alignment="center">
      <Symbol name="speedometer" color={$env.accent} />
      <VStack alignment="leading" spacing={4}>
        <Text fontSize={40}>78</Text>
        <Text fontSize={14}>{$env.speedUnit}</Text>
      </VStack>
    </HStack>
  );
}

动画

这个例子把速度换算成一个圆弧角度,再为角度变化加过渡。先在仪表设置里选择基础速度,然后粘贴代码。

speed / 200 得到相对于 200 的比例,限制在 0…1 之后乘以 360,就是当前要画出的角度。例如速度为 50 时角度是 90°,速度为 100 时是 180°。这里的 200 是示例量程,使用的是当前速度单位下的数值,可以根据自己的仪表修改。

startAngle={-90} 把起点放在顶部;sweepAngle 决定从起点扫过多少角度。animations 中的 property: 'sweepAngle' 表示对这个属性的变化做动画:从 90° 变到 180° 时,用 0.25 秒完成过渡。

试着把 duration 改为 1,观察圆弧更慢地跟随新目标。动画不会提高真实数据的采样频率,也不会把圆弧自动变成一段计时动画;必须有新的目标角度才会发生变化。

下面的代码在没有速度时显示横线,不把缺测伪装成零。圆弧只对有效的数字读数绘制。

function main() {
  const speed = $data.current.speed?.value;
  if (speed == null) {
    return (
      <Text fontSize={32} color={$env.foreground}>
        —
      </Text>
    );
  }
  return (
    <Circle
      width={120}
      height={120}
      background="clear"
      stroke={$env.accent}
      lineWidth={8}
      startAngle={-90}
      sweepAngle={Math.max(0, Math.min(1, speed / 200)) * 360}
      animations={[
        { property: 'sweepAngle', duration: 0.25, curve: 'easeOut' },
      ]}
    />
  );
}

导入与分享

先关闭预览并保存仪表,再从已保存仪表的菜单导出。.instrument 包含代码、图片资源与输入定义,可通过系统分享面板发送或存入“文件”。定义中的默认值会导出。本机修改的输入值不会导出。OBD 设备绑定不会导出。

接收者用 CapDrive 打开它,导入后仍需通过 编辑仪表盘 添加到页面。在 输入绑定 中设置自己的数值、文字或选项;OBD 输入则选择接收者设备的相应车辆参数。

分享转速或水温仪表时,应说明需要哪个车辆读数、在哪里绑定。只要保留输入标识符,重新绑定设备就不必修改代码。分享前检查不同尺寸与主题,并核对代码、资源和默认文字中是否含有个人信息。

在电脑上编辑

在电脑上编辑的是手机中当前打开的仪表草稿。先在手机端进入这块仪表的编辑器,再按下面的顺序连接:

  1. 让 iPhone 与电脑连接同一个 Wi-Fi 网络。
  2. 在手机编辑器打开 远程编辑模式,等待出现地址。
  3. 在电脑浏览器输入手机显示的完整地址。不要使用旧会话地址,也不要把电脑的 localhost 当成手机地址。
  4. 保持手机编辑会话打开,在电脑修改一处容易识别的内容,例如字号,然后到手机预览检查变化。
  5. 编辑完成后回到手机保存仪表,并在实际仪表盘确认。

如果地址打不开,先确认两台设备确实在同一网络、手机会话仍在运行。关闭远程编辑、离开编辑器或将 App 切到后台,会停止会话;重新开启后使用手机当前显示的地址。

此连接使用未加密的本地 HTTP,没有独立登录密码。能访问该局域网地址的设备可能读取或修改当前草稿及其资源,也可能查看编辑日志。因此只在可信网络开启,编辑完成后关闭远程编辑并在手机保存。

排查问题

先判断是代码问题还是数据问题

预览直接报错时,先看日志中的行号。检查括号、属性名和数据类型;例如对字符串调用 toFixed 与定位没有信号是两种不同问题。

预览正常、实际仪表没有值时,先检查数据来源。基础速度看定位,OBD 看设备参数列表,再检查仪表选择的数据和读取表达式。不要用一个固定数字替换缺测后就认为连接修好了。

内容挤在一起或被裁掉

先缩小到“一个容器 + 一行文字”,确认可用空间,再逐个放回图标、第二行文字和图形。检查固定宽高、字号和间距。用 Stack 排列内容;需要整体平移、缩放或旋转时再使用 transform。

动画没有效果

先确认目标属性本身真的在变化,再确认 animations.property 指向了这个属性。固定的 sweepAngle={180} 不会因为声明了动画就自行转圈。先用预览中的变化数据验证,再对照实际数据更新。

保存前做一次完整核对

在不同尺寸和明暗主题下检查外观;验证有效零值、缺测和文本读数;关闭预览保存后,再把仪表添加到页面检查实际数据。外观、代码与真实读数都对应上,才算完成这块仪表。

接下来