组件/GlassSurface 玻璃拟态
通用组件

GlassSurface 玻璃拟态

用于渲染带玻璃拟态效果的容器。

该页面由 AI 迁移生成,请谨慎使用

内容已迁移完成,但仍建议结合源码和人工评审结果使用。

GlassSurface 玻璃拟态

用于渲染带玻璃拟态效果的容器。

基础用法

GlassSurface

示例即将加载...
<template>
  <TxGlassSurface :width="360" :height="160" :border-radius="20" :background-opacity="0">
    <div style="padding: 16px; font-weight: 700;">GlassSurface</div>
  </TxGlassSurface>
</template>

参数调节(滑块)

GlassSurface 参数调节

示例即将加载...
<script setup lang="ts">
import { ref } from 'vue'

const width = ref(360)
const height = ref(160)
const borderRadius = ref(20)
const borderWidth = ref(0.08)
const brightness = ref(85)
const opacity = ref(0.9)
const blur = ref(10)
const displace = ref(0.6)
const backgroundOpacity = ref(0.08)
const saturation = ref(1.2)
const distortionScale = ref(-180)
const redOffset = ref(0)
const greenOffset = ref(10)
const blueOffset = ref(20)
const xChannel = ref<'R' | 'G' | 'B'>('R')
const yChannel = ref<'R' | 'G' | 'B'>('G')
const mixBlendMode = ref('difference')

const channels = ['R', 'G', 'B']
const blendModes = [
  'normal',
  'multiply',
  'screen',
  'overlay',
  'darken',
  'lighten',
  'color-dodge',
  'color-burn',
  'hard-light',
  'soft-light',
  'difference',
  'exclusion',
  'hue',
  'saturation',
  'color',
  'luminosity',
  'plus-darker',
  'plus-lighter',
]
</script>

<template>
  <div style="display: flex; flex-direction: column; gap: 16px;">
    <div
      style="
        position: relative;
        border-radius: 16px;
        padding: 20px;
        background:
          radial-gradient(circle at 10% 15%, rgba(255, 208, 164, 0.7), transparent 45%),
          radial-gradient(circle at 86% 20%, rgba(168, 214, 255, 0.7), transparent 46%),
          radial-gradient(circle at 20% 80%, rgba(198, 255, 228, 0.55), transparent 50%),
          linear-gradient(135deg, rgba(255, 255, 255, 0.85), rgba(236, 240, 248, 0.98));
        border: 1px solid rgba(0, 0, 0, 0.06);
        overflow: hidden;
      "
    >
      <div
        style="
          position: relative;
          height: 280px;
          border-radius: 14px;
          overflow: hidden;
          background: rgba(255, 255, 255, 0.5);
        "
      >
        <div
          style="
            height: 100%;
            overflow-y: auto;
            padding: 20px 22px 30px;
            display: flex;
            flex-direction: column;
            gap: 16px;
            font-family: 'Playfair Display', 'Times New Roman', serif;
            color: rgba(0, 0, 0, 0.72);
          "
        >
          <div style="display: flex; align-items: center; gap: 10px;">
            <div
              style="
                padding: 4px 10px;
                border-radius: 999px;
                font-size: 12px;
                letter-spacing: 0.08em;
                text-transform: uppercase;
                background: rgba(255, 255, 255, 0.8);
              "
            >
              Glass Journal
            </div>
            <div style="font-size: 12px; opacity: 0.6;">
              scroll to preview depth
            </div>
          </div>
          <div style="font-size: 18px; font-weight: 600;">
            Light, texture, and a quiet sense of depth
          </div>
          <div style="font-size: 13px; line-height: 1.6; opacity: 0.78;">
            A glass surface should feel breathable. Subtle blur, soft light dispersion, and layered
            gradients turn a flat panel into something you want to hover over.
          </div>
          <div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px;">
            <div
              style="
                height: 120px;
                border-radius: 14px;
                background:
                  linear-gradient(135deg, rgba(255, 255, 255, 0.85), rgba(215, 230, 255, 0.9)),
                  radial-gradient(circle at 20% 20%, rgba(255, 208, 164, 0.7), transparent 55%);
                border: 1px solid rgba(0, 0, 0, 0.08);
              "
            />
            <div
              style="
                height: 120px;
                border-radius: 14px;
                background:
                  linear-gradient(135deg, rgba(255, 255, 255, 0.9), rgba(214, 255, 236, 0.9)),
                  radial-gradient(circle at 80% 20%, rgba(168, 214, 255, 0.7), transparent 55%);
                border: 1px solid rgba(0, 0, 0, 0.08);
              "
            />
          </div>
          <div
            style="
              display: grid;
              grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
              gap: 10px;
              font-family: 'IBM Plex Mono', 'Courier New', monospace;
              font-size: 12px;
            "
          >
            <div style="padding: 10px 12px; border-radius: 10px; background: rgba(255, 255, 255, 0.8);">
              blur: keep it airy
            </div>
            <div style="padding: 10px 12px; border-radius: 10px; background: rgba(255, 255, 255, 0.8);">
              light: soft highlight
            </div>
            <div style="padding: 10px 12px; border-radius: 10px; background: rgba(255, 255, 255, 0.8);">
              tint: warm + cool
            </div>
          </div>
          <div style="height: 120px;" />
        </div>

        <div
          style="
            position: absolute;
            inset: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            pointer-events: none;
          "
        >
          <TxGlassSurface
            :width="width"
            :height="height"
            :border-radius="borderRadius"
            :border-width="borderWidth"
            :brightness="brightness"
            :opacity="opacity"
            :blur="blur"
            :displace="displace"
            :background-opacity="backgroundOpacity"
            :saturation="saturation"
            :distortion-scale="distortionScale"
            :red-offset="redOffset"
            :green-offset="greenOffset"
            :blue-offset="blueOffset"
            :x-channel="xChannel"
            :y-channel="yChannel"
            :mix-blend-mode="mixBlendMode"
          >
            <div
              style="
                padding: 18px 20px;
                display: flex;
                flex-direction: column;
                gap: 6px;
                font-weight: 600;
                color: rgba(0, 0, 0, 0.68);
              "
            >
              <div style="font-size: 16px;">
                GlassSurface
              </div>
              <div style="font-size: 12px; opacity: 0.7;">
                Layered clarity with adjustable optics
              </div>
            </div>
          </TxGlassSurface>
        </div>
      </div>
    </div>

    <div
      style="
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
        gap: 12px 16px;
      "
    >
      <div>
        <div style="font-size: 12px; opacity: 0.72; margin-bottom: 6px;">
          width (px)
        </div>
        <TxSlider v-model="width" :min="200" :max="560" :step="10" show-value />
      </div>
      <div>
        <div style="font-size: 12px; opacity: 0.72; margin-bottom: 6px;">
          height (px)
        </div>
        <TxSlider v-model="height" :min="120" :max="320" :step="10" show-value />
      </div>
      <div>
        <div style="font-size: 12px; opacity: 0.72; margin-bottom: 6px;">
          borderRadius
        </div>
        <TxSlider v-model="borderRadius" :min="0" :max="64" :step="1" show-value />
      </div>
      <div>
        <div style="font-size: 12px; opacity: 0.72; margin-bottom: 6px;">
          borderWidth
        </div>
        <TxSlider v-model="borderWidth" :min="0" :max="0.3" :step="0.01" show-value />
      </div>
      <div>
        <div style="font-size: 12px; opacity: 0.72; margin-bottom: 6px;">
          brightness
        </div>
        <TxSlider v-model="brightness" :min="0" :max="140" :step="1" show-value />
      </div>
      <div>
        <div style="font-size: 12px; opacity: 0.72; margin-bottom: 6px;">
          opacity
        </div>
        <TxSlider v-model="opacity" :min="0" :max="1" :step="0.01" show-value />
      </div>
      <div>
        <div style="font-size: 12px; opacity: 0.72; margin-bottom: 6px;">
          blur (px)
        </div>
        <TxSlider v-model="blur" :min="0" :max="24" :step="1" show-value />
      </div>
      <div>
        <div style="font-size: 12px; opacity: 0.72; margin-bottom: 6px;">
          displace
        </div>
        <TxSlider v-model="displace" :min="0" :max="6" :step="0.1" show-value />
      </div>
      <div>
        <div style="font-size: 12px; opacity: 0.72; margin-bottom: 6px;">
          backgroundOpacity
        </div>
        <TxSlider v-model="backgroundOpacity" :min="0" :max="0.5" :step="0.01" show-value />
      </div>
      <div>
        <div style="font-size: 12px; opacity: 0.72; margin-bottom: 6px;">
          saturation
        </div>
        <TxSlider v-model="saturation" :min="0.5" :max="2.4" :step="0.05" show-value />
      </div>
      <div>
        <div style="font-size: 12px; opacity: 0.72; margin-bottom: 6px;">
          distortionScale
        </div>
        <TxSlider v-model="distortionScale" :min="-600" :max="0" :step="10" show-value />
      </div>
      <div>
        <div style="font-size: 12px; opacity: 0.72; margin-bottom: 6px;">
          redOffset
        </div>
        <TxSlider v-model="redOffset" :min="-80" :max="80" :step="1" show-value />
      </div>
      <div>
        <div style="font-size: 12px; opacity: 0.72; margin-bottom: 6px;">
          greenOffset
        </div>
        <TxSlider v-model="greenOffset" :min="-80" :max="80" :step="1" show-value />
      </div>
      <div>
        <div style="font-size: 12px; opacity: 0.72; margin-bottom: 6px;">
          blueOffset
        </div>
        <TxSlider v-model="blueOffset" :min="-80" :max="80" :step="1" show-value />
      </div>
    </div>

    <div style="display: flex; flex-wrap: wrap; gap: 16px;">
      <label style="display: flex; flex-direction: column; gap: 6px; font-size: 12px; opacity: 0.72;">
        xChannel
        <select v-model="xChannel" style="padding: 6px 8px; border-radius: 8px; border: 1px solid rgba(0,0,0,0.12);">
          <option v-for="channel in channels" :key="channel" :value="channel">
            {{ channel }}
          </option>
        </select>
      </label>
      <label style="display: flex; flex-direction: column; gap: 6px; font-size: 12px; opacity: 0.72;">
        yChannel
        <select v-model="yChannel" style="padding: 6px 8px; border-radius: 8px; border: 1px solid rgba(0,0,0,0.12);">
          <option v-for="channel in channels" :key="channel" :value="channel">
            {{ channel }}
          </option>
        </select>
      </label>
      <label style="display: flex; flex-direction: column; gap: 6px; font-size: 12px; opacity: 0.72; min-width: 180px;">
        mixBlendMode
        <select v-model="mixBlendMode" style="padding: 6px 8px; border-radius: 8px; border: 1px solid rgba(0,0,0,0.12);">
          <option v-for="mode in blendModes" :key="mode" :value="mode">
            {{ mode }}
          </option>
        </select>
      </label>
    </div>
  </div>
</template>

API

Props

属性名类型默认值说明
widthstring | number'200px'宽度
heightstring | number'200px'高度
borderRadiusnumber20圆角
borderWidthnumber0.07边缘强度
brightnessnumber70亮度
opacitynumber0.93玻璃透明度
blurnumber11模糊
displacenumber0.5位移模糊强度
backgroundOpacitynumber0背景透明度
saturationnumber1饱和度
distortionScalenumber-180色散强度
redOffsetnumber0红色通道偏移
greenOffsetnumber10绿色通道偏移
blueOffsetnumber20蓝色通道偏移
xChannel'R' | 'G' | 'B''R'X 轴通道选择
yChannel'R' | 'G' | 'B''G'Y 轴通道选择
mixBlendModestring'difference'混合模式

该组件会根据浏览器能力自动降级(不支持 SVG filter / backdrop-filter 时)。