js leader-line 学习及问题总结

leader-line一个在网页上画指引线的库,文档地址

leader-line 绘制指引线部分效果图预览

安装

在你的页面引入 leader-line 依赖项(下载链接

<script src="https://files.cnblogs.com/files/mggahui/leader-line.min.js"></script>

当然,也可通过npm方式安装,不过通过npm形式安装,使用的的时候会有一些问题,可参考文章末尾给出的解决方案

npm install leader-line -S

使用

指示线会被画在 start 和 end 两个元素之间

    <div id="start">start</div>
    <div id="end">end</div>
    <script>
        new LeaderLine(
            document.getElementById('start'),
            document.getElementById('end')
        );
    </script>

执行以上初始化代码后,页面效果如下

 

(这些指引线使用了一个叫leader-line的样式class,如果绘制指引线时出现遮挡情况,可以通过调整这个样式class的z-index或者position来处理。

同时我们也应该注意到:

①,避免定义全局className 为 leader-line 的样式,避免覆盖库的样式;

②,生成的 svg 指示线标签使用了相对于 body 绝对行为 (查看leader-line 的class样式可以看到)

现在我们来修改一下样式效果,让页面看起来更舒服些,可以通过css 修改元素样式和通过给 LeaderLine 构造函数传递参数修改样式(此处指 leader-line 修改指示线样式)。

其实我们也可以通过 LeaderLine 构造函数返回的实例来修改属性,因为这个实例具有和构造函数接收参数一样的同名属性(除了 hide 属性),当然我们推荐使用 setOptions 方法来修改属性,详情请参考文档。

给开始(start)和结束(end)元素添加样式后,重新运行效果如下

    <style>
        .target {
            display: inline-block;
            background-color: #9ee7ea;
            padding: 12px;
        }

        #start {}

        #end {
            float: right;
            margin-top: 200px;
        }
    </style>
  <div id="start" class="target">start</div>
  <div id="end" class="target">end</div>

现在,通过css样式把 start 和 end两个元素位置分隔的距离变大了,LeaderLine 初始化后默认会以红色带箭头实线绘制指示线,现在我们试试修改指示线的样式吧

修改指示线样式

通过添加 dash 参数修改为虚线样式

    var startEle = document.getElementById('start');
    var endEle = document.getElementById('end');

    var leader_line = new LeaderLine(
        startEle,
        endEle,
        {
            dash: true,
        }
    );

让指示线动起来

通过添加  animation 等参数,从下方开始,仅展示核心代码部分

    var leader_line = new LeaderLine(
        startEle,
        endEle,
        {
            startPlugColor: '#ff3792', // 渐变色开始色
            endPlugColor: '#fff386',// 渐变色结束色
            gradient: true, // 使用渐变色
            dash: { // 虚线样式
                animation: true,// 让线条滚动起来
            }
        }
    );

 实例的属性和方法

setOptions 方法

leader_line.setOptions(options)

该方法接受和构造函数相同的参数选项(除了 hide 属性)

show  ,  hide 方法

leader_line.show([showEffectName[, animOptions]])
leader_line.hide([showEffectName[, animOptions]])

显示或隐藏指示线 (showEffectName效果可取 'draw' 慢慢绘制效果和 'fade'淡入淡出效果)

position 方法

leader_line.position()

将 start 和 end 元素的当前位置和大小重新定位到指示线。如果您的网页在不调整窗口大小的情况下移动或调整了元素的大小应调用此方法重新定位指示线位置

scrollableBox.addEventListener('scroll', AnimEvent.add(function() {
  leader_line.position();
}), false);

remove 方法

leader_line.remove()

实例相关的svg标签将从页面上被删除,leader_line 实例也被销毁

更多方法和属性请参考文档

让指示线从开始到结束慢慢绘制出来

    var leader_line = new LeaderLine(
      startEle,
      endEle, {
        startPlugColor: '#ff3792', // 渐变色开始色
        endPlugColor: '#fff386', // 渐变色结束色
        gradient: true, // 使用渐变色
        dash: { // 虚线样式
          animation: true, // 让线条滚动起来
        },
        hide: true,
      },
    );
    /** 显示效果
     *  draw 从起点到终点绘制线条
     *  fade 淡入淡出
     *  none 无效果,即直接显示
     */
    var showEffectName = 'draw';
    // 动画参数
    var animOptions = {
      duration: 1000, //持续时长
      timing: 'ease-in', // 动画函数
    }
    leader_line.show(showEffectName, animOptions)

注意,想实现这个效果,必须先隐藏指示线,然后再调用实例 show 方法,并控制绘制时长。即在构造函数中添加 hide 选项来影藏指示线,然后再调用show方法,绘制效果写入 'draw'。

学习代码

页面效果完整代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>leader-line学习</title>
  <script src="https://cdn.bootcss.com/vConsole/3.3.4/vconsole.min.js"></script>

  <script>
    var vConsole = new VConsole(); // 移动端调试工具

  </script>
  <script src="https://files.cnblogs.com/files/mggahui/leader-line.min.js"></script>
  <style>
    .target {
      display: inline-block;
      padding: 12px;
      background-color: #9ee7ea;
    }

    #start {}

    #end {
      float: right;
      margin-top: 200px;
    }

  </style>
</head>

<body>
  <div id="start" class="target">start</div>
  <div id="end" class="target">end</div>
  <script>
    var startEle = document.getElementById('start');
    var endEle = document.getElementById('end');
    var leader_line = new LeaderLine(
      startEle,
      endEle, {
        startPlugColor: '#ff3792', // 渐变色开始色
        endPlugColor: '#fff386', // 渐变色结束色
        gradient: true, // 使用渐变色
        dash: { // 虚线样式
          animation: true, // 让线条滚动起来
        },
        hide: true,
      },
    );
    /** 显示效果
     *  draw 绘制线条
     *  fade 淡入
     *  none 无效果,即直接显示
     */
    var showEffectName = 'draw';
    // 动画参数
    var animOptions = {
      duration: 1000, //持续时长
      timing: 'ease-in', // 动画函数
    }
    leader_line.show(showEffectName, animOptions)

  </script>
</body>

</html>
leader-line学习

使用 leader-line 遇到的问题

①,安装引入依赖问题

1,在项目中直接使用 script 标签引入的时候,会报错   Uncaught ReferenceError: LeaderLine is not defined   


2,若使用如下方式(通过 npm 安装的),会报错   Uncaught TypeError: leader_line__WEBPACK_IMPORTED_MODULE_0___default.a is not a constructor  

import LeaderLine from 'leader-line';
const myLine = new LeaderLine(
     document.getElementById('start'),
     document.getElementById('end')
);

 报模块找不到,是因为 leader-line 包文件没有支持 es6 等模块导出语法,整个文件就只有一个函数。

查看 leader-line node_module 包文件发现,该文件仅仅定义了一个LeaderLine 函数 ,并没有使用任何模块导出语句 (即没有module.export 或者 es6 export 导出语句)

既然找到了问题产生原因,有以下对应方案解决问题

方案一

解决思想是手工在文件末尾添加es6模块导出语句

①,把 leader-line.min.js 文件复制出来到自己项目文件中,并在文件末尾末尾添加 es6 模块导出语句 "export default LeaderLine",如下图所示

②,然后在你的项目中使用import语句导入

import LeaderLine from 'leader-line'

方案二

解决思想是申明LeaderLine为全局外部变量(使用webpack 配置CDN方式)

①,在index.html文件中以script标签形式引入leader-line.min.js 文件(因为是script引入,所以需要将文件修改为UMD模块规范,为什么还是要改源码呢,因为cdn引入后,在页面上依旧使用模块导入语句使用代码的,如,reuqire后者import)

②,在vue.config.js文件中配置 externals 字段来申明引入外部依赖文件,配置如下所示

  configureWebpack: (config) => {
    config.externals = {
      'leader-line': 'LeaderLine',
    }
  },

③,然后在你的项目中使用import语句导入

import LeaderLine from 'leader-line'

上面两种方案需要手动修改源码,推荐使用下面方案三

方案三 (推荐)

使用 skeleton-loader (自定义loader)

①,npm安装依赖 

npm install skeleton-loader -D
npm install leader-line -S

②,添加如下 webpack loader 配置

  module: {
    rules: [
      {
        test: require('path').resolve(__dirname, 'node_modules/leader-line/'),
        use: [{
          loader: 'skeleton-loader',
          options: {procedure: content => `${content}export default LeaderLine`}
        }]
      }
    ]
  }

若是 vuecli3 项目,可在 vue.config.js 配置文件中添加如下配置

  configureWebpack: (config) => {
    config.module.rules.push(
      {
        test: path.resolve(__dirname, 'node_modules/leader-line/'),
        use: [{
          loader: 'skeleton-loader',
          options: {procedure: content => `${content}export default LeaderLine`}
        }]
      }
    )
  },

③,然后在你的项目中使用import语句导入

import LeaderLine from 'leader-line' 

解决方案参考链接

https://stackoverflow.com/questions/62932910/using-leader-line-on-vuejs

https://github.com/anseki/leader-line/issues/8

②,移动端屏幕滚动问题

 

可以看到,指示线绘制出来后,屏幕滚动,指示线并没有跟随滚动,而是固定在屏幕上啦。

究其本质,是因为leader-line 绘制的svg指示线是利用相对于 body 的 absolute 定位。而在移动端给body的布局高度为 height:100%,页面是在body局部滚动的,所以指示线的位置相对body始终是固定的,在屏幕上看起来也就是固定不变的。

解决方案:

  方案一:使得页面的滚动是body在滚动,而不是body的局部区域滚动,即需要修改body高度为非页面高度,同时调整布局 (修改代价比较大)

  方案二:使用实例 position 方法重新定位指示线位置 (推荐)

  方案三:移动svg(指示线元素)到另外一个容器中(定位基准)  https://github.com/anseki/leader-line/issues/54

③,SPA应用页面间切换问题

举例:在 SPA(单页面应用)中有 A,B 两个页面,当在 A 页面生成 leader-line 指示线后,这个时候切换到 B 页面,在 B 页面依旧会显示上一个页面的 leader-line 指示线(由 svg 定位决定)。

原因:因为 leader-line svg 标签相对于 body 绝对定位生成,所以即使你切换新页面,也依旧会显示上个页面的 leader-line 指示线。(本质上 A,B 两个页面还是同一个 html 页面上)

解决方案: 

  方案一:切换页面时候,销毁 leader_line 实例 ,即调用 leader_line.remove() 方法

  方案二:切换页面时候,隐藏 leader_line 实例 ,重新切换回来的时候,再显示 leader_line 实例。即调用 leader_line.show() 方法,leader_line.hide() 方法

④,html2canvas不能保存生成的指示线为图片

原因:html2canvs有些情况下会出现不能保存 svg 为图片(具体哪些情况待定)

解决:参考 https://www.cnblogs.com/mggahui/p/14118293.html 

@萍2樱释ღ( ´・ᴗ・` )

打不死的小强
原文地址:https://www.cnblogs.com/mggahui/p/13715361.html