如何做新人引導功能?

linong發表於2022-05-18

功能點

節前碰到一個需求:「新人引導效果」針對第一次使用平臺的使用者進行主要功能引導
具體引導路徑為:點選“新增按鈕”,對彈出的內容進行解釋,並引導使用者填充表單,最後提交表單。

下面為效果截圖(感興趣的兄弟們可以自己實現一下,我用的 vue + ElementUI):

  1. image.png
  2. image.png
  3. image.png
  4. image.png

我們打工人要的就是效率,我們不生產輪子,我們都是輪子的搬運工。

是否有現成的輪子?

通過搜尋引擎來查詢解決辦法。

常見外掛

實現

我試用了一下 introjs 和 driver.js,最後使用了 introjs 來實現,但是兩個庫都有不如意的點

  1. introjs

    1. http://jsrun.net/ERQKp/edit 新增按鈕是好使的,但是彈窗中的 input 無法單擊。(也有可能是 elementUI 有毒)
      我最後使用 pointer-events: none;user-select: none; + 引導中狀態來自行實現的功能。
    2. 不支援 next 回撥,不支援 delay 控制。
      我最後把引導分為了兩步來實現,手動實現 delay 邏輯
  2. driver.js

    1. http://jsrun.net/PmQKp/edit 看上去彈窗的時候,層級關係就不對了。我直接就麻了。

當然了,即使這麼難,但還是有辦法的。introjs 實現案例:http://jsrun.net/KAQKp/edit雖然相容性有可能堪憂

拆解功能點

雖然有外掛,但是我們也可以瞭解一下如何實現。我們來拆解一下

  1. 高亮功能&遮罩功能

    1. fixed + z-index 層級
    2. box-shadow
    3. border + 位移
  2. 獲取元素位置方便定位
  3. 上一步、下一步等回撥方便處理邏輯。

高亮功能&遮罩功能

image.png

https://jsrun.net/cRQKp/edit
可以看到基本能滿足,但是底部還是可單擊的。而且並沒有分層

image.png

通過增加遮罩層來實現分層功能,這樣就可以阻止事件了。https://jsrun.net/duQKp/edit

但是這裡還是有一個問題的。z-index 不能超過父級。所以我們需要增加多個層,來規避這個問題。

獲取元素位置 popper 定位

popper 的功能我們可以使用一些三方庫來實現

  1. popper.js
    https://jsrun.net/duQKp/edit 很快我們就實現了想要的功能。
  2. 自己通過 offsetParent 和 遞迴 parentNode 來實現。

    1. absolute + event (pageY)

      
           tooltip.style.position = 'absolute';
           tooltip.style.top = `${e.pageY}px`;
           tooltip.style.left = `${e.pageX}px`;
    2. fixed + event (clientY)

      
           tooltip.style.position = 'fixed';
           tooltip.style.top = `${e.clientY}px`;
           tooltip.style.left = `${e.clientX}px`;
    3. absolute + 遞迴 offset

       const getOffestValue = function getOffestValue(el, offsetLeft="offsetLeft"){
           if(!el) return 0;
           return el[offsetLeft] + (getOffestValue(el.offsetParent, offsetLeft) || 0)
       }
      
      
       tooltip.style.position = 'absolute';
       tooltip.style.top = `${getOffestValue(el, 'offsetTop') - 30}px`;
       tooltip.style.left = `${getOffestValue(el) - 20}px`;
      1. fixed + getBoundingClientRect
          const {x,y} = el.getBoundingClientRect()
          tooltip.style.position = 'fixed';
          tooltip.style.top = `${y - 30}px`;
          tooltip.style.left = `${x - 30}px`;

回撥邏輯

可以通過 bus 或者 $emit 丟擲。

相關文章