Skip to content

縮放與置中 API

僅限 comp-hub

$onScaleChange 是由 comp-hub 的預覽環境注入的。它不是標準框架 API,在 comp-hub 之外不存在。對於 Vue 元件,它被新增到 Vue 實例(this.$onScaleChange);對於 React 元件,它作為 prop onScaleChange 傳入。如果您在元件中使用此 API,請確保在 comp-hub 之外執行時對其為 undefined 的情況進行防護。

$onScaleChange 訂閱容器尺寸變化並自動計算縮放與置中樣式,協助內容適應預覽容器。

為什麼需要縮放?

迷你預覽面板空間有限(通常約 300×200),但有些元件會顯示豐富的內容(圖表、表格、複雜表單佈局等)。如果不縮放,迷你面板中只能看到部分區域,無法查看完整元件。縮放 API 讓您可以定義預設的內容尺寸(例如 800×500),並自動將其縮放以適應迷你容器,保持所有內容可見。

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

interface ScaleStyle {
  transform: string       // e.g. "translate(100px, 50px) scale(0.75)"
  transformOrigin: string // always "left top"
}

縮放模式

模式行為
"widthFirst"縮放以適應容器寬度,高度可能溢出
"heightFirst"縮放以適應容器高度,寬度可能溢出
"contain"等比縮放,內容完全可見於容器內(建議預設)
"cover"等比縮放,內容填滿容器(可能裁剪多餘部分)

所有模式都會透過 translate 將內容在容器內置中。

$onScaleChange(params, callback) → 取消訂閱

訂閱容器尺寸變化。回呼會立即以目前的縮放值被呼叫,之後每次容器調整大小時再次呼叫。

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

使用(React)

縮放 API 的 React 版本作為 prop onScaleChange 傳給您的 demo 元件:

jsx
import React, { useEffect, useState } from "react";

const DemoMini = ({ onScaleChange }) => {
  const [scaleStyle, setScaleStyle] = useState({});

  useEffect(() => {
    if (onScaleChange) {
      const unsubscribe = onScaleChange(
        { mode: "contain", width: 800, height: 500 },
        (style) => setScaleStyle(style)
      );
      return unsubscribe; // cleanup on unmount
    }
  }, [onScaleChange]);

  return (
    <div style={scaleStyle}>
      {/* your content */}
    </div>
  );
};

export default DemoMini;

使用(Vue 2 Options API)

vue
<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>

使用(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. 清理訂閱 — 務必在 beforeDestroy / onBeforeUnmount 中呼叫 unsubscribe() 以防止記憶體洩漏
  2. 固定內容尺寸 — 以特定的寬 × 高(例如 800×500)設計您的 demo,讓縮放 API 處理其餘部分
  3. contain 是安全的預設 — 即使在小型面板中也能確保所有內容可見
  4. 為非 comp-hub 環境做防護 — 由於此 API 僅存在於 comp-hub 預覽中,呼叫前務必檢查其是否可用:
js
// 安全呼叫模式
if (this.$onScaleChange) {
  this._unsub = this.$onScaleChange(
    { mode: "contain", width: 800, height: 500 },
    (style) => { this.scaleStyle = style }
  )
}

使用者上傳的元件遵循開源協議