Skip to content

Commit

Permalink
增加炫酷模式选项
Browse files Browse the repository at this point in the history
  • Loading branch information
SHERlocked93 committed Aug 9, 2018
1 parent af88d9b commit 3e2cc3b
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 40 deletions.
16 changes: 8 additions & 8 deletions README.md
Expand Up @@ -54,28 +54,28 @@ new Catalog({

构造函数还有一些其他参数:

### contentEl [String]
#### contentEl [String]
需要检索生成目录的内容区的id选择器,不需要加#

### catalogEl [String]
#### catalogEl [String]
将生成的目录append进的目录容器的id选择器,不需要加#

### scrollWrapper [可选, String]
#### scrollWrapper [可选, String]
监听scroll事件的内容区容器的id选择器,不需要加#,如果不填则默认是 `contentEl` 的父元素

### linkClass [可选, String]
#### linkClass [可选, String]
所有目录项都有的类,默认值:`cl-link`

### selector [可选, Array]
#### selector [可选, Array]
选择目录的标题标签,默认值:`['h1', 'h2', 'h3', 'h4', 'h5', 'h6']`

如果只希望生成目标内容区的 h2, h3 标签的目录,那么可以设置 `selector: ['h2', 'h3']`

### activeHook [可选, Function]
#### activeHook [可选, Function]
当激活新的目录项标签的时候的回调函数

### topMargin [可选, Number]
#### topMargin [可选, Number]
第一个目录标签在被认为可见之前需要向下移动的距离,默认值:0

### bottomMargin [可选, Number]
#### bottomMargin [可选, Number]
同上,向下移动的距离,默认值:0
Binary file added assets/simple.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 31 additions & 26 deletions src/index.js
Expand Up @@ -7,7 +7,8 @@ export default function(opts) {
scrollWrapper: null, // 按优先级排序
activeHook: null, // 激活时候回调
topMargin: 0,
bottomMargin: 0
bottomMargin: 0,
cool: true // 炫酷模式开关
}

const Opt = Object.assign({}, defaultOpts, opts)
Expand All @@ -31,8 +32,11 @@ export default function(opts) {
const tocPath = $catalog.querySelector('.cl-marker path')
let tocItems, pathLength // 左边svg-path长度

window.addEventListener('resize', drawPath, false)
$scroll_wrap.addEventListener('scroll', sync, false)
// 事件注册
window.addEventListener('resize', drawPath)
$catalog.addEventListener('click', clickHandler)
Opt.cool && $scroll_wrap.addEventListener('scroll', coolScrollHandler)
Opt.cool || $scroll_wrap.addEventListener('scroll', simpleScrollHandler)

setTimeout(drawPath) // 放在宏任务中,防止找不到DOM

Expand All @@ -41,7 +45,6 @@ export default function(opts) {
*/
function drawPath() {
tocItems = [...$catalog.querySelectorAll('li')]
// Cache element references and measurements
tocItems = tocItems.map(function(liDom) {
const anchor = liDom.querySelector(`.${Opt.linkClass}`)
const target = document.getElementById(anchor.getAttribute('data-cata-target'))
Expand All @@ -52,27 +55,24 @@ export default function(opts) {
target: target
}
})
// Remove missing targets
tocItems = tocItems.filter(item => !!item.target)

const path = []
let pathIndent

tocItems.forEach(function(item, i) {
tocItems.forEach(function(item, idx) {
const { offsetLeft, offsetTop, offsetHeight } = item.anchor,
x = Opt.cool ? offsetLeft - 5 : offsetLeft,
y = offsetTop,
height = offsetHeight

const x = item.anchor.offsetLeft - 5,
y = item.anchor.offsetTop,
height = item.anchor.offsetHeight

if (i === 0) {
if (idx === 0) {
path.push('M', x, y, 'L', x, y + height)
item.pathStart = 0
}
else {
// Draw an additional line when there's a change in indent levels
if (pathIndent !== x) path.push('L', pathIndent, y)
if (pathIndent !== x) path.push('L', pathIndent, y) // 缩进级别发生变化
path.push('L', x, y)
// Set the current path so that we can measure it
tocPath.setAttribute('d', path.join(' '))
item.pathStart = tocPath.getTotalLength() || 0
path.push('L', x, y + height)
Expand All @@ -82,26 +82,32 @@ export default function(opts) {
item.pathEnd = tocPath.getTotalLength()
})
pathLength = tocPath.getTotalLength()
sync()
coolScrollHandler()
}

function sync() {
/**
* 炫酷模式下滚动事件
*/
function coolScrollHandler() {
const wrapHeight = $scroll_wrap.clientHeight
let pathStart = pathLength,
pathEnd = 0,
visibleItems = 0
tocItems.forEach(function(liItem) {
const { bottom, top } = liItem.target.getBoundingClientRect()
const { bottom, top } = liItem.target.getBoundingClientRect(),
firstChild = liItem.listItem.firstChild
if (bottom > Opt.topMargin && top < wrapHeight - Opt.bottomMargin) {
pathStart = Math.min(liItem.pathStart, pathStart)
pathEnd = Math.max(liItem.pathEnd, pathEnd)
visibleItems += 1
liItem.listItem.classList.add('visible')
firstChild.classList.add(Opt.linkActiveClass)
Opt.cool && firstChild.classList.add('cl-transform')
} else {
liItem.listItem.classList.remove('visible')
firstChild.classList.remove(Opt.linkActiveClass)
Opt.cool && firstChild.classList.remove('cl-transform')
}
})
if (visibleItems > 0 && pathStart < pathEnd) {
if (visibleItems > 0 && pathStart < pathEnd && Opt.cool) {
tocPath.setAttribute('stroke-dashoffset', '1')
tocPath.setAttribute('stroke-dasharray', `1, ${pathStart}, ${pathEnd - pathStart}, ${pathLength}`)
tocPath.setAttribute('opacity', '1')
Expand All @@ -112,10 +118,9 @@ export default function(opts) {
}

/**
* 滚动处理事件
* @param e
* 普通模式下滚动事件
*/
$scroll_wrap.addEventListener('scroll', function resolveScroll(el) {
function simpleScrollHandler(el) {
let scrollToEl = null
for (let i = allCatalogs.length - 1; i >= 0; i--) {
if (allCatalogs[i].offsetTop <= $scroll_wrap.scrollTop) {
Expand All @@ -125,15 +130,15 @@ export default function(opts) {
}
if (scrollToEl) setActiveItem(scrollToEl.id)
else setActiveItem(null) // 无匹配的元素
})
}

/* 点击事件 */
$catalog.addEventListener('click', function({ target }) {
function clickHandler({ target }) {
const datasetId = target.getAttribute(Opt.datasetName)
target.classList.contains(Opt.linkClass) &&
document.getElementById(datasetId)
.scrollIntoView({ behavior: "smooth", block: "start" })
})
}

/**
* 获取目录树,生成类似于Vnode的树
Expand Down
11 changes: 5 additions & 6 deletions src/progress-catalog.css
Expand Up @@ -9,23 +9,22 @@
list-style: none;
}

.cl-wrapper li.visible > .cl-link {
.cl-wrapper li > .cl-link.cl-link-active {
color: rgba(66, 185, 131, 0.9);
transform: translate(3px);
transition: .5s;
}

.cl-wrapper li > .cl-transform.cl-link-active {
transform: translate(3px);
}

.cl-wrapper .cl-link {
cursor: pointer;
color: rgba(52, 73, 94, 0.5);
font-size: 13px;
transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1);
}

.cl-wrapper .cl-link-active {
color: rgba(66, 185, 131, 0.9);
}

.cl-wrapper .cl-marker {
position: absolute;
top: 0;
Expand Down

0 comments on commit 3e2cc3b

Please sign in to comment.