Skip to content

缩放与居中 API

仅限 comp-hub 环境

$getScaleStyle$onScaleChangecomp-hub 预览环境注入的方法不是标准 Vue API,在本地真实工程环境中不存在。如果在组件中使用了这些 API,请做好判空处理,避免在 comp-hub 之外运行时出错。

在预览面板中,comp-hub 会为你的组件 Vue 实例提供两个方法,帮助内容自适应预览容器:

  • $getScaleStyle — 主动查询当前的缩放与位移样式
  • $onScaleChange — 订阅容器尺寸变化,自动获取最新样式

$getScaleStyle(params) → Style

同步获取基于内容尺寸与缩放模式计算出的缩放 + 居中样式。

ts
type ScaleMode = "widthFirst" | "heightFirst" | "contain" | "cover"

interface ScaleStyle {
  transform: string       // 例如 "translate(100px, 50px) scale(0.75)"
  transformOrigin: string // 固定为 "left top"
}

this.$getScaleStyle({
  mode: ScaleMode    // 缩放模式
  width: number      // 组件内容宽度(px)
  height: number     // 组件内容高度(px)
}): ScaleStyle

使用示例(Vue 2 Options API)

vue
<template>
  <div :style="$getScaleStyle({ mode: 'contain', width: 800, height: 500 })">
    <!-- 组件内容 -->
  </div>
</template>

使用示例(Vue 3 Composition API)

ts
import { getCurrentInstance } from "vue"

const instance = getCurrentInstance()
const scaleStyle = instance.proxy.$getScaleStyle({
  mode: "contain",
  width: 800,
  height: 500
})

缩放模式说明

模式行为
"widthFirst"按容器宽度缩放,高度可能溢出
"heightFirst"按容器高度缩放,宽度可能溢出
"contain"等比例缩放,内容始终完整可见(默认推荐)
"cover"等比例缩放,填满容器(可能裁切超出部分)

所有模式均通过 translate 将内容居中于容器内。

$onScaleChange(params, callback) → unsubscribe

订阅容器尺寸变化。注册时立即回调一次当前 scale,之后容器大小变化时自动回调最新值。

ts
const unsubscribe = this.$onScaleChange(
  params: { mode: ScaleMode, width: number, height: number },
  callback: (style: ScaleStyle) => void
): () => void

使用示例(Vue 2 Options API)

vue
<script>
export default {
  data() {
    return { scaleStyle: {} }
  },
  mounted() {
    // 保存内容尺寸
    this.contentSize = { width: 800, height: 500 }

    // 订阅 — 容器缩放时自动重新计算
    this._unsub = this.$onScaleChange(
      { mode: "contain", width: 800, height: 500 },
      (style) => { this.scaleStyle = style }
    )
  },
  beforeDestroy() {
    this._unsub?.() // 取消订阅,防止内存泄漏
  }
}
</script>

使用示例(Vue 3 Composition API)

vue
<script setup>
import { ref, getCurrentInstance, onBeforeUnmount } from "vue"

const instance = getCurrentInstance()
const scaleStyle = ref({})

const unsub = instance.proxy.$onScaleChange(
  { mode: "contain", width: 800, height: 500 },
  (style) => { scaleStyle.value = style }
)

onBeforeUnmount(() => unsub())
</script>

常见模式

固定内容尺寸的 demo 组件

预览 demo 组件通常预设一个固定内容区域,再通过缩放 API 自适应预览面板:

vue
<template>
  <div class="demo-wrapper" :style="scaleStyle">
    <!-- 按照 800×500 设计的内容 -->
    <div class="demo-content">...</div>
  </div>
</template>

<script>
export default {
  data() {
    return { scaleStyle: {} }
  },
  mounted() {
    this._unsub = this.$onScaleChange(
      { mode: "contain", width: 800, height: 500 },
      (style) => { this.scaleStyle = style }
    )
  },
  beforeDestroy() {
    this._unsub?.()
  }
}
</script>

<style scoped>
.demo-wrapper {
  transform-origin: left top;
}
.demo-content {
  width: 800px;
  height: 500px;
  overflow: hidden;
}
</style>

最佳实践

  1. 订阅优于轮询 — 使用 $onScaleChange 响应容器变化,避免反复调用 $getScaleStyle
  2. 及时取消订阅 — 在 beforeDestroy / onBeforeUnmount 中调用 unsubscribe(),防止内存泄漏
  3. 预设固定尺寸 — 将 demo 内容设计为固定宽高(如 800×500),缩放交给 API 处理
  4. contain 是默认安全选择 — 确保内容在小型预览面板中也完整可见
  5. 判空保护非 comp-hub 环境 — 这些 API 仅在 comp-hub 预览中存在,调用前务必检查可用性:
js
// 安全的调用方式
if (this.$getScaleStyle) {
  this.scaleStyle = this.$getScaleStyle({ mode: "contain", width: 800, height: 500 })
}

if (this.$onScaleChange) {
  this._unsub = this.$onScaleChange(
    { mode: "contain", width: 800, height: 500 },
    (style) => { this.scaleStyle = style }
  )
}

用户上传的组件遵循开源协议