Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
AI_BOOK_TOOL
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
template admin
AI_BOOK_TOOL
Commits
2b2ffbc3
Commit
2b2ffbc3
authored
Jun 27, 2025
by
liujiangnan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 逐词高亮逻辑
parent
c0996581
Changes
4
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
82772 additions
and
1774 deletions
+82772
-1774
defaultData_1.json
play/defaultData_1.json
+82660
-1773
index.css
play/index.css
+16
-0
index.html
play/index.html
+12
-0
index.js
play/index.js
+84
-1
No files found.
play/defaultData_1.json
View file @
2b2ffbc3
This diff is collapsed.
Click to expand it.
play/index.css
View file @
2b2ffbc3
...
...
@@ -70,6 +70,22 @@ body {
transform
:
scale
(
1
);
}
/* 单词级别矩形高亮样式 */
.word-rect-layer
{
position
:
absolute
;
background-color
:
rgba
(
255
,
235
,
59
,
0.3
);
border
:
2px
solid
#ffeb3b
;
border-radius
:
4px
;
pointer-events
:
none
;
z-index
:
3
;
box-shadow
:
0
0
8px
rgba
(
255
,
235
,
59
,
0.5
);
}
.word-rect-layer
:hover
{
background-color
:
rgba
(
255
,
235
,
59
,
0.5
);
box-shadow
:
0
0
12px
rgba
(
255
,
235
,
59
,
0.8
);
}
.subtitle-bar
{
position
:
fixed
;
left
:
50%
;
...
...
play/index.html
View file @
2b2ffbc3
...
...
@@ -23,6 +23,16 @@
<template
v-if=
"currentRects && isRectVisible"
>
<div
v-for=
"(rect, idx) in currentRects"
:key=
"idx"
class=
"rect-layer rect-visible"
:style=
"getRectStyle(rect)"
></div>
</template>
<!-- 单词级别矩形高亮 -->
<template
v-if=
"highlightedWordRects && isRectVisible"
>
<div
v-for=
"(wordRect, idx) in highlightedWordRects"
:key=
"'word-' + idx"
class=
"word-rect-layer"
:style=
"getWordRectStyle(wordRect)"
:title=
"wordRect.text"
></div>
</template>
</div>
</transition>
</div>
...
...
@@ -45,6 +55,8 @@
<div>
单词数: {{ debugInfo.totalWords }}
</div>
<div>
高亮索引: {{ debugInfo.highlightedIndexes.join(', ') }}
</div>
<div>
当前单词: {{ debugInfo.currentWord }}
</div>
<div>
单词矩形数: {{ debugInfo.wordRectsCount }}
</div>
<div>
组单词数: {{ debugInfo.groupWordsCount }}
</div>
</div>
</div>
<div
class=
"fixed-btn-group"
>
...
...
play/index.js
View file @
2b2ffbc3
...
...
@@ -41,6 +41,9 @@ function initializeApp(data) {
// 逐字高亮相关
currentWords
:
[],
highlightedWordIndexes
:
[],
// 单词级别矩形高亮相关
currentGroupWords
:
[],
// 当前活跃组的单词矩形信息
highlightedWordRects
:
[],
// 当前高亮的单词矩形
},
computed
:
{
currentGroups
()
{
...
...
@@ -85,7 +88,9 @@ function initializeApp(data) {
currentTime
:
this
.
audio
?
this
.
audio
.
currentTime
:
0
,
totalWords
:
this
.
currentWords
.
length
,
highlightedIndexes
:
this
.
highlightedWordIndexes
,
currentWord
:
currentWord
?
`
${
currentWord
.
word
}
(
${
currentWord
.
start
}
-
${
currentWord
.
end
}
)`
:
'
无
'
currentWord
:
currentWord
?
`
${
currentWord
.
word
}
(
${
currentWord
.
start
}
-
${
currentWord
.
end
}
)`
:
'
无
'
,
wordRectsCount
:
this
.
highlightedWordRects
.
length
,
groupWordsCount
:
this
.
currentGroupWords
.
length
};
}
},
...
...
@@ -171,6 +176,8 @@ function initializeApp(data) {
if
(
currentPage
&&
currentPage
.
groups
)
{
// 重置活跃组索引数组
this
.
activeGroupIndexes
=
[];
this
.
currentGroupWords
=
[];
this
.
highlightedWordRects
=
[];
// 遍历所有组,找出所有时间匹配的组
currentPage
.
groups
.
forEach
((
group
,
idx
)
=>
{
...
...
@@ -178,6 +185,55 @@ function initializeApp(data) {
currentTime
>=
group
.
start
&&
currentTime
<=
group
.
end
)
{
// 将匹配的组索引添加到活跃组数组中
this
.
activeGroupIndexes
.
push
(
idx
);
// 处理单词级别的矩形高亮
if
(
group
.
group
&&
Array
.
isArray
(
group
.
group
))
{
group
.
group
.
forEach
(
item
=>
{
if
(
item
.
words
&&
Array
.
isArray
(
item
.
words
))
{
// 将单词信息添加到当前组单词列表
item
.
words
.
forEach
(
word
=>
{
this
.
currentGroupWords
.
push
({
...
word
,
groupIndex
:
idx
,
itemIndex
:
group
.
group
.
indexOf
(
item
)
});
});
// 只高亮当前正在播放的单词
if
(
this
.
currentWords
.
length
>
0
&&
this
.
highlightedWordIndexes
.
length
>
0
)
{
this
.
highlightedWordIndexes
.
forEach
(
hIdx
=>
{
const
audioWord
=
this
.
currentWords
[
hIdx
];
// 收集所有匹配的页面单词
const
matchingWords
=
[];
item
.
words
.
forEach
((
word
,
wordIdx
)
=>
{
if
(
audioWord
&&
word
.
text
&&
audioWord
.
word
&&
word
.
text
.
trim
().
toLowerCase
()
===
audioWord
.
word
.
trim
().
toLowerCase
()
)
{
matchingWords
.
push
({
...
word
,
groupIndex
:
idx
,
itemIndex
:
group
.
group
.
indexOf
(
item
),
audioWord
,
wordIdx
});
}
});
// 根据音频单词的索引选择对应的页面单词
if
(
matchingWords
.
length
>
0
)
{
// 如果匹配的单词数量大于音频索引,选择对应位置的单词
// 否则选择最后一个匹配的单词
const
selectedWord
=
matchingWords
[
hIdx
]
||
matchingWords
[
matchingWords
.
length
-
1
];
this
.
highlightedWordRects
.
push
(
selectedWord
);
}
});
}
}
});
}
}
});
...
...
@@ -246,6 +302,9 @@ function initializeApp(data) {
this
.
currentWords
=
[];
this
.
highlightedWordIndexes
=
[];
this
.
currentAudioPointIndex
=
-
1
;
// 重置单词矩形高亮状态
this
.
currentGroupWords
=
[];
this
.
highlightedWordRects
=
[];
},
togglePlay
()
{
if
(
this
.
isPlaying
)
{
...
...
@@ -317,6 +376,30 @@ function initializeApp(data) {
height
:
(
height
*
imgRect
.
height
)
+
'
px
'
,
display
:
rect
.
visible
===
false
?
'
none
'
:
'
block
'
};
},
getWordRectStyle
(
wordRect
)
{
if
(
!
wordRect
||
!
wordRect
.
rect
||
!
this
.
imageSize
.
width
||
!
this
.
imageSize
.
height
)
return
{};
// 获取图片元素
const
img
=
this
.
$refs
.
mainImg
;
if
(
!
img
)
return
{};
// 获取图片的实际显示尺寸和位置
const
imgRect
=
img
.
getBoundingClientRect
();
const
x
=
parseFloat
(
wordRect
.
rect
.
x
);
const
y
=
parseFloat
(
wordRect
.
rect
.
y
);
const
width
=
parseFloat
(
wordRect
.
rect
.
width
);
const
height
=
parseFloat
(
wordRect
.
rect
.
height
);
return
{
position
:
'
absolute
'
,
left
:
(
x
*
imgRect
.
width
+
imgRect
.
left
)
+
'
px
'
,
top
:
(
y
*
imgRect
.
height
+
imgRect
.
top
)
+
'
px
'
,
width
:
(
width
*
imgRect
.
width
)
+
'
px
'
,
height
:
(
height
*
imgRect
.
height
)
+
'
px
'
,
backgroundColor
:
'
rgba(255, 235, 59, 0.3)
'
,
border
:
'
2px solid #ffeb3b
'
,
borderRadius
:
'
4px
'
,
pointerEvents
:
'
none
'
,
zIndex
:
3
};
}
}
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment