前端新手指引:Driver.js前端产品步骤引导库,在svelte项目中安装和使用

·  阅读 1092
前端新手指引:Driver.js前端产品步骤引导库,在svelte项目中安装和使用

一、安装

由于本工程是采用lerna实现的单工程多bundle的形式,所以在安装时候按照lerna的安装标准执行命令如下:

lerna add driver.js --scope=vr-config   // 将 driver.js 安装到 vr-config工程
复制代码

在其他工程中的安装:

yarn add driver.js
或
npm install driver.js
复制代码

二、在需要加引导的页面引入并使用

1.基本使用

<script lang="ts">
  import { onMount } from 'svelte';
  import Driver from "driver.js";

  onMount(() => {
    // 新手引导
    showTips();
  })
  // 新手指引
  const showTips = () => {
     const driver = new Driver();
      driver.highlight({
        element: "#driver-demo",
        stageBackground: "#ffa0a0",
        popover: {
          title: "温馨提示",
          description: "这是本站的首页",
          position: "bottom",
          className: "first-step"
        }
      });
  }
</script>

<div class="w-full relative flex justify-center items-center bg-color" >
  <h1>测试driver.js</h1>
  <button id="driver-demo">新手指引测试</button>
</div>

<style>
.container-height {
  height: calc(100% - 38px);
}
</style>
复制代码

2.提供步骤,以指导用户有关功能的信息 (刷新或者再次打开该网页仍有引导)

<script lang="ts">
  import { onMount } from 'svelte';
  import Driver from "driver.js";

  onMount(() => {
    // 新手引导
    showTips();
  })
  // 新手指引
  const showTips = () => {
     const driver = new Driver({
        prevBtnText: "上一步",
        nextBtnText: "下一步",
        doneBtnText: "我知道了",
        closeBtnText: "关闭"
      });
      const steps = [
        {
          element: "#first-des",
          popover: {
            title: "这是本站首页",
            description: "本站首页是一些展示性的信息",
            position: "bottom"
          }
        },
        {
          element: "#second-des",
          popover: {
            title: "这是素材上传",
            description: "素材上传",
            position: "top"
          }
        },
        {
          element: "#third-des",
          popover: {
            title: "这是编辑指导",
            description: "视频指导",
            position: "right"
          }
        }
      ];
      driver.defineSteps(steps);
      driver.start();
  }
</script>

<div class="w-full relative flex justify-center items-center bg-color" >
  <h1>测试driver.js</h1>
  <button id="first-des">首页</button>
  <button id="second-des">素材上传</button>
  <button id="third-des">编辑指导</button>
</div>

<style>
.container-height {
  height: calc(100% - 38px);
}
</style>
复制代码

3.新手引导,当用户第一次访问该网站的时候,才有新手引导,刷新或者再次打开该网页 ,无引导

入口初始化时候 用localStorage存取访问的状态firstVisitEditor

let flag = localStorage.getItem("firstVisitEditor");

用户关闭了新手引导,此时需设置firstVisitEditor,表明该用户已经访问过该网页(不是第一次访问),下次在同一台电脑上再打开该网页的时候,将不再显示新手引导(用户手动清除缓存的情况除外)

onReset: (ele) => {

//Called when overlay is about to be cleared; 用户关闭了新手引导,此时需设置firstVisitEditor,表明该用户已经访问过该网页(不是第一次访问),下次在同一台电脑上再打开该网页的时候,将不再显示新手引导(用户手动清除缓存的情况除外)

localStorage.setItem(

"firstVisitEditor",

JSON.stringify({ firstVisitEditor: false })

);

},

<script lang="ts">
  import { onMount } from 'svelte';
  // 引入driver.js
  import Driver from "driver.js";
	// 入口初始化时候 用localStorage存取访问的状态firstVisitEditor
  onMount(() => {
    // 新手引导
    let flag = localStorage.getItem("firstVisitEditor");
      if (!flag) {
        // flag不存在,即当用户第一次访问该网页的时候,调用showTips,显示新手引导
        showTips();
      }
  })
  // 新手指引
  // 每个步骤都有唯一的id 对应到页面的html中的id
  const showTips = () => {
    const driver = new Driver({
      prevBtnText: "上一步",
      nextBtnText: "下一步",
      doneBtnText: "我知道了",
      closeBtnText: "关闭",
      onReset: (ele) => {
        //Called when overlay is about to be cleared; 用户关闭了新手引导,此时需设置firstVisitEditor,表明该用户已经访问过该网页(不是第一次访问),下次在同一台电脑上再打开该网页的时候,将不再显示新手引导(用户手动清除缓存的情况除外)
        localStorage.setItem(
          "firstVisitEditor",
          JSON.stringify({ firstVisitEditor: false })
        );
      },
    });
    const steps = [
      {
        element: "#first-des",
        popover: {
          title: "这里是页面列表区域",
          description: "在这里你可以直观地看到你的页面列表",
          position: "right",
        },
      },
      {
        element: "#second-des",
        popover: {
          title: "添加组件前,你需要添加一个页面来承载组件",
          description: "VR 场景可以添加多个页面,分别可以添加2D和3D页面,每个组件添加前需要创建一个页面",
          position: "bottom",
        },
      },
      {
        element: "#third-des",
        popover: {
          title: "这是组件列表开关",
          description: "开关打开后,点击组件列表区域,你可以快速选择组件来进行拖动编辑",
          position: "top",
        },
      },
      {
        element: "#fourth-des",
        popover: {
          title: "这是模型素材开关",
          description: "如果你还没有想好要做成什么样子,打开模型素材开关来看看我们的成品区域吧",
          position: "top",
        },
      },
      {
        element: "#mainIframe",
        popover: {
          title: "介绍中间部分",
          description: "中间是可视化拖动区域,对于一些组件你都可以拖动来改变他的位置/大小",
          position: "right",
        },
      },
      {
        element: "#sixth-des",
        popover: {
          title: "介绍属性栏",
          description: "这里是属性编辑区域,您可以对组件的属性进行修改",
          position: "left",
        },
      },
    ];
    driver.defineSteps(steps);
    driver.start();
  }

</script>

<div class="container-height w-full relative flex justify-center items-center bg-color" >
  <div class="h-full absolute flex flex-row top-0 overflow-hidden" style="left: 205px;">
    <ComponentsMenu></ComponentsMenu>
  </div>
  <Container></Container>
  <!-- <div id="WebGL-output" /> -->
  <!-- <Helper /> -->
  <div class="h-full absolute flex flex-row left-0 top-0">
    <Layout></Layout>
    <TemplateLayout></TemplateLayout>
  </div>
  // id和steps中id相对应 其他id在子组件中
  <div id="sixth-des" class="h-full absolute flex flex-row right-0 top-0">
    <MaterielForm></MaterielForm>
  </div>
  <EventModal/>
</div>

<style>
.container-height {
  height: calc(100% - 38px);
}
</style>
复制代码

4.跨组件跨路由时候新手指引如何设置呢?

每个路由子组件入口组件中分别在localStorage中设置不同的参数,来标识当前的路由下的组件或者页面,是否是第一次访问的

如我的项目分为三个路由,也就是页面链接一共是三个,我也不知道用户什么时候跳转到下一个路由页面,所以每个路由子页面都设置不用的状态来管理

vr1.png

VR2.png

PhoneEdge.svelte中

onMount(
    () => {
    // 新手引导
    let flag = localStorage.getItem("firstVisitEdge");
    if (!flag) {
      // flag不存在,即当用户第一次访问该网页的时候,调用showTips,显示新手引导
      showTips();
    }
    )
  // 新手指引
const showTips = () => {
    const driver = new Driver({
      prevBtnText: "上一步",
      nextBtnText: "下一步",
      doneBtnText: "我知道了",
      closeBtnText: "关闭",
      stageBackground: '#808080',
      onReset: (ele) => {
        //Called when overlay is about to be cleared; 用户关闭了新手引导,此时需设置firstVisitEdge,表明该用户已经访问过该网页(不是第一次访问),下次在同一台电脑上再打开该网页的时候,将不再显示新手引导(用户手动清除缓存的情况除外)
        localStorage.setItem(
          "firstVisitEdge",
          JSON.stringify({ firstVisitEdge: false })
        );
      },
    });
    const vidoHtml=`<video controls width="450">

                    <source src="https://www.w3schools.com/media/cc0-videos/flower.webm"
                            type="video/webm">

                    <source src="https://www.w3schools.com/html/mov_bbb.mp4"
                            type="video/mp4">

                    Sorry, your browser doesn't support embedded videos.
                    </video>`;
    const steps = [
      {
        element: "#first-model",
        popover: {
          title: "这里是体验示例",
          description: vidoHtml,
          position: "right",
        },
      },
      {
        element: "#second-model",
        popover: {
          title: "这里是一键矫正",
          description: "在测试图片的时候可以使用一键矫正的功能,如果你只是想测试我们的功能,那就可以直接点击这个按钮哦",
          position: "right",
        },
      }
    ];
    driver.defineSteps(steps);
    driver.start();
  }
复制代码

PhotoUpload.svelte

onMount(() => {
  // 新手引导
  let flag = localStorage.getItem("firstVisitUpload");
  if (!flag) {
    // flag不存在,即当用户第一次访问该网页的时候,调用showTips,显示新手引导
    showTips();
  }
});
// 新手指引
const showTips = () => {
    const driver = new Driver({
      prevBtnText: "上一步",
      nextBtnText: "下一步",
      doneBtnText: "我知道了",
      closeBtnText: "关闭",
      // stageBackground: '#808080',
      onReset: (ele) => {
        //Called when overlay is about to be cleared; 用户关闭了新手引导,此时需设置firstVisitUpload,表明该用户已经访问过该网页(不是第一次访问),下次在同一台电脑上再打开该网页的时候,将不再显示新手引导(用户手动清除缓存的情况除外)
        localStorage.setItem(
          "firstVisitUpload",
          JSON.stringify({ firstVisitUpload: false })
        );
      },
    });
    const steps = [
      {
        element: "#first-img",
        popover: {
          title: "这里是图片上传",
          description: "点击/拖拽全景图(检测图片是否为 2: 1 的比例)至指定区域(上传规定的全景图,即可开启VR世界)",
          position: "right",
        },
      },
      {
        element: "#second-img",
        popover: {
          title: "这里是体验示例",
          description: "如果您没有全景图,可以【使用体验示例】区域使用我们的示例图片;如果还没有拍摄好全景图,也欢迎使用我们的示例全景图",
          position: "right",
        },
      }
    ];
    driver.defineSteps(steps);
    driver.start();
  }
复制代码

Editor.svelte

onMount(() => {
    // 新手引导
    let flag = localStorage.getItem("firstVisitEditor");
      if (!flag) {
        // flag不存在,即当用户第一次访问该网页的时候,调用showTips,显示新手引导
        showTips();
      }
  })
  // 新手指引
  const showTips = () => {
    const driver = new Driver({
      prevBtnText: "上一步",
      nextBtnText: "下一步",
      doneBtnText: "我知道了",
      closeBtnText: "关闭",
      onReset: (ele) => {
        //Called when overlay is about to be cleared; 用户关闭了新手引导,此时需设置firstVisitEditor,表明该用户已经访问过该网页(不是第一次访问),下次在同一台电脑上再打开该网页的时候,将不再显示新手引导(用户手动清除缓存的情况除外)
        localStorage.setItem(
          "firstVisitEditor",
          JSON.stringify({ firstVisitEditor: false })
        );
      },
    });
    const steps = [
      {
        element: "#first-des",
        popover: {
          title: "这里是页面列表区域",
          description: "在这里你可以直观地看到你的页面列表",
          position: "right",
        },
      },
      {
        element: "#second-des",
        popover: {
          title: "添加组件前,你需要添加一个页面来承载组件",
          description: "VR 场景可以添加多个页面,分别可以添加2D和3D页面,每个组件添加前需要创建一个页面",
          position: "bottom",
        },
      },
      {
        element: "#third-des",
        popover: {
          title: "这是组件列表开关",
          description: "开关打开后,点击组件列表区域,你可以快速选择组件来进行拖动编辑",
          position: "top",
        },
      },
      {
        element: "#fourth-des",
        popover: {
          title: "这是模型素材开关",
          description: "如果你还没有想好要做成什么样子,打开模型素材开关来看看我们的成品区域吧",
          position: "top",
        },
      },
      {
        element: "#mainIframe",
        popover: {
          title: "介绍中间部分",
          description: "中间是可视化拖动区域,对于一些组件你都可以拖动来改变他的位置/大小",
          position: "right",
        },
      },
      {
        element: "#sixth-des",
        popover: {
          title: "介绍属性栏",
          description: "这里是属性编辑区域,您可以对组件的属性进行修改",
          position: "left",
        },
      },
    ];
    driver.defineSteps(steps);
    driver.start();
  }
复制代码

三、从新手指引看实现原理

看秋风的笔记中有文章介绍:从王者荣耀里我学会的前端新手指引juejin.cn/post/689105…

直接贴代码:

// 蒙层实现
<style>
.guide-mask {
  z-index: 999999;
  background-color: #000;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  position: fixed;
  opacity: 0.8;
}
</style>
<div class="guide-mask"></div>
复制代码
// 气泡实现
<style>
.tooltip-box:before {
  content: "";
  position: absolute;
  right: 100%;
  top: -10px;
  left: 20%;
  width: 0;
  height: 0;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  border-bottom: 13px solid white;
}
</style>
<div class='tooltip-box'>
  气泡实现
</div>
复制代码

上面没什么可解释的比较容易理解下面来说下

定位

我们通过 getBoundingClientRect 属性来获取目标元素的大小及其相对于视口的位置。然后通过绝对定位来进行布局。

<style>
  ...
  .guide-helper-layer {
    position: absolute;
    z-index: 9999998;
    background-color: #FFF;
    background-color: rgba(255, 255, 255, .9);
    border-radius: 4px;
  }
  .guide-content {
    position: absolute;
    z-index: 10000000;
    background-color: transparent;
  }
  .guide-mark-relative {
    position: relative;
    z-index: 9999999 !important;
  }
  ...
</style>
</head>
<body>
    <h2>新手指引demo</h2>
    <div class="skill guide-mark-relative">
        ...
    </div>
    <div class="guide-mask"></div>
    <div class="guide-helper-layer" style="width: 472px; height:58px; top:55px;left: 36px;">
        <div class='tooltip-box'>
            气泡实现
        </div>
    </div>
    <script>
        const guideTarget = document.querySelector('.skill')
        const tooltip = document.querySelector('.tooltip-box')
        var rect = guideTarget.getBoundingClientRect()
        const helperLayer = document.querySelector('.guide-helper-layer')
        helperLayer.style.left = rect.left - 3 + 'px'
        helperLayer.style.top = rect.top - 3 + 'px'
        helperLayer.style.width = rect.width + 3 * 2 + 'px'
        helperLayer.style.height = rect.height + 3 * 2 + 'px'
        tooltip.style.top = rect.height + 3 * 2 + 10 + 5 + 'px'
</script>
复制代码

效果预览&&源码

感谢阅读

❤️关注+点赞+收藏+评论+转发❤️,原创不易,鼓励笔者创作更好的文章

关注公众号小圆脸儿,一个专注于web前端基础、工程化、面试的前端公众号

分类:
前端
分类:
前端
收藏成功!
已添加到「」, 点击更改