|
@@ -156,30 +156,39 @@ export const useSpeak = () => {
|
|
|
const showDomRect = showDom.getBoundingClientRect();
|
|
|
|
|
|
// 判断 上边超出边界
|
|
|
- if (y - parentRect?.top > showDomRect.height + fHeight / 2) {
|
|
|
- showDom.style.top =
|
|
|
- (
|
|
|
- y -
|
|
|
- parentRect?.top -
|
|
|
- (showDomRect.height + fHeight / 2) +
|
|
|
- musicContent?.scrollTop
|
|
|
- ).toFixed(2) + 'px';
|
|
|
- } else {
|
|
|
- console.log(
|
|
|
- false,
|
|
|
- parentRect?.bottom -
|
|
|
- bottom +
|
|
|
+ // if (y - parentRect?.top > showDomRect.height + fHeight / 2) {
|
|
|
+ // showDom.style.top =
|
|
|
+ // (
|
|
|
+ // y -
|
|
|
+ // parentRect?.top -
|
|
|
+ // (showDomRect.height + fHeight / 2) +
|
|
|
+ // musicContent?.scrollTop
|
|
|
+ // ).toFixed(2) + 'px';
|
|
|
+ // } else {
|
|
|
+ // console.log(
|
|
|
+ // false,
|
|
|
+ // parentRect?.bottom -
|
|
|
+ // bottom +
|
|
|
+ // (showDomRect.height + fHeight / 2) +
|
|
|
+ // musicContent?.scrollTop
|
|
|
+ // );
|
|
|
+ showDom.style.top =
|
|
|
+ (
|
|
|
+ y -
|
|
|
+ parentRect?.top +
|
|
|
(showDomRect.height + fHeight / 2) +
|
|
|
musicContent?.scrollTop
|
|
|
- );
|
|
|
- showDom.style.top =
|
|
|
- (
|
|
|
- y -
|
|
|
- parentRect?.top +
|
|
|
- (showDomRect.height + fHeight / 2) +
|
|
|
- musicContent?.scrollTop
|
|
|
- ).toFixed(2) + 'px';
|
|
|
- }
|
|
|
+ ).toFixed(2) + 'px';
|
|
|
+ // }
|
|
|
+ // console.log({
|
|
|
+ // parentRectWidth: parentRect?.width,
|
|
|
+ // firstRectLeft: x,
|
|
|
+ // parentRectLeft: parentRect?.left,
|
|
|
+ // parentRectStatus:
|
|
|
+ // parentRect?.width - (x - parentRect?.left) > showDomRect.width,
|
|
|
+ // diff: parentRect?.width - (x - parentRect?.left),
|
|
|
+ // showDomRect: showDomRect.width
|
|
|
+ // });
|
|
|
if (parentRect?.width - (x - parentRect?.left) > showDomRect.width) {
|
|
|
// 判断是否选择到最右边 超出边界
|
|
|
showDom.style.left = (x - parentRect?.left).toFixed(2) + 'px';
|
|
@@ -257,8 +266,11 @@ export const useSpeak = () => {
|
|
|
const textContainer: any = document.querySelector('#musicContent');
|
|
|
const sentences: any = textContainer?.querySelectorAll('label.speak-label');
|
|
|
|
|
|
+ // console.log(options, '--endIndex');
|
|
|
let currentSentenceIndex = options.startIndex || 0;
|
|
|
- const end = options.endIndex || sentences.length - 1;
|
|
|
+ const end =
|
|
|
+ options.endIndex === undefined ? sentences.length - 1 : options.endIndex;
|
|
|
+
|
|
|
// 高亮显示
|
|
|
const highlightSentence = (index: number) => {
|
|
|
sentences.forEach((sentence: any, i: number) => {
|
|
@@ -277,6 +289,12 @@ export const useSpeak = () => {
|
|
|
const speaker = () => {
|
|
|
try {
|
|
|
state.synth = window.speechSynthesis;
|
|
|
+
|
|
|
+ // 获取可用的 voice 列表
|
|
|
+ // const voices = speechSynthesis.getVoices();
|
|
|
+ // 选择一个特定的 voice
|
|
|
+ // const voice = voices.find(voice => voice.lang === 'zh-CN');
|
|
|
+ // console.log(voice, 'voice');
|
|
|
// 如果当前正在播放,先暂停
|
|
|
if (state.synth.speaking) {
|
|
|
state.synth.cancel(); // 取消当前播放
|
|
@@ -288,29 +306,42 @@ export const useSpeak = () => {
|
|
|
return;
|
|
|
}
|
|
|
// 判断是否为选中的内容播放
|
|
|
- if (options.startIndex === options.endIndex) {
|
|
|
+ if (
|
|
|
+ options.startIndex === options.endIndex &&
|
|
|
+ options.endIndex !== undefined
|
|
|
+ ) {
|
|
|
sentence = sentence.substr(
|
|
|
options.anchorOffset,
|
|
|
(options.focusOffset || 0) - (options.anchorOffset || 0)
|
|
|
);
|
|
|
} else {
|
|
|
if (options.startIndex === currentSentenceIndex) {
|
|
|
- sentence = sentence.substr(
|
|
|
- options.anchorOffset,
|
|
|
- sentence.length - 1
|
|
|
- );
|
|
|
+ sentence = sentence.substr(options.anchorOffset, sentence.length);
|
|
|
}
|
|
|
if (options.endIndex === currentSentenceIndex) {
|
|
|
sentence = sentence.substr(0, options.focusOffset);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- const utterance = new SpeechSynthesisUtterance();
|
|
|
+ const replaceText = ['长笛', '曲'];
|
|
|
+ const afterReplaceText = ['尝笛', '取'];
|
|
|
+
|
|
|
+ if (sentence) {
|
|
|
+ replaceText.forEach((item: string, index: number) => {
|
|
|
+ if (sentence.includes(item)) {
|
|
|
+ const regex = new RegExp(item, 'g');
|
|
|
+ sentence = sentence.replace(regex, afterReplaceText[index]);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log(sentence, currentSentenceIndex, end, '---------');
|
|
|
+ const utterance = new SpeechSynthesisUtterance(sentence);
|
|
|
utterance.lang = 'zh-CN';
|
|
|
utterance.volume = 1;
|
|
|
utterance.rate = 0.8; // 语速 0.1到10
|
|
|
utterance.pitch = 1.5; // 范围从0(最小)到2(最大)
|
|
|
- utterance.text = sentence;
|
|
|
+ // utterance.text = sentence;
|
|
|
|
|
|
if (utterance) {
|
|
|
utterance.onstart = null;
|
|
@@ -345,7 +376,7 @@ export const useSpeak = () => {
|
|
|
};
|
|
|
setTimeout(() => {
|
|
|
state.synth.speak(utterance);
|
|
|
- }, 100);
|
|
|
+ }, 80);
|
|
|
} catch (e) {
|
|
|
console.log(e, 'e');
|
|
|
}
|
|
@@ -387,10 +418,12 @@ export const useSpeak = () => {
|
|
|
|
|
|
onMounted(async () => {
|
|
|
document.addEventListener('mouseup', getSelectText);
|
|
|
+ document.addEventListener('touchend', getSelectText);
|
|
|
});
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
document.removeEventListener('mouseup', getSelectText);
|
|
|
+ document.addEventListener('touchend', getSelectText);
|
|
|
onCloseSpeak();
|
|
|
});
|
|
|
|