通用组件
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
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
width | string | number | '200px' | 宽度 |
height | string | number | '200px' | 高度 |
borderRadius | number | 20 | 圆角 |
borderWidth | number | 0.07 | 边缘强度 |
brightness | number | 70 | 亮度 |
opacity | number | 0.93 | 玻璃透明度 |
blur | number | 11 | 模糊 |
displace | number | 0.5 | 位移模糊强度 |
backgroundOpacity | number | 0 | 背景透明度 |
saturation | number | 1 | 饱和度 |
distortionScale | number | -180 | 色散强度 |
redOffset | number | 0 | 红色通道偏移 |
greenOffset | number | 10 | 绿色通道偏移 |
blueOffset | number | 20 | 蓝色通道偏移 |
xChannel | 'R' | 'G' | 'B' | 'R' | X 轴通道选择 |
yChannel | 'R' | 'G' | 'B' | 'G' | Y 轴通道选择 |
mixBlendMode | string | 'difference' | 混合模式 |
该组件会根据浏览器能力自动降级(不支持 SVG filter / backdrop-filter 时)。