feat(all): update audio

This commit is contained in:
zyronon
2023-09-19 18:15:05 +08:00
parent cbbb760eac
commit f06069ee6c
28 changed files with 279 additions and 210 deletions

View File

@@ -67,7 +67,7 @@ a {
outline: none;
border: 1px solid transparent;
border-radius: 6rem;
padding:8rem 10rem;
padding: 8rem 10rem;
transition: all .3s;
min-height: 20rem;
width: 100%;
@@ -77,7 +77,7 @@ a {
border: 1px solid var(--color-main-active);
}
&[readonly]{
&[readonly] {
cursor: not-allowed;
opacity: .7;
}
@@ -108,11 +108,21 @@ footer {
gap: $space;
}
.i-icon {
cursor: pointer;
}
.pointer {
cursor: pointer;
}
.flex {
display: flex;
}
.justify-content-between {
justify-content: space-between;
}
.flex-center {
display: flex;
align-items: center;
justify-content: center;
}

View File

@@ -9,7 +9,7 @@ import {onMounted} from "vue";
import {getRandom} from "@/utils/index.ts";
import boom from '@/assets/sound/boom.mp3'
import shotfire from '@/assets/sound/shotfire.mp3'
import {useSound} from "@/hooks/useSound.ts";
import {useSound} from "@/hooks/sound.ts";
const canvas = $ref()
const [playBoom] = useSound([boom], 3)

View File

@@ -15,7 +15,7 @@ export default {
<style scoped lang="scss">
@import "@/assets/css/colors";
$w: 20rem;
$w: 22rem;
.icon-wrapper {
//padding: 2rem;
width: 26rem;

View File

@@ -1,17 +1,19 @@
<script setup lang="ts">
interface IProps {
modelValue?: boolean,
width?: string
}
withDefaults(defineProps<IProps>(), {
modelValue: true,
width: '180rem'
})
</script>
<template>
<Transition name="fade">
<div v-if="modelValue" class="mini-modal">
<div v-if="modelValue" class="mini-modal" :style="{width}">
<slot></slot>
</div>
</Transition>

View File

@@ -1,41 +1,13 @@
<script setup lang="ts">
import {Icon} from '@iconify/vue'
import {usePlayWordAudio} from "@/hooks/usePlayWordAudio.ts"
import {computed, nextTick, onMounted, reactive, watch, watchEffect} from "vue"
import {cloneDeep} from "lodash-es"
import 快速打字的机械键盘声音Mp3 from '../..//assets/sound/key-sounds/快速打字的机械键盘声音.mp3'
import 键盘快速打字的声音Mp3 from '../..//assets/sound/key-sounds/键盘快速打字的声音.mp3'
import 电话打字的声音Mp3 from '../..//assets/sound/key-sounds/电话打字的声音.mp3'
import 老式机械 from '../..//assets/sound/key-sounds/老式机械.mp3'
import 机械0 from '../..//assets/sound/key-sounds/jixie/机械0.mp3'
import 机械1 from '../..//assets/sound/key-sounds/jixie/机械1.mp3'
import 机械2 from '../..//assets/sound/key-sounds/jixie/机械2.mp3'
import 机械3 from '../..//assets/sound/key-sounds/jixie/机械3.mp3'
import beep from '../..//assets/sound/beep.wav'
import correct from '../..//assets/sound/correct.wav'
import {useSound} from "@/hooks/useSound.ts"
import {$computed, $ref} from "vue/macros";
import {
Article,
ArticleWord,
DefaultWord,
DictType,
SaveKey,
Sentence,
ShortKeyMap,
TranslateEngine,
Word
} from "@/types";
import {computed, nextTick, watchEffect} from "vue"
import {$ref} from "vue/macros";
import {Article, ArticleWord, ShortKeyMap, Word} from "@/types";
import {useBaseStore} from "@/stores/base";
import {usePracticeStore} from "@/components/Practice/usePracticeStore.ts";
import {useEventListener} from "@/hooks/useEvent.ts";
import TypeWord from "@/components/Practice/TypeWord.vue";
import {updateLocalSentenceTranslate, getNetworkTranslate} from "@/hooks/translate.ts";
import IconWrapper from "@/components/IconWrapper.vue";
import Tooltip from "@/components/Tooltip.vue";
import MiniModal from "@/components/MiniModal.vue";
import {splitArticle} from "@/hooks/article.ts";
import {useSettingStore} from "@/stores/setting.ts";
import {usePlayBeep, usePlayCorrect, usePlayKeyboardAudio, usePlayWordAudio} from "@/hooks/sound.ts";
let article1 = `How does the older investor differ in his approach to investment from the younger investor?
There is no shortage of tipsters around offering 'get-rich-quick' opportunities. But if you are a serious private investor, leave the Las Vegas mentality to those with money to fritter. The serious investor needs a proper 'portfolio' -- a well-planned selection of investments, with a definite structure and a clear aim. But exactly how does a newcomer to the stock market go about achieving that?
@@ -51,13 +23,10 @@ article1 = `Last week I went to the theatre. I had a very good seat. The play wa
It's none of your business, the young man said rudely. This is a private conversation!`
// article1 = `Last week I went to the theatre. I had a very good seat. The play was very interesting. I did not enjoy it.`
const [playAudio] = usePlayWordAudio()
// const [playKeySound, setAudio] = useSound([机械0, 机械1, 机械2, 机械3], 1)
const [playKeySound, setAudio] = useSound([老式机械], 3)
// const [playKeySound, setAudio] = useSound([电话打字的声音Mp3], 3)
const [playBeep] = useSound([beep], 1)
const [playCorrect] = useSound([correct], 1)
const playBeep = usePlayBeep()
const playCorrect = usePlayCorrect()
const playKeyboardAudio = usePlayKeyboardAudio()
const playWordAudio = usePlayWordAudio()
const store = useBaseStore()
const practiceStore = usePracticeStore()
const settingStore = useSettingStore()
@@ -159,7 +128,7 @@ function calcTranslateLocation() {
}
function play() {
return playAudio(article1)
return playWordAudio(article1)
if (isPlay) {
isPlay = false
return window.speechSynthesis.pause();
@@ -205,7 +174,7 @@ function onKeyDown(e: KeyboardEvent) {
if (settingStore.dictation) {
calcTranslateLocation()
}
playAudio(currentSection[sentenceIndex].text)
playWordAudio(currentSection[sentenceIndex].text)
}
}
}
@@ -237,7 +206,7 @@ function onKeyDown(e: KeyboardEvent) {
wrong = input = ''
}, 500)
}
playKeySound()
playKeyboardAudio()
} else {
let letter = e.key
@@ -288,7 +257,7 @@ function onKeyDown(e: KeyboardEvent) {
}, 500)
// console.log('未匹配')
}
playKeySound()
playKeyboardAudio()
}
} else {
switch (e.key) {
@@ -335,11 +304,9 @@ function onKeyUp() {
}
}
useEventListener('keydown', onKeyDown)
useEventListener('keyup', onKeyUp)
function playWord(word: ArticleWord) {
playAudio(word.name)
playWordAudio(word.name)
}
function currentWordInput(word: ArticleWord, i: number, i2: number,) {
@@ -388,6 +355,8 @@ function otherWord(word: ArticleWord, i: number, i2: number, i3: number) {
return str
}
useEventListener('keydown', onKeyDown)
useEventListener('keyup', onKeyUp)
</script>
<template>
@@ -410,7 +379,7 @@ function otherWord(word: ArticleWord, i: number, i2: number, i3: number) {
]"
@mouseenter="settingStore.allowWordTip && (hoverIndex = {sectionIndex : indexI,sentenceIndex :indexJ})"
@mouseleave="hoverIndex = {sectionIndex : -1,sentenceIndex :-1}"
@click="playAudio(sentence.text)"
@click="playWordAudio(sentence.text)"
v-for="(sentence,indexJ) in section">
<span
v-for="(word,indexW) in sentence.words"

View File

@@ -1,28 +1,15 @@
<script setup lang="ts">
import {computed, onMounted, onUnmounted, provide, watch, watchEffect} from "vue"
import 快速打字的机械键盘声音Mp3 from '../../assets/sound/key-sounds/快速打字的机械键盘声音.mp3'
import 键盘快速打字的声音Mp3 from '../../assets/sound/key-sounds/键盘快速打字的声音.mp3'
import 电话打字的声音Mp3 from '../../assets/sound/key-sounds/电话打字的声音.mp3'
import 老式机械 from '../../assets/sound/key-sounds/老式机械.mp3'
import 机械0 from '../../assets/sound/key-sounds/jixie/机械0.mp3'
import 机械1 from '../../assets/sound/key-sounds/jixie/机械1.mp3'
import 机械2 from '../../assets/sound/key-sounds/jixie/机械2.mp3'
import 机械3 from '../../assets/sound/key-sounds/jixie/机械3.mp3'
import beep from '../../assets/sound/beep.wav'
import correct from '../../assets/sound/correct.wav'
import {onMounted, watchEffect} from "vue"
import {$computed, $ref} from "vue/macros"
import {useSound} from "@/hooks/useSound.ts"
import {useBaseStore} from "@/stores/base.ts"
import {DictType, SaveKey, ShortKeyMap, Statistics, Word} from "../../types";
import {usePlayWordAudio} from "@/hooks/usePlayWordAudio.ts"
import useTheme from "@/hooks/useTheme.ts";
import Tooltip from "@/components/Tooltip.vue";
import {DictType, ShortKeyMap, Word} from "../../types";
import BaseButton from "@/components/BaseButton.vue";
import {emitter, EventKey} from "@/utils/eventBus.ts"
import {cloneDeep} from "lodash-es"
import {usePracticeStore} from "@/components/Practice/usePracticeStore.ts"
import {useEventListener} from "@/hooks/useEvent.ts";
import {useSettingStore} from "@/stores/setting.ts";
import {usePlayBeep, usePlayCorrect, usePlayKeyboardAudio, usePlayWordAudio} from "@/hooks/sound.ts";
interface IProps {
words: Word[],
@@ -50,12 +37,10 @@ const store = useBaseStore()
const practiceStore = usePracticeStore()
const settingStore = useSettingStore()
// const [playKeySound, setAudio] = useSound([机械0, 机械1, 机械2, 机械3], 1)
// const [playKeySound, setAudio] = useSound([老式机械], 3)
const [playKeySound, setAudio] = useSound([电话打字的声音Mp3], 3)
const [playBeep] = useSound([beep], 1)
const [playCorrect] = useSound([correct], 1)
const [playAudio] = usePlayWordAudio()
const playBeep = usePlayBeep()
const playCorrect = usePlayCorrect()
const playKeyboardAudio = usePlayKeyboardAudio()
const playWordAudio = usePlayWordAudio()
watchEffect(() => {
@@ -140,7 +125,7 @@ async function onKeyDown(e: KeyboardEvent) {
if (isWrong) {
input += letter
wrong = ''
playKeySound()
playKeyboardAudio()
} else {
if (!store.wrongWordDict.originWords.find((v: Word) => v.name.toLowerCase() === word.name.toLowerCase())) {
store.wrongWordDict.originWords.push(word)
@@ -152,7 +137,7 @@ async function onKeyDown(e: KeyboardEvent) {
practiceStore.wrongNumber++
}
wrong = letter
playKeySound()
playKeyboardAudio()
playBeep()
setTimeout(() => {
wrong = ''
@@ -229,7 +214,7 @@ async function onKeyDown(e: KeyboardEvent) {
</template>
<span class="letter" v-else>{{ resetWord }}</span>
</div>
<div class="audio" @click="playAudio(word.name)">播放</div>
<div class="audio" @click="playWordAudio(word.name)">播放</div>
</div>
<div class="phonetic">{{ word.usphone }}</div>
<div class="options">

View File

@@ -4,6 +4,7 @@ import {useBaseStore} from "@/stores/base.ts"
import {Icon} from '@iconify/vue';
import {watch, ref} from "vue";
import {useSettingStore} from "@/stores/setting.ts";
import {useChangeAllSound, useWatchAllSound} from "@/hooks/sound.ts";
const tabIndex = $ref(0)
const settingStore = useSettingStore()
@@ -20,28 +21,7 @@ const emit = defineEmits([
'update:modelValue',
])
let allSound = $ref<boolean>(true)
watch([
() => settingStore.wordSound,
() => settingStore.keyboardSound,
() => settingStore.translateSound,
() => settingStore.effectSound,
], (n) => {
if (n.some(v => v)) {
allSound = true
} else {
allSound = false
}
})
function changAllSound(e: boolean) {
allSound = e
settingStore.wordSound = e
settingStore.keyboardSound = e
settingStore.translateSound = e
settingStore.effectSound = e
}
useWatchAllSound()
</script>
@@ -66,8 +46,8 @@ function changAllSound(e: boolean) {
<div class="row">
<label class="main-title">所有音效</label>
<div class="wrapper">
<el-switch v-model="allSound"
@change="changAllSound"
<el-switch v-model="settingStore.allSound"
@change="useChangeAllSound"
inline-prompt
active-text=""
inactive-text=""

View File

@@ -4,34 +4,54 @@ import MiniModal from "@/components/MiniModal.vue";
import {Icon} from "@iconify/vue";
import IconWrapper from "@/components/IconWrapper.vue";
import Tooltip from "@/components/Tooltip.vue";
import {useBaseStore} from "@/stores/base.ts";
import {useWindowClick} from "@/hooks/event.ts";
import {emitter, EventKey} from "@/utils/eventBus.ts";
import {useSettingStore} from "@/stores/setting.ts";
import VolumeIcon from "@/components/VolumeIcon.vue";
import {getAudioFileUrl, useChangeAllSound, usePlayAudio, useWatchAllSound} from "@/hooks/sound.ts";
import {SoundFileOptions} from "@/utils/const.ts";
const store = useBaseStore()
const settingStore = useSettingStore()
let show = $ref(false)
useWindowClick(() => show = false)
useWatchAllSound()
function toggle() {
if (!show) emitter.emit(EventKey.closeOther)
show = !show
}
</script>
<template>
<div class="setting" @click.stop="null">
<div class="setting"
@click.stop="null">
<Tooltip title="音效设置">
<IconWrapper>
<Icon icon="icon-park-outline:volume-notice"
<Icon v-if="settingStore.allSound" icon="icon-park-outline:volume-notice"
@click="toggle"
/>
<Icon v-else icon="icon-park-outline:volume-mute"
@click="toggle"
/>
</IconWrapper>
</Tooltip>
<MiniModal v-model="show">
<MiniModal
width="230rem"
v-model="show">
<div class="mini-row">
<label class="item-title">所有音效</label>
<div class="wrapper">
<el-switch v-model="settingStore.allSound"
@change="useChangeAllSound"
inline-prompt
active-text=""
inactive-text=""
/>
</div>
</div>
<div class="mini-row">
<label class="item-title">单词发音</label>
<div class="wrapper">
@@ -62,6 +82,28 @@ function toggle() {
/>
</div>
</div>
<div class="mini-row">
<label class="item-title">按键音效</label>
<div class="wrapper">
<el-select v-model="settingStore.keyboardSoundFile"
placeholder="请选择"
size="small">
<el-option
v-for="item in SoundFileOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
<div class="el-option-row">
<span>{{ item.label }}</span>
<VolumeIcon
:time="100"
@click="usePlayAudio(getAudioFileUrl(item.value)[0])"/>
</div>
</el-option>
</el-select>
</div>
</div>
<div class="mini-row">
<label class="item-title">效果音</label>
<div class="wrapper">
@@ -85,6 +127,16 @@ function toggle() {
.setting {
position: relative;
}
.el-option-row {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
.icon-wrapper {
transform: translateX(10rem);
}
}
</style>

View File

@@ -0,0 +1,49 @@
<script setup lang="ts">
import {Icon} from "@iconify/vue";
import {$ref} from "vue/macros";
import IconWrapper from "@/components/IconWrapper.vue";
const props = withDefaults(defineProps<{ time?: number }>(), {
time: 400
})
let step = $ref(0)
const emit = defineEmits(['click'])
function play(time = props.time) {
setTimeout(() => {
if (step === 2) {
step = 0
} else {
step++
if (step === 2) {
play(time + 100)
} else {
play(time + 100)
}
}
}, time)
}
function click() {
emit('click')
play()
}
</script>
<template>
<IconWrapper @click.stop="click">
<div class="center">
<Icon v-if="step === 0" icon="bx:volume"/>
<Icon v-if="step === 1" icon="bx:volume-low"/>
<Icon v-if="step === 2" icon="bx:volume-full"/>
</div>
</IconWrapper>
</template>
<style scoped lang="scss">
.center {
display: flex;
align-items: center;
justify-content: center;
}
</style>

View File

@@ -1,9 +1,9 @@
<script setup lang="ts">
import {Word} from "../types";
import {usePlayWordAudio} from "../hooks/usePlayWordAudio";
import {watch} from "vue"
import {useBaseStore} from "@/stores/base.ts"
import {Icon} from '@iconify/vue';
import {usePlayWordAudio} from "@/hooks/sound.ts";
const store = useBaseStore()
const emit = defineEmits(['change'])
@@ -13,7 +13,7 @@ const props = defineProps<{
isActive: boolean
}>()
const [playAudio] = usePlayWordAudio()
const playWordAudio = usePlayWordAudio()
const listRef: HTMLElement = $ref(null as any)
function scrollViewToCenter(index: number) {
@@ -52,7 +52,7 @@ watch(() => props.list, () => {
</div>
</div>
<div class="right">
<div class="audio" @click="playAudio(item.name)">播放</div>
<div class="audio" @click="playWordAudio(item.name)">播放</div>
<Icon icon="fluent:delete-28-regular" width="20" color="#929596"/>
</div>
</div>
@@ -93,7 +93,7 @@ watch(() => props.list, () => {
&:hover {
//background: $dark-main-bg;
//background: $item-hover;
background: rgb(226,226,226);
background: rgb(226, 226, 226);
}
.left {

View File

@@ -1,42 +1,118 @@
import {onMounted} from "vue"
import {useBaseStore} from "@/stores/base.ts";
import {onMounted, watch, watchEffect} from "vue"
import {useSettingStore} from "@/stores/setting.ts";
import {PronunciationApi} from "@/types.ts";
import beep from "@/assets/sound/beep.wav";
import correct from "@/assets/sound/correct.wav";
export function useSound(srcList?: string[], num?: number) {
let audioList: HTMLAudioElement[] = $ref([])
let audioLength = $ref(1)
const setAudio = (srcList2: string[], num2?: number) => {
if (num2) audioLength = num2
audioList = []
for (let i = 0; i < audioLength; i++) {
srcList2.map(src => {
audioList.push(new Audio(src))
})
export function useSound(urlList?: string[], num?: number) {
let audioList: HTMLAudioElement[] = $ref([])
let audioLength = $ref(1)
let index = $ref(0)
onMounted(() => {
if (urlList) setAudio(urlList, num)
})
function setAudio(srcList2: string[], num2?: number) {
if (num2) audioLength = num2
audioList = []
for (let i = 0; i < audioLength; i++) {
srcList2.map(src => audioList.push(new Audio(src)))
}
index = 0
}
index = 0
}
onMounted(() => {
if (srcList) setAudio(srcList, num)
})
function play() {
index++
if (audioList.length > 1 && audioList.length !== audioLength) {
audioList[index % audioList.length].play()
} else {
audioList[index % audioLength].play()
}
}
let index = $ref(0)
const play: Function = () => {
index++
if (audioList.length > 1 && audioList.length !== audioLength) {
audioList[index % audioList.length].play()
return [
play,
setAudio
]
}
export function usePlayKeyboardAudio() {
const settingStore = useSettingStore()
const [playKeyboardAudio, setAudio] = useSound()
watchEffect(() => {
let urlList = getAudioFileUrl(settingStore.keyboardSoundFile)
setAudio(urlList, urlList.length === 1 ? 3 : 1)
})
return playKeyboardAudio
}
export function usePlayBeep() {
return useSound([beep], 1)[0]
}
export function usePlayCorrect() {
return useSound([correct], 1)[0]
}
export function usePlayWordAudio() {
const audio = $ref(new Audio())
function generateWordSoundSrc(word: string, pronunciation: string) {
switch (pronunciation) {
case 'uk':
return `${PronunciationApi}${word}&type=1`
case 'us':
return `${PronunciationApi}${word}&type=2`
}
}
function playWordAudio(word: string) {
audio.src = generateWordSoundSrc(word, 'us')
audio.play()
}
return playWordAudio
}
export function usePlayAudio(url: string) {
new Audio(url).play().then(r => void 0)
}
export function getAudioFileUrl(name: string) {
if (name === '机械') {
return [
`/sound/key-sounds/jixie/机械0.mp3`,
`/sound/key-sounds/jixie/机械1.mp3`,
`/sound/key-sounds/jixie/机械2.mp3`,
`/sound/key-sounds/jixie/机械3.mp3`,
]
} else {
audioList[index % audioLength].play()
return [`/sound/key-sounds/${name}.mp3`]
}
}
return [
play,
setAudio
]
}
export function playKeyboardSound() {
const store = useBaseStore()
export function useWatchAllSound() {
const settingStore = useSettingStore()
watch([
() => settingStore.wordSound,
() => settingStore.keyboardSound,
() => settingStore.translateSound,
() => settingStore.effectSound,
], (n) => {
settingStore.allSound = n.some(v => v);
})
}
export function useChangeAllSound(e: boolean) {
const settingStore = useSettingStore()
settingStore.allSound = e
settingStore.wordSound = e
settingStore.keyboardSound = e
settingStore.translateSound = e
settingStore.effectSound = e
}

View File

@@ -1,21 +0,0 @@
import {PronunciationApi} from "../types";
export function usePlayWordAudio() {
const audio = $ref(new Audio())
function generateWordSoundSrc(word: string, pronunciation: string) {
switch (pronunciation) {
case 'uk':
return `${PronunciationApi}${word}&type=1`
case 'us':
return `${PronunciationApi}${word}&type=2`
}
}
function playAudio(word: string) {
audio.src = generateWordSoundSrc(word, 'us')
audio.play()
}
return [playAudio]
}

View File

@@ -1,35 +0,0 @@
import {onMounted} from "vue"
export function useSound(srcList?: string[], num?: number) {
let audioList: HTMLAudioElement[] = $ref([])
let audioLength = $ref(1)
const setAudio = (srcList2: string[], num2?: number) => {
if (num2) audioLength = num2
audioList = []
for (let i = 0; i < audioLength; i++) {
srcList2.map(src => {
audioList.push(new Audio(src))
})
}
index = 0
}
onMounted(() => {
if (srcList) setAudio(srcList, num)
})
let index = $ref(0)
const play: Function = () => {
index++
if (audioList.length > 1 && audioList.length !== audioLength) {
audioList[index % audioList.length].play()
} else {
audioList[index % audioLength].play()
}
}
return [
play,
setAudio
]
}

View File

@@ -4,6 +4,7 @@ export interface SettingState {
showToolbar: boolean,
show: boolean,
allSound: boolean,
wordSound: boolean,
wordSoundVolume: number,
wordSoundSpeed: number,
@@ -25,10 +26,6 @@ export interface SettingState {
foreignLanguageFontSize: number,
translateLanguageFontSize: number,
value1: boolean,
value2: number,
value3: number,
value4: boolean,
}
export const useSettingStore = defineStore('setting', {
@@ -37,12 +34,13 @@ export const useSettingStore = defineStore('setting', {
showToolbar: true,
show: false,
allSound: true,
wordSound: true,
wordSoundVolume: 100,
wordSoundSpeed: 1,
keyboardSound: true,
keyboardSoundVolume: 100,
keyboardSoundFile: '老式机械.mp3',
keyboardSoundFile: '老式机械',
translateSound: true,
translateSoundVolume: 100,
effectSound: true,
@@ -59,10 +57,6 @@ export const useSettingStore = defineStore('setting', {
translateLanguageFontSize: 20,
waitTimeForChangeWord: 300,
value1: false,
value2: 50,
value3: 1,
value4: false,
}
},
})

7
src/utils/const.ts Normal file
View File

@@ -0,0 +1,7 @@
export const SoundFileOptions = [
{value: '快速打字的机械键盘声音', label: '快速打字的机械键盘声音'},
{value: '键盘快速打字的声音', label: '键盘快速打字的声音'},
{value: '电话打字的声音', label: '电话打字的声音'},
{value: '老式机械', label: '老式机械'},
{value: '机械', label: '机械'},
]