bugfix: 语音输入动画重复初始化
This commit is contained in:
1
src/assets/icons/pause.svg
Normal file
1
src/assets/icons/pause.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg t="1760927343641" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5713" width="200" height="200"><path d="M512 51.2c254.08 0 460.8 206.72 460.8 460.8s-206.72 460.8-460.8 460.8S51.2 766.08 51.2 512 257.92 51.2 512 51.2M512 0C229.248 0 0 229.248 0 512s229.248 512 512 512 512-229.248 512-512S794.752 0 512 0L512 0z" fill="currentColor" p-id="5714"></path><path d="M741.312 700.352c0 16-12.928 28.992-28.928 28.992L311.616 729.344c-16 0-28.928-12.992-28.928-28.992L282.688 299.648c0-16 12.928-28.864 28.928-28.864l400.768 0c16 0 28.928 12.864 28.928 28.864L741.312 700.352z" fill="currentColor" p-id="5715"></path></svg>
|
||||||
|
After Width: | Height: | Size: 666 B |
@@ -13,7 +13,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, onUnmounted, nextTick } from 'vue'
|
import { ref, onMounted, nextTick } from 'vue'
|
||||||
|
|
||||||
// 定义线条类型
|
// 定义线条类型
|
||||||
interface Line {
|
interface Line {
|
||||||
@@ -24,7 +24,6 @@ const containerRef = ref<HTMLElement>()
|
|||||||
const visualizerRef = ref<HTMLElement>()
|
const visualizerRef = ref<HTMLElement>()
|
||||||
const lines = ref<Line[]>([])
|
const lines = ref<Line[]>([])
|
||||||
const isInitialized = ref<boolean>(false)
|
const isInitialized = ref<boolean>(false)
|
||||||
let resizeObserver: ResizeObserver | null = null
|
|
||||||
|
|
||||||
// 计算需要的线条数量
|
// 计算需要的线条数量
|
||||||
const calculateLines = (): Line[] => {
|
const calculateLines = (): Line[] => {
|
||||||
@@ -102,6 +101,7 @@ const calculateLines = (): Line[] => {
|
|||||||
|
|
||||||
// 更新线条
|
// 更新线条
|
||||||
const updateLines = () => {
|
const updateLines = () => {
|
||||||
|
if (isInitialized.value) return
|
||||||
const newLines = calculateLines()
|
const newLines = calculateLines()
|
||||||
if (newLines.length > 0) {
|
if (newLines.length > 0) {
|
||||||
lines.value = newLines
|
lines.value = newLines
|
||||||
@@ -114,11 +114,6 @@ defineExpose({
|
|||||||
updateLines
|
updateLines
|
||||||
})
|
})
|
||||||
|
|
||||||
// 监听窗口大小变化
|
|
||||||
const handleResize = () => {
|
|
||||||
updateLines()
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await nextTick()
|
await nextTick()
|
||||||
|
|
||||||
@@ -138,28 +133,6 @@ onMounted(async () => {
|
|||||||
updateLines()
|
updateLines()
|
||||||
}
|
}
|
||||||
}, 150)
|
}, 150)
|
||||||
|
|
||||||
// 使用ResizeObserver监听容器大小变化,更精确地检测初始化时机
|
|
||||||
if (visualizerRef.value && window.ResizeObserver) {
|
|
||||||
resizeObserver = new ResizeObserver((entries) => {
|
|
||||||
for (const entry of entries) {
|
|
||||||
if (entry.contentRect.width > 50 && !isInitialized.value) {
|
|
||||||
updateLines()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
resizeObserver.observe(visualizerRef.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('resize', handleResize)
|
|
||||||
})
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
window.removeEventListener('resize', handleResize)
|
|
||||||
if (resizeObserver) {
|
|
||||||
resizeObserver.disconnect()
|
|
||||||
resizeObserver = null
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -170,7 +143,6 @@ onUnmounted(() => {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
min-height: 200px;
|
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
<div class="input-container">
|
<div class="input-container">
|
||||||
<!-- 加号图标 -->
|
<!-- 加号图标 -->
|
||||||
<div class="icon-wrapper">
|
<div class="icon-wrapper">
|
||||||
<SvgIcon name="plus" size="40" />
|
<SvgIcon v-if="!isRecording" name="plus" size="40" />
|
||||||
|
<SvgIcon v-else name="pause" size="60" @click="stopRecording" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 分隔线 -->
|
<!-- 分隔线 -->
|
||||||
@@ -138,9 +139,6 @@ const handleClickAudio = async (): Promise<void> => {
|
|||||||
audioVisualizerRef.value.updateLines?.()
|
audioVisualizerRef.value.updateLines?.()
|
||||||
}
|
}
|
||||||
}, 50)
|
}, 50)
|
||||||
}
|
|
||||||
|
|
||||||
if (isRecording.value) {
|
|
||||||
startRecording()
|
startRecording()
|
||||||
} else {
|
} else {
|
||||||
stopRecording()
|
stopRecording()
|
||||||
@@ -174,7 +172,7 @@ const startRecording = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 识别结果
|
// 识别结果
|
||||||
speechRecognition.onresult = (event) => {
|
speechRecognition.onresult = (event: any) => {
|
||||||
let finalTranscript = ''
|
let finalTranscript = ''
|
||||||
let interimTranscript = ''
|
let interimTranscript = ''
|
||||||
|
|
||||||
@@ -213,7 +211,7 @@ const startRecording = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 识别错误
|
// 识别错误
|
||||||
speechRecognition.onerror = (event) => {
|
speechRecognition.onerror = (event: any) => {
|
||||||
console.error('语音识别错误:', event.error)
|
console.error('语音识别错误:', event.error)
|
||||||
isRecording.value = false
|
isRecording.value = false
|
||||||
// alert('语音识别失败,请重试')
|
// alert('语音识别失败,请重试')
|
||||||
@@ -273,6 +271,7 @@ const stopRecording = () => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
color: #6d6868;
|
||||||
|
|
||||||
&.send-icon {
|
&.send-icon {
|
||||||
margin-left: 4.38rem;
|
margin-left: 4.38rem;
|
||||||
|
|||||||
Reference in New Issue
Block a user