拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Mpx跨端小程序必知:px、rpx、pt单位换算与悬浮窗实现

在跨端小程序开发的“mpx 教程”里最容易让新手卡住的往往不是组件通信或状态管理而是从原型到真机之间的一层单位换算。设计稿标着 20px代码里也写 20px到了不同尺寸的手机上按钮有时偏大有时偏小悬浮窗口更是如此位置和尺寸只要算错一个单位真机上的表现就和原型完全两样。这篇文章围绕 Mpx 跨端小程序框架把 px、rpx、pt 三类单位的关系、悬浮窗的典型尺寸、可拖拽实现和常见排查思路完整过一遍最后会给你一份可以直接复用的发布前检查清单。读完你会形成一套适合自己的单位换算表以及一个能跑在微信开发者工具里的悬浮窗代码模板。标题里的“双金”如果拆成工程语言来看就是两个指标原型产出效率高真机运行稳定性好。Mpx 在这两点上的优势恰好取决于你是否把“设计稿里的 px 到小程序里的 rpx/px”这条链路处理稳。这个环节一旦稳了后面做悬浮窗、弹层、吸底按钮都会顺畅很多。1. Mpx 与 px先把原型和真机之间的“单位差”补齐1.1 Mpx 是什么为什么原型验证阶段值得用它Mpx 是一套使用 Vue 语法的小程序跨端框架。它可以同时产出微信、支付宝等小程序平台代码并支持通过构建配置扩展到更多端。在原型验证阶段Mpx 的写法接近 Vue写起来比原生小程序快在正式发布阶段又能通过编译配置尽量复用业务代码。这里不把它说成“最好”的方案但如果你已经熟悉 Vue又想保留小程序原生的性能习惯Mpx 是一个值得评估的选择。Mpx 的几个关键特征页面使用.mpx单文件组织模板、脚本、样式放在同一个文件里和 Vue 的单文件组件类似。提供createPage、createComponent等 API组件化能力和原生小程序兼容。一套业务代码可以编译出多端产物但不同平台的小程序仍有各自的边界需要单独验证。先理解这一点很重要Mpx 不是把小程序变成 H5而是尽量让你用接近 Web 的开发方式去写原生小程序。所以凡是小程序平台自己约定好的单位规则最终还是会由小程序运行时来解释。1.2 为什么原型设计稿里的 px 不能直接照搬设计稿里的 px 是设计工具里的像素标注通常基于一个固定宽度的画板比如 375 或 750。小程序里的 px 是 CSS 逻辑像素在不同设备上这个“1px”对应的物理像素数是不一样的。举个例子设计稿宽度 375px一个按钮标注 20px。在 iPhone SE 这类逻辑宽度 375px 的设备上写width: 20px视觉比例正好。在逻辑宽度 390px 或 414px 的设备上写width: 20px按钮占屏比例会偏小。如果希望按钮在不同宽度的屏幕上保持“占屏比例一致”就需要使用 rpx。小程序的 rpx 把屏幕宽度定义为 750rpx所以rpx 设计稿标注值 × 750 / 设计稿宽度设计稿宽度是 375 时20px标注对应40rpx。这样设计稿里 20px 的元素在 375 宽手机上等于 20px在 390 宽手机上会自动放大到约 20.8px。虽然视觉上“绝对像素”变了但相对屏幕宽度的比例没变这才是原型稿希望达到的适配效果。1.3 px、rpx、pt 的换算关系表在 Mpx 项目里你至少会遇到三类单位单位含义常见来源使用建议pxCSS 逻辑像素相对固定设计稿、CSS 样式、绘制工具适合边框、阴影、固定尺寸的触控按钮rpx小程序响应式像素750rpx 屏幕宽度小程序样式、设计稿换算适合宽度、间距、字号等需要随屏幕等比例变化的场景ptiOS 逻辑点常见于设计标注和导图iOS 设计稿、Figma/Sketch 标注布局按 1pt 约等于 1 个 CSS px 理解导图按物理像素处理这里需要特别注意pt 和物理像素不是一回事。iPhone 的逻辑宽度是 375pt物理像素可能达到 750 或 1125。设计稿里的 20pt 对应到 CSS 逻辑尺寸可以理解为 20px但导出位图时需要按 2x 或 3x 生成 40px 或 60px 的物理图片。1.4 Mpx 里单位处理的默认边界在 Mpx 项目中样式中的单位最终由小程序运行时解释。rpx 在微信小程序端原生生效但 Mpx 本身不会自动把每个 px 变成 rpx。项目里需要达成一个约定布局尺寸、间距、字体大小优先使用 rpx。固定定位的悬浮按钮、边框宽度、圆角、阴影、1px 分割线这类不随屏幕比例变化的样式优先使用 px。如果编译目标包含 H5rpx 在小程序端之外不一定自动生效需要单独检查构建配置。这个约定的核心是“哪些元素应该等比缩放哪些元素应该保持稳定触控尺寸”。悬浮窗就是典型场景可拖动区域和触控按钮需要稳定的操作尺寸但悬浮窗离屏幕边界的距离又希望在多端之间有统一表现所以哪部分用 px、哪部分用 rpx必须提前定好。2. 从零搭一个 Mpx 项目先把环境跑通2.1 环境依赖和版本要求开始写代码之前先确认本地环境。以下配置在常见 Mpx 项目里可用依赖版本建议说明Node.js16 或 18 LTS版本过旧会导致依赖安装失败npm / pnpmnpm 8 或 pnpm 7包管理器按团队习惯选择微信开发者工具稳定版即可用于导入和预览小程序Mpx CLI以官方版本为准创建项目脚手架不同 Mpx CLI 版本存在命令差异。如果下面命令在你的环境里不可用先查一次mpx --help以本机安装版本的提示为准。2.2 创建项目并查看目录结构使用 Mpx CLI 创建项目npm i -g mpxjs/cli mpx create mpx-px-demo cd mpx-px-demo npm install创建出来的项目结构大致如下mpx-px-demo/ ├── src/ │ ├── app.mpx │ └── pages/ │ └── index/ │ └── index.mpx ├── mpx.config.js ├── package.json └── project.config.json其中src/app.mpx是应用入口src/pages/index/index.mpx是一个页面。.mpx文件把模板、逻辑和样式放在一起和 Vue 单文件组件非常接近。实际目录结构以脚手架生成为准重点是把src/pages/index/index.mpx找到后续所有演示代码都写在这个文件里。2.3 改写首页加入一个悬浮窗占位先跑一个最小页面确认 Mpx 项目本身没问题。把src/pages/index/index.mpx改成下面这样template view classpage view classfloat-box悬浮/view /view /template script import { createPage } from mpxjs/core createPage({ data: { title: Mpx px 演示 } }) /script style .page { height: 100vh; background: #f5f6fa; } .float-box { position: fixed; left: 30px; top: 260px; width: 80px; height: 80px; background: #1677ff; color: #ffffff; border-radius: 40px; line-height: 80px; text-align: center; box-shadow: 0 8px 24px rgba(22, 119, 255, 0.3); z-index: 999; } /style这段代码解决的问题是验证.mpx页面能否正常渲染、position: fixed是否生效、px单位在小程序里是否能直接使用。2.4 如何确认项目已经可运行查看package.json里的 scripts确认本地启动命令。常见命令有两种npm run serve或npm run dev:mp-weixin运行后用微信开发者工具导入项目根目录AppID 可以选择测试号。导入成功后模拟器里应该能看到一个蓝色的圆形悬浮按钮。如果页面正常显示说明 Mpx 项目已经跑通。还有一个小检查点把模拟器切换到 iPhone SE 和 iPhone 15 Pro观察悬浮按钮的位置差异。此时按钮写法用的全是 px所以在不同宽度设备上位置不会自动按比例变化。这个现象正是后面要重点处理的。3. 实现一个带 px 换算的悬浮窗3.1 悬浮窗需求拆解把一个悬浮窗做好至少需要处理四件事初始位置打开页面后悬浮窗出现在哪里。拖拽能力用户按住后可以移动松手后停在当前位置。边界限制不能拖出屏幕至少不能拖到完全不可见。尺寸适配宽高在真机上是否容易点按内容型悬浮窗是否遮挡主要操作区。在很多业务里悬浮窗还会加“展开/收起”“关闭”“停留记忆”等能力。这里先实现一个最小闭环一个 80px 的圆形按钮可以拖动且不会超过屏幕边界。3.2 模板结构用 data 驱动坐标改写成可拖动悬浮窗模板部分需要绑定坐标并监听触摸事件template view classpage view classfloat-box :styleboxStyle touchstartonTouchStart touchmoveonTouchMove touchendonTouchEnd text classfloat-text拖/text /view /view /template这里的boxStyle会由 data 动态生成。之所以用内联样式更新位置是因为悬浮窗的位置经常变化不适合写在静态样式表里。3.3 样式什么时候用 rpx什么时候用 px样式部分继续使用 px 控制固定尺寸.float-box { position: fixed; width: 80px; height: 80px; background: #1677ff; color: #ffffff; border-radius: 40px; display: flex; align-items: center; justify-content: center; box-shadow: 0 8px 24px rgba(22, 119, 255, 0.3); z-index: 999; } .float-text { font-size: 14px; line-height: 1; }这里的width、height、border-radius、font-size都使用 px。原因很简单悬浮按钮是操作控件它的可点击面积不能随屏幕宽度无限缩放太小时容易点不中太大时又遮挡页面内容。对操作类悬浮物优先保证稳定的触控尺寸。页面间距、列表卡片宽度这类“随屏宽变化”的元素才适合用 rpx。比如页面两侧留白可以写padding: 0 32rpx在 375 宽手机上等于 16px在 390 宽手机等于约 16.64px视觉比例一致。3.4 触摸事件拖动、边界限制和尺寸计算下面是完整的页面对应逻辑script import { createPage } from mpxjs/core createPage({ data: { left: 30, top: 260, startX: 0, startY: 0, boxStyle: left: 30px; top: 260px; }, methods: { onTouchStart (e) { const touch e.touches[0] // 记录手指在悬浮窗内部的偏移量 this.startX touch.clientX - this.left this.startY touch.clientY - this.top }, onTouchMove (e) { const width 80 const height 80 // 兼容新旧版本基础库 const win wx.getWindowInfo ? wx.getWindowInfo() : wx.getSystemInfoSync() const touch e.touches[0] let left touch.clientX - this.startX let top touch.clientY - this.startY // 限制边界避免悬浮窗被拖出屏幕 left Math.min(Math.max(left, 0), win.windowWidth - width) top Math.min(Math.max(top, 0), win.windowHeight - height) this.left left this.top top this.boxStyle left: left px; top: top px; }, onTouchEnd () { // 这里可以记录最终坐标后续用于本地缓存 } } }) /script关键点有三个startX和startY必须记录手指在按钮内部的位置否则拖动时按钮会“跳到手指位置”产生明显的偏移感。边界限制使用Math.min和Math.max保证left不小于 0且不超过屏幕宽度减去按钮宽度。wx.getWindowInfo是较新的 API如果基础库版本较低需要回退到wx.getSystemInfoSync。这段代码没有把 rpx 混进坐标计算因为触摸事件给的是clientX和clientY单位是 CSS px。如果强行把left和top存成 rpx计算边界时还得先转回 px反而容易出错。3.5 悬浮窗口到底设多少 px“悬浮窗口一般设多少px”这个问题不能只看视觉效果还要考虑手指触控和系统安全区。常见参考值如下场景推荐尺寸说明圆形悬浮按钮56px 直径触控区不小于 44px小于 40px 会明显增加误触概率可拖动内容悬浮窗宽度 300~360px高度不超过屏幕 70%高度过高会遮挡主内容必须留关闭按钮吸底操作栏高度 56px 安全区宽度撑满适配 iPhone 底部黑条悬浮窗边缘留白
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门