
前端【免费下载链接】vueuseCollection of essential Vue Composition Utilities for Vue 3项目地址https://gitcode.com/gh_mirrors/vu/vueuse点击查看免费下载导读createProjection是 VueUsevueuse/math包中的一个工厂函数用于将一个数值区间源域source domain中的输入值响应式地映射到另一个数值区间目标域target domain并返回一个可复用的投影器projector函数。本文将以packages/math/createProjection模块的官方文档为主体结合其底层源码、测试用例与配套 demo讲解投影的数学原理、响应式行为、自定义投影器以及useProjection、createGenericProjection等家族函数的使用与取舍帮助你在一行代码内完成数值归一化、坐标换算、范围重映射等常见前端需求。什么是数值域投影在数据处理与可视化场景中我们经常需要把一组数值从一个区间搬到另一个区间例如把滑块的0 ~ 100输入映射为进度条的0% ~ 100%把传感器的-1 ~ 1读数映射为 UI 上的0 ~ 255色值把地图经度-180 ~ 180映射到画布像素坐标。createProjection正是为这类数值线性映射而生的工具。官方文档对其的定义只有一句话Reactive numeric projection from one domain to another.将一个数值域响应式地投影到另一个数值域。关键在于Reactive响应式投影不仅对输入值的变化作出反应还能对源域、目标域本身的变化作出反应这是它区别于普通纯函数的核心价值。基础用法官方文档给出了最简洁的用法示例createProjection接受两个区间返回一个投影器函数该投影器接收一个输入值并返回计算后的映射结果。import { createProjection } from vueuse/math const useProjector createProjection([0, 10], [0, 100]) const input ref(0) const projected useProjector(input) // projected.value 0 input.value 5 // projected.value 50 input.value 10 // projected.value 100运行逻辑非常直观[0, 10]是源域[0, 100]是目标域5恰好位于源域的中点因此被映射到目标域的中点50。从源码签名可以看到返回的投影器是一个高阶函数的组合// packages/math/createProjection/index.ts export function createProjection( fromDomain: MaybeRefOrGetterreadonly [number, number], toDomain: MaybeRefOrGetterreadonly [number, number], projector: ProjectorFunctionnumber, number defaultNumericProjector, ): UseProjectionnumber, number { return createGenericProjection(fromDomain, toDomain, projector) }其中UseProjectionnumber, number的类型定义为// packages/math/createGenericProjection/index.ts export type UseProjectionF, T (input: MaybeRefOrGetterF) ComputedRefT也就是说createProjection(...)调用后得到的useProjector接受一个值或 ref 或 getter 函数作为输入并始终返回一个ComputedRef。这就是示例中projected.value能持续跟随input.value更新的原因。源域与目标域的响应式域本身也可以是 refcreateProjection的签名中fromDomain与toDomain的类型是MaybeRefOrGetterreadonly [number, number]这意味着源域和目标域本身也可以传入 ref 或 getter 函数。底层实现通过 Vue 的toValue统一取值并放在computed中求值见 createGenericProjection 源码export function createGenericProjectionF number, T number( fromDomain: MaybeRefOrGetterreadonly [F, F], toDomain: MaybeRefOrGetterreadonly [T, T], projector: ProjectorFunctionF, T, ): UseProjectionF, T { return (input: MaybeRefOrGetterF) { return computed(() projector(toValue(input), toValue(fromDomain), toValue(toDomain))) } }因此当域的边界如最大值发生变化时投影结果会随之自动重算。这一行为在 createProjection 测试用例 中有非常完整的验证const fromStart shallowRef(0) const fromEnd shallowRef(10) const toRange deepRef[number, number]([50, 100]) const useProjector createProjection( () [fromStart.value, fromEnd.value], // 以 getter 形式提供源域 toRange, // 以 ref 形式提供目标域 ) const input shallowRef(0) const output useProjector(input) expect(output.value).toBe(50) // input0 → 映射到 50 input.value 10 expect(output.value).toBe(100) // input10 → 映射到 100 input.value 5 expect(output.value).toBe(75) // input5 → 映射到 75[50,100] 的中点 fromEnd.value 20 // 源域变为 [0, 20]输入仍为 1 时 expect(output.value).toBe(52.5) // 1 在 [0,20] 中占比 5% → 50 5% * 50 toRange.value [80, 120] // 目标域变为 [80, 120] expect(output.value).toBe(82) // 输入 1 在 [0,20] 占比 5% → 80 5% * 40从测试可以看到无论输入值、源域还是目标域变化输出都会同步更新。这非常适合区间边界由用户或数据驱动的动态场景比如图表缩放、滤波器范围联动等。底层数学原理默认线性投影公式当不传第三个参数时createProjection使用内置的默认投影器defaultNumericProjector其实现就一行线性插值公式见 packages/math/createProjection/index.tsfunction defaultNumericProjector(input: number, from: readonly [number, number], to: readonly [number, number]) { return (input - from[0]) / (from[1] - from[0]) * (to[1] - to[0]) to[0] }逐步拆解这个公式(input - from[0]) / (from[1] - from[0])先把输入值归一化到0 ~ 1的比率。input from[0]时结果为0input from[1]时结果为1* (to[1] - to[0])把归一化比率按目标域跨度放大 to[0]再加上目标域的起点偏移完成平移。例如createProjection([0, 10], [0, 100])且input 5(5 - 0) / (10 - 0) 0.50.5 * (100 - 0) 0 50。这正是文档示例中5 → 50的由来。该公式与标准的线性映射normalization数学完全一致可放心用于归一化、反归一化等场景。自定义投影器让映射不再局限于线性如果默认的线性映射不满足需求例如需要对数映射、指数映射、分段映射或映射到非数值类型createProjection的第三个参数projector允许你完全接管投影逻辑。其类型签名来自 createGenericProjection/index.tsexport type ProjectorFunctionF, T (input: F, from: readonly [F, F], to: readonly [T, T]) Tprojector接收三个参数当前的输入值、源域、目标域返回任意类型的映射结果T。由于createProjection固定了F T number自定义投影器仅需遵循(input: number, from: [number, number], to: [number, number]) number的形状。例如实现一个对数缩放映射import { createProjection } from vueuse/math const logProjector (input: number, from: [number, number], to: [number, number]) { const ratio Math.log(input 1) / Math.log(from[1] 1) return ratio * (to[1] - to[0]) to[0] } const useLogProjector createProjection([0, 100], [0, 1000], logProjector)从源码结构看createProjection本身只是createGenericProjection的一个数字特化包装两者共享同一套响应式计算骨架区别仅在泛型类型参数。因此若你需要把任意类型如字符串、日期、颜色对象的域映射到另一个任意类型应直接使用 createGenericProjection它是createProjection的通用版本对应文档见createProjection与useProjection。家族对比createProjection / useProjection / createGenericProjectionVueUse 的vueuse/math包提供了三个高度相关的函数统一从 packages/math/index.ts 导出它们的分工需要区分清楚函数定位签名要点适用场景createProjection工厂函数返回可复用的投影器createProjection(from, to, projector?)→(input) ComputedRefnumber同一对区间需在多处复用或把区间配置与输入解耦useProjection一次性组合函数直接得到投影结果useProjection(input, from, to, projector?)→ComputedRefnumber单个调用点内一次性的映射需求createGenericProjection通用版工厂支持任意类型域createGenericProjectionF, T(from, to, projector)非数值类型或复杂自定义投影逻辑其中useProjection的实现本质上是把createProjection立即调用一次见 packages/math/useProjection/index.tsexport function useProjection( input: MaybeRefOrGetternumber, fromDomain: MaybeRefOrGetterreadonly [number, number], toDomain: MaybeRefOrGetterreadonly [number, number], projector?: ProjectorFunctionnumber, number, ) { return createProjection(fromDomain, toDomain, projector)(input) }官方文档给出了useProjection的等价用法import { useProjection } from vueuse/math const input ref(0) const projected useProjection(input, [0, 10], [0, 100]) input.value 5 // projected.value 50 input.value 10 // projected.value 100它的测试用例进一步验证了返回值为 ref、支持 getter 输入以及完全响应式见 packages/math/useProjection/index.test.ts// 返回值是一个 ref expect(isRef(useProjection(shallowRef(5), [0, 10], [0, 100]))).toBe(true) // 静态值也可直接传入 expect(useProjection(5, [0, 10], [0, 100]).value).toBe(50) // 响应式更新 const inputRef shallowRef(5) const projection useProjection(inputRef, [0, 10], [0, 100]) inputRef.value 8 expect(projection.value).toBe(80) // getter 函数输入 expect(useProjection(() 5, [0, 10], [0, 100]).value).toBe(50)选择建议如果你只需要在一个组件里做一次映射useProjection最直接如果同一个区间映射逻辑被多个组件或多个输入复用用createProjection创建投影器后共享如果域类型不是数字或投影规则高度定制则使用createGenericProjection。实际应用滑块与区间联动的可交互示例packages/math/useProjection目录下附带了一个 demo.vue展示了最典型的实战形态——源域、目标域和输入均为响应式 ref配合v-model.number与 range 滑块实时联动script setup langts import { useProjection } from vueuse/math import { shallowRef } from vue const from shallowRef[number, number]([0, 10]) const to shallowRef[number, number]([10, 100]) const input shallowRef(0) const output useProjection(input, from, to) /script template div divProjection from [{{ from[0] }}, {{ from[1] }}] to [{{ to[0] }}, {{ to[1] }}]/div div input idinput v-model.numberinput typerange :minfrom[0] :maxfrom[1] /div divInput: {{ input }}/div divOutput: {{ output }}/div /div /template注意模板中{{ output }}直接渲染的就是投影结果——因为它是ComputedRef在模板中会自动解包。滑块的min/max绑定到from域因此拖动滑块时输入值在源域内变化输出值实时显示为目标域中的映射结果。若将from、to也做成可配置的响应式数据就构成了一个完整的区间映射可视化交互组件。小结createProjection是 VueUsevueuse/math中轻量而强大的数值映射工具它用一行线性插值公式完成区间换算通过MaybeRefOrGetter与computed让输入、源域、目标域三者全部响应式联动并支持自定义投影器以满足非线性或类型化映射需求。与useProjection一次性和createGenericProjection泛型版组合使用可以覆盖从简单的滑块换算到复杂数据可视化的各类数值域映射场景。深入阅读 createProjection 源码、createGenericProjection 源码 及其 测试用例即可完全掌握其实现原理与边界行为。赞分享前端【免费下载链接】vueuseCollection of essential Vue Composition Utilities for Vue 3项目地址https://gitcode.com/gh_mirrors/vu/vueuse点击查看免费下载相关推荐在 Vue 3 项目中使用 useArrayFilter 实现响应式数组过滤VueUse 响应式 Array.filter 深度实战在 Vue 3 项目中使用 useArrayFilter 实现响应式数组过滤VueUse 响应式 Array.filter 深度实战 useArrayFiltAI 应用人工智能大模型数字人AI Agent语音前端后端桌面应用移动开发即时通讯3D渲染QuickRecorder macOS 录屏工具完整上手一条命令装好5 分钟录出第一条片QuickRecorder macOS 录屏工具完整上手一条命令装好5 分钟录出第一条片 QuickRecorder 是一款给 macOS 用户用的轻量录屏桌面应用音视频屏幕录制在 Vue 3 项目中用 VueUse useFirestore 实现响应式 Firestore 数据同步在 Vue 3 项目中用 VueUse useFirestore 实现响应式 Firestore 数据同步 本指南围绕 VueUse 生态中的 useFiresAI 应用人工智能大模型数字人AI Agent语音前端后端桌面应用移动开发即时通讯3D渲染上一篇PyInstaller提取实战用pyinstxtractor快速拆解exe拿回.pyc源码下一篇硬盘被复制粘贴撑爆了吗图片去重工具 AntiDupl.NET 完整上手指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考