113 lines
2.4 KiB
JavaScript
113 lines
2.4 KiB
JavaScript
|
function scroll (offsetTop) {
|
||
|
[document.body, document.documentElement].forEach((ele) => {
|
||
|
// eslint-disable-next-line
|
||
|
TweenLite.to(
|
||
|
ele,
|
||
|
0.4,
|
||
|
{
|
||
|
scrollTop: offsetTop,
|
||
|
ease: Power2.easeOut // eslint-disable-line
|
||
|
}
|
||
|
)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
function getAttrTag (line) {
|
||
|
return `[data-source-line="${line}"]`
|
||
|
}
|
||
|
|
||
|
function getPreLineOffsetTop (line) {
|
||
|
let currentLine = line - 1
|
||
|
let ele = null
|
||
|
while (currentLine > 0 && !ele) {
|
||
|
ele = document.querySelector(getAttrTag(currentLine))
|
||
|
if (!ele) {
|
||
|
currentLine -= 1
|
||
|
}
|
||
|
}
|
||
|
return [
|
||
|
currentLine >= 0 ? currentLine : 0,
|
||
|
ele ? ele.offsetTop : 0
|
||
|
]
|
||
|
}
|
||
|
|
||
|
function getNextLineOffsetTop (line, len) {
|
||
|
let currentLine = line + 1
|
||
|
let ele = null
|
||
|
while (currentLine < len && !ele) {
|
||
|
ele = document.querySelector(getAttrTag(currentLine))
|
||
|
if (!ele) {
|
||
|
currentLine += 1
|
||
|
}
|
||
|
}
|
||
|
return [
|
||
|
currentLine < len ? currentLine : len - 1,
|
||
|
ele ? ele.offsetTop : document.documentElement.scrollHeight
|
||
|
]
|
||
|
}
|
||
|
|
||
|
function topOrBottom (line, len) {
|
||
|
if (line === 0) {
|
||
|
scroll(0)
|
||
|
} else if (line === len - 1) {
|
||
|
scroll(document.documentElement.scrollHeight)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function relativeScroll (line, ratio, len) {
|
||
|
let offsetTop = 0
|
||
|
const lineEle = document.querySelector(`[data-source-line="${line}"]`)
|
||
|
if (lineEle) {
|
||
|
offsetTop = lineEle.offsetTop
|
||
|
} else {
|
||
|
const pre = getPreLineOffsetTop(line)
|
||
|
const next = getNextLineOffsetTop(line, len)
|
||
|
offsetTop = pre[1] + ((next[1] - pre[1]) * (line - pre[0]) / (next[0] - pre[0]))
|
||
|
}
|
||
|
scroll(offsetTop - document.documentElement.clientHeight * ratio)
|
||
|
}
|
||
|
|
||
|
export default {
|
||
|
relative: function ({
|
||
|
cursor,
|
||
|
winline,
|
||
|
winheight,
|
||
|
len
|
||
|
}) {
|
||
|
const line = cursor - 1
|
||
|
const ratio = winline / winheight
|
||
|
if (line === 0 || line === len - 1) {
|
||
|
topOrBottom(line, len)
|
||
|
} else {
|
||
|
relativeScroll(line, ratio, len)
|
||
|
}
|
||
|
},
|
||
|
middle: function ({
|
||
|
cursor,
|
||
|
// winline,
|
||
|
// winheight,
|
||
|
len
|
||
|
}) {
|
||
|
const line = cursor - 1
|
||
|
if (line === 0 || line === len - 1) {
|
||
|
topOrBottom(line, len)
|
||
|
} else {
|
||
|
relativeScroll(line, 0.5, len)
|
||
|
}
|
||
|
},
|
||
|
top: function ({
|
||
|
cursor,
|
||
|
winline,
|
||
|
// winheight,
|
||
|
len
|
||
|
}) {
|
||
|
let line = cursor - 1
|
||
|
if (line === 0 || line === len - 1) {
|
||
|
topOrBottom(line, len)
|
||
|
} else {
|
||
|
line = cursor - winline
|
||
|
relativeScroll(line, 0, len)
|
||
|
}
|
||
|
}
|
||
|
}
|