初入前端,最近在使用word时发现有个批注功能,就想的如何用代码去实现一下css
1.页面总体分为左中右两部分,中间为正文内容区域,右右两侧为注释浏览区域
2.右侧展现的注释内容必须与所需注释词汇在一条线上
3.初始时只显示两行内容,点击时展开所有
4.若是两个被注释的词距离太近,注释部分要求依次排序html
1.在注释内容外侧添加一个div,利用div的min-height属性控制注释的位置
2.利用position: absolute绝对定位,动态的生成和改变注释的位置前端
在实现上述两种方法的过程当中发现,第一种方案在数据量庞大的状况下,会出现bug,页面会奔溃,果断放弃了,选择了第二种方式实现jquery
1> args--------->当前文章内容中有注释的词集合
2> notes-------->从库中获取到的注释文本集合
3> rightWrap---->右侧部分注释区域对象
4> leftWrap----->左侧部分注释区域对象数据库
1> setSite()------------------------------>初始界面加载时肯定注释的位置
2> resetTop(elem, type)------------------->在点击时从新设置全部注释的位置
elem:当前被点击的对象
type:(open/close)所有展开或部分展现
3> bindClick(elem, type, selector, fn)---->绑定事件函数
elem:绑定事件的元素
type:绑定的事件类型,例如(click)
selector:动态添加到elem中的元素
fn:绑定事件执行后回调方法app
1> index.html部分代码ide
<div class="wrap"> <aside class="left"></aside> <article class="center"> <h3>人世</h3> <br /> <p>使其停下来</p> <p>使光影、蜉蝣</p> <p><b class="special-0 nleft">众生</b>的所向是什么</p> <p>尤以静止方可得出</p> <p>我不作空明的阐述</p> <p>我是凡人,且一直落在凡尘里</p> <p>使云霞似锦吧</p> <p>若产出时间的黄金</p> <p>时间的<b class="special-1">黄金</b>只能在一颗内心</p> <p>播种,<b class="special-2">萌发</b>,成为照耀</p> <p>内敛的照耀比及月亮</p> <p>咱们需作辉光的同谋人</p> <p>咱们依旧不能成为闪电或是惊雷</p> <p>咱们只是平凡的形形色色</p> <p>为全部悸动欢呼的应该是另外一群人</p> <p>那些卑微的怯懦的都给我</p> <p>我隐在暗处说——</p> <p>“这很好!”,是的,你注视我说——</p> <p>“你很好!”</p> <p>还有可使其堕落下去使其沦陷下去的吗</p> <p>光影、<b class="special-3">蜉蝣</b>、我和你</p> <p>和岸边无风也要摇荡的芦苇</p> <p>和彷佛永不休止的蝉鸣</p> <p>和流水</p> </article> <aside class="right"></aside> </div>
2> index.css部分代码函数
.wrap { display: flex; position: relative; width: 100%; } article.center { flex: 1; text-align: justify; padding: 20px; border-right: 1px solid #ddd; border-left: 1px solid #ddd; } article.center p { line-height: 24px; } article.center p b { color: red; } aside.left, aside.right { width: 300px; padding: 20px 0; } .wrap aside mark { background-color: #fff; color: #afafaf; padding: 0 20px; position: absolute; top: 0; height: 44px; overflow: hidden; line-height: 20px; font-size: 12px; text-align: justify; cursor: pointer; width: 260px; }
3> index.js部分代码flex
; (function() { // 构造函数 function View(elem, notes, rightWrap, leftWrap) { this.rightWrap = rightWrap; this.leftWrap = leftWrap; this.args = typeof elem === 'object' ? elem : document.getElementById(elem); this.notes = notes === undefined ? [] : notes; this.init(); } // 原型 View.prototype = { constructor: View, init: function() { var self = this; self.setSite(); self.bindClick(document.body, 'click', 'mark', function (e) { var target = e.target; if(this.style.height) { this.style.height = ''; self.resetTop(this, 'close'); return; } else { this.style.height = this.scrollHeight +'px'; self.resetTop(this, 'open'); } }); }, // 设定初始高度 setSite: function() { for(let i = 0; i < this.args.length; i++) { // 默认新建的批注距离顶部的高度 var swdTop = 0; var addMark = ''; // 计算当前批注的高度是否被覆盖,若是被覆盖,进行处理 if(i > 0) { if(this.args[i].offsetTop - this.args[i-1].offsetTop > $('.note-' + (i-1)).height()) { swdTop = this.args[i].offsetTop - 2 + 'px'; } else { swdTop = this.args[i-1].offsetTop + $('.note-' + (i-1)).height() - 2 + 'px'; } } else { swdTop = this.args[i].offsetTop - 2 + 'px'; } if(this.notes.length > 0) { addMark = '<mark class="note-' + i + '" style="top:' + swdTop + '">'+ this.args[i].innerHTML +':' + this.notes[i] + '</mark>'; } else { addMark = ''; } // 将获得的新标签动态添加到容器中 if(this.args[i].classList.length > 1 && this.args[i].classList[1] === 'nleft' && this.leftWrap !== undefined) { this.leftWrap.append(addMark); } else { this.rightWrap.append(addMark); } } }, // 从新设置元素高度 resetTop: function(elem, type) { let index = parseInt(elem.className.substr(elem.className.indexOf('-')+1)); for(; index < this.args.length-1; index++) { var swdNewTop = 0; var addTop = []; if(this.args[index+1].offsetTop - this.args[index].offsetTop > $('.' + elem.className).height()) { console.log('咱们不须要执行任何东西了') return } else { if(type === 'open') { swdNewTop = this.args[index].offsetTop + $('.' + elem.className).height() + 8 + 'px'; addTop[index+1] = swdNewTop; } else { swdNewTop = this.args[index].offsetTop + $('.' + elem.className).height() + 'px'; } $('.note-' + (index+1)).attr('style', 'top:' + swdNewTop); return } } }, // 绑定元素点击事件 bindClick: function(elem, type, selector, fn) { if(fn === null) { fn = selector; selector = null; } elem.addEventListener(type, function(e) { var target = e.target; if(selector) { target = e.target; if(target.matches(selector)) { fn.call(target, e); } } else { fn(e); } }) } } // 对外公开方法 window.View = View; })();
(function($) { $.fn.extend({ viewDocument: function(notes, rightWrap, leftWrap) { new View(this, notes, rightWrap, leftWrap); // 为了保证jQuery全部的方法可以实现链式访问,每一个方法的最后必须返回this,即返回jquery的实例 return this; } }) })(jQuery);
// 此内容从数据库中获取,这里只是举个例子 let notes = [ '某些脑残们如今农村你如今,每次, 很快就恢复九分裤空间发挥科技的护肤开始开好房间快点恢复快接啊汉兰达!', '梦想决定了开始,没拿到,啥的,明年初,茉香奶茶, 空间打开手机上看到空间发挥的机会福克斯杜鹃花开始疯狂开几号放假回家看到好看接电话时刻,会尽快的释放开好房间大客户', '没你聪明,在哪吃没写呢不出毛病都说了卡刷卡机打尽快打款收到啦囊括了速度很快啦可垃圾袋', '欧文一二恶牛肉回复可见回复可见空间十分开始。很快地恢复快速回复确定是客户反馈的金凤凰,等会看是否考核得分健康的首付款' ]; // 获取注释所在的容器 let rightWrap = $('aside.right'); let leftWrap = $('aside.left'); $('.center b').viewDocument(notes, rightWrap, leftWrap);
以上写的时间比较急,代码很粗糙,有相似功能的大神们有好的建议或者想法多多留言与分享,谢谢 先就这些吧,后续再继续改进和优化