forked from zhongyidian/super_video
feat: 提示词
This commit is contained in:
1 parent
b980f2993b
commit
6090abf955
15 files changed
+330
-54
No files matched your search
@@ -137,7 +137,7 @@ const positionStyle = computed(() => {
|
||||
}
|
||||
|
||||
.guide-panel {
|
||||
@apply relative bg-white rounded-2xl shadow-2xl;
|
||||
@apply relative bg-white rounded-2xl;
|
||||
/* background: linear-gradient(135deg, #60a5fa 0%, #a855f7 100%);
|
||||
border: 2px solid #60a5fa;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); */
|
||||
@@ -170,7 +170,7 @@ const positionStyle = computed(() => {
|
||||
}
|
||||
|
||||
.guide-content {
|
||||
@apply flex items-start p-6 h-full;
|
||||
@apply flex items-start pl-6 pt-9 pb-0 h-full;
|
||||
}
|
||||
|
||||
.content-icon {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
:target-selector="highlightSelector"
|
||||
:padding="highlightPadding"
|
||||
:border-radius="highlightRadius"
|
||||
:highlight-mode="highlightMode"
|
||||
/>
|
||||
<div class="guide-align" :style="alignStyle">
|
||||
<GuideDragon
|
||||
@@ -73,6 +74,8 @@ interface Props {
|
||||
highlightPadding?: number
|
||||
/** 高亮圆角,默认16 */
|
||||
highlightRadius?: number
|
||||
/** 高亮模式:'border' 画框效果,'gradient' 渐变灯光效果,默认 'border' */
|
||||
highlightMode?: 'border' | 'gradient'
|
||||
/** 垂直偏移(仅Y轴),支持 number(px) 或 '10%'/'120px' */
|
||||
positionOffsetY?: number | string
|
||||
}
|
||||
@@ -91,6 +94,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
highlightSelector: null,
|
||||
highlightPadding: 8,
|
||||
highlightRadius: 16,
|
||||
highlightMode: 'border',
|
||||
positionOffsetY: '50%'
|
||||
})
|
||||
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
<template>
|
||||
<div v-if="visible" class="spotlight-overlay">
|
||||
<!-- 渐变遮罩层 -->
|
||||
<div v-if="props.highlightMode === 'gradient'" class="spotlight-mask" :style="maskStyle"></div>
|
||||
<!-- 画框模式:使用 box-shadow 遮罩 + 边框 -->
|
||||
<div
|
||||
v-if="props.highlightMode === 'border' && rect.width > 0 && rect.height > 0"
|
||||
class="spotlight-hole"
|
||||
:style="{
|
||||
top: rect.top + 'px',
|
||||
left: rect.left + 'px',
|
||||
width: rect.width + 'px',
|
||||
height: rect.height + 'px',
|
||||
borderRadius: borderRadius + 'px',
|
||||
boxShadow: `0 0 0 9999px rgba(0,0,0,0.6)`
|
||||
}"
|
||||
:style="holeStyle"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, watch, onMounted, onBeforeUnmount } from 'vue'
|
||||
import { reactive, computed, watch, onMounted, onBeforeUnmount } from 'vue'
|
||||
|
||||
interface Props {
|
||||
/** 是否可见 */
|
||||
@@ -26,13 +23,19 @@ interface Props {
|
||||
padding?: number
|
||||
/** 圆角 */
|
||||
borderRadius?: number
|
||||
/** 渐变过渡范围(像素) */
|
||||
gradientRange?: number
|
||||
/** 高亮模式:'border' 画框效果,'gradient' 渐变灯光效果 */
|
||||
highlightMode?: 'border' | 'gradient'
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: false,
|
||||
targetSelector: null,
|
||||
padding: 8,
|
||||
borderRadius: 16
|
||||
borderRadius: 16,
|
||||
gradientRange: 100,
|
||||
highlightMode: 'border'
|
||||
})
|
||||
|
||||
const rect = reactive({ top: 0, left: 0, width: 0, height: 0 })
|
||||
@@ -72,7 +75,78 @@ onBeforeUnmount(() => {
|
||||
window.removeEventListener('scroll', onScroll)
|
||||
})
|
||||
|
||||
const borderRadius = props.borderRadius
|
||||
// 计算渐变遮罩样式
|
||||
const maskStyle = computed(() => {
|
||||
if (!props.visible || rect.width === 0 || rect.height === 0) {
|
||||
return {
|
||||
maskImage: 'none',
|
||||
WebkitMaskImage: 'none'
|
||||
}
|
||||
}
|
||||
|
||||
// 计算中心点坐标(相对于视口)
|
||||
const centerX = rect.left + rect.width / 2
|
||||
const centerY = rect.top + rect.height / 2
|
||||
|
||||
// 计算椭圆半径(基于高亮区域)
|
||||
// 使用较大的尺寸作为基准,确保覆盖整个高亮区域
|
||||
const maxDimension = Math.max(rect.width, rect.height)
|
||||
const aspectRatio = rect.width / rect.height
|
||||
|
||||
// 渐变范围
|
||||
const gradientRangeValue = Math.max(0, props.gradientRange)
|
||||
|
||||
// 计算椭圆的半径(考虑宽高比)
|
||||
// 对于椭圆,我们需要分别计算 x 和 y 方向的半径
|
||||
const baseRadius = maxDimension / 2
|
||||
const radiusX = baseRadius + gradientRangeValue
|
||||
const radiusY = (baseRadius + gradientRangeValue) / aspectRatio
|
||||
|
||||
// 高亮区域边缘的半径(椭圆的主轴)
|
||||
const highlightRadius = baseRadius
|
||||
|
||||
// 渐变停止点:从中心透明,到高亮边缘仍透明,然后向外渐变到不透明
|
||||
// 计算渐变停止点的像素值
|
||||
const highlightEdge = highlightRadius // 高亮区域边缘,保持透明
|
||||
const gradientStart = highlightRadius + gradientRangeValue * 0.1 // 渐变开始
|
||||
const gradientMid = highlightRadius + gradientRangeValue * 0.5 // 渐变中间
|
||||
const gradientEnd = highlightRadius + gradientRangeValue // 渐变结束,完全不透明
|
||||
|
||||
// 创建径向渐变遮罩
|
||||
// mask-image 中,transparent 表示遮罩透明(背景可见),black 表示遮罩不透明(背景被遮住)
|
||||
// 我们需要从中心透明(高亮区域可见)渐变到边缘不透明(周围变暗)
|
||||
// 使用平滑的多色停止点创建柔和的渐变效果
|
||||
const gradient = `radial-gradient(
|
||||
ellipse ${radiusX}px ${radiusY}px at ${centerX}px ${centerY}px,
|
||||
transparent 0px,
|
||||
transparent ${highlightEdge}px,
|
||||
rgba(0, 0, 0, 0.2) ${gradientStart}px,
|
||||
rgba(0, 0, 0, 0.5) ${gradientMid}px,
|
||||
rgba(0, 0, 0, 0.9) ${gradientEnd * 0.9}px,
|
||||
black ${gradientEnd}px
|
||||
)`
|
||||
|
||||
return {
|
||||
maskImage: gradient,
|
||||
WebkitMaskImage: gradient
|
||||
}
|
||||
})
|
||||
|
||||
// 计算画框模式样式(box-shadow + 边框)
|
||||
const holeStyle = computed(() => {
|
||||
if (!props.visible || rect.width === 0 || rect.height === 0) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
top: rect.top + 'px',
|
||||
left: rect.left + 'px',
|
||||
width: rect.width + 'px',
|
||||
height: rect.height + 'px',
|
||||
borderRadius: props.borderRadius + 'px',
|
||||
boxShadow: `0 0 0 9999px rgba(0,0,0,0.6)`
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -83,8 +157,26 @@ const borderRadius = props.borderRadius
|
||||
z-index: 100000;
|
||||
}
|
||||
|
||||
.spotlight-hole {
|
||||
.spotlight-mask {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
transition: opacity 0.3s ease-in-out;
|
||||
mask-image: radial-gradient(ellipse, transparent 0%, black 100%);
|
||||
-webkit-mask-image: radial-gradient(ellipse, transparent 0%, black 100%);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.spotlight-hole {
|
||||
position: absolute;
|
||||
border: 2px solid rgba(255, 255, 255, 0.9);
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(0, 0, 0, 0.3),
|
||||
0 0 20px rgba(255, 255, 255, 0.3),
|
||||
0 0 0 9999px rgba(0, 0, 0, 0.6);
|
||||
pointer-events: none;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user