资讯专栏INFORMATION COLUMN

类似world中批注在侧边栏浏览功能的js实现

willin / 1321人阅读

摘要:很快地恢复快速回复肯定是客户反馈的金凤凰,等会看是否考核得分健康的首付款获取注释所在的容器四总结以上写的时间比较急,代码很粗糙,有类似功能的大神们有好的建议或者想法多多留言与分享,谢谢先就这些吧,后续再继续改进和优化

初入前端,最近在使用word时发现有个批注功能,就想的如何用代码去实现一下

一、大概需求如下:

1.页面整体分为左中右两部分,中间为正文内容区域,右右两侧为注释浏览区域
2.右侧展示的注释内容必须与所需注释词汇在一条线上
3.初始时只显示两行内容,点击时展开全部
4.如果两个被注释的词距离太近,注释部分要求依次排序

二、预设解决方案

1.在注释内容外侧添加一个div,利用div的min-height属性控制注释的位置
2.利用position: absolute绝对定位,动态的生成和改变注释的位置

三、实现过程

在实现上述两种方法的过程中发现,第一种方案在数据量庞大的情况下,会出现bug,页面会奔溃,果断放弃了,选择了第二种方式实现

1.常量部分:

1> args--------->当前文章内容中有注释的词集合
2> notes-------->从库中获取到的注释文本集合
3> rightWrap---->右侧部分注释区域对象
4> leftWrap----->左侧部分注释区域对象

2.方法部分

1> setSite()------------------------------>初始界面加载时确定注释的位置
2> resetTop(elem, type)------------------->在点击时重新设置所有注释的位置
elem:当前被点击的对象
type:(open/close)全部展开或部分展示
3> bindClick(elem, type, selector, fn)---->绑定事件函数
elem:绑定事件的元素
type:绑定的事件类型,例如(click)
selector:动态添加到elem中的元素
fn:绑定事件执行后回调方法

3.整体代码

1> index.html部分代码

人世


使其停下来

使光影、蜉蝣

众生的所向是什么

尤以静止方可得出

我不做空明的阐述

我是凡人,且一直落在凡尘里

使云霞似锦吧

若产出时间的黄金

时间的黄金只能在一颗心里

播种,萌发,成为照耀

内敛的照耀比及月亮

我们需做辉光的同谋人

我们依旧不能成为闪电或是惊雷

我们只是平凡的形形色色

为所有悸动欢呼的应该是另一群人

那些卑微的怯懦的都给我

我隐在暗处说——

“这很好!”,是的,你注视我说——

“你很好!”

还有可以使其堕落下去使其沦陷下去的吗

光影、蜉蝣、我和你

和岸边无风也要摇荡的芦苇

和似乎永不休止的蝉鸣

和流水

2> index.css部分代码

.wrap {
    display: flex;
    position: relative;
    width: 100%;
}
article.center {
    flex: 1;
    text-align: justify;
    padding: 20px;
    border-right: 1px solid #ffffd;
    border-left: 1px solid #ffffd;
}
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部分代码

;
(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 = ""+ this.args[i].innerHTML     +":" + this.notes[i] + "";
                 } 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;
})();
4.通过扩展方法将拖拽方法扩展到jquery的一个实例方法
(function($) {
  $.fn.extend({
    viewDocument: function(notes, rightWrap, leftWrap) {
      new View(this, notes, rightWrap, leftWrap);
      //  为了保证jQuery所有的方法能够实现链式访问,每个方法的最后必须返回this,即返回jquery的实例
      return  this;
    }
  })
})(jQuery);
5.在主界面上的调用方法
//  此内容从数据库中获取,这里只是举个例子
let notes = [
         "某些脑残们现在农村你现在,每次, 很快就恢复九分裤空间发挥科技的护肤开始开好房间快点恢复快接啊汉兰达!",
         "梦想决定了开始,没拿到,啥的,明年初,茉香奶茶, 空间打开手机上看到空间发挥的机会福克斯杜鹃花开始疯狂开几号放假回家看到好看接电话时刻,会尽快的释放开好房间大客户",
         "没你聪明,在哪吃没写呢不出毛病都说了卡刷卡机打尽快打款收到啦囊括了速度很快啦可垃圾袋",
         "欧文一二恶牛肉回复可见回复可见空间十分开始。很快地恢复快速回复肯定是客户反馈的金凤凰,等会看是否考核得分健康的首付款"
     ];
     
//  获取注释所在的容器
let rightWrap = $("aside.right");
let leftWrap = $("aside.left");
$(".center b").viewDocument(notes, rightWrap, leftWrap);

四、总结
以上写的时间比较急,代码很粗糙,有类似功能的大神们有好的建议或者想法多多留言与分享,谢谢
先就这些吧,后续再继续改进和优化

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108169.html

相关文章

  • HTML5 新特性

    一、HTML5与HTML4 1.1 推出的理由和目标 H5的出现,对于Web来说意义重大。因为他的意图是想要把目前Web上存在的各种问题一并解决掉。 Web浏览器之间的兼容性很低 文档结构不够明确(增加了很多结构, 语义化的标签) Web应用程序的功能受到了限制 H5 的出现极大的解决了上面的问题 1.2 语法的改变 1.2.1 DOCTYPE声明 H5 DOCTYPE的声明是这样的: ...

    王伟廷 评论0 收藏0
  • HTML5 新特性

    一、HTML5与HTML4 1.1 推出的理由和目标 H5的出现,对于Web来说意义重大。因为他的意图是想要把目前Web上存在的各种问题一并解决掉。 Web浏览器之间的兼容性很低 文档结构不够明确(增加了很多结构, 语义化的标签) Web应用程序的功能受到了限制 H5 的出现极大的解决了上面的问题 1.2 语法的改变 1.2.1 DOCTYPE声明 H5 DOCTYPE的声明是这样的: ...

    sunnyxd 评论0 收藏0
  • HTML5 新特性

    一、HTML5与HTML4 1.1 推出的理由和目标 H5的出现,对于Web来说意义重大。因为他的意图是想要把目前Web上存在的各种问题一并解决掉。 Web浏览器之间的兼容性很低 文档结构不够明确(增加了很多结构, 语义化的标签) Web应用程序的功能受到了限制 H5 的出现极大的解决了上面的问题 1.2 语法的改变 1.2.1 DOCTYPE声明 H5 DOCTYPE的声明是这样的: ...

    appetizerio 评论0 收藏0
  • 从今天开始,拿起VuePress打造属于自己专属博客

    摘要:故九万里,则风斯在下矣,而后乃今培风背负青天,而莫之夭阏者,而后乃今将图南。这里是文件的内容部分最后更新时间最后更新时间默认不开启,它是基于提交的时间戳,所以我们的静态站点是需要通过的仓库进行管理的,并且它是按的时间来计算的。VuePress(0.x版本) 本blog配套了一个基于 VuePress 的一个简单的配置案例,此配置案例包含了本blog绝大部分配置案例,更多详情请移步这里VueP...

    dantezhao 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<