1

growing.io圈选及热力图功能还是比较好用的,这周调研了它的技术实现,发现其实并不复杂。

演示

演示网址 (https://www.readingblog.cn/tr...

sdk

之前自己实现了一个无埋点sdk (https://github.com/mfaying/we...
也介绍了无埋点的实现原理 (https://juejin.im/post/5dd158...
现在我们在这个sdk的基础上增加圈选及热力图功能。

通信

由于sdk页面在埋点系统中会嵌入在一个iframe里,所以我们必须使sdk具备跨域通信的能力。这里我们使用的是postMessage,sdk会监听埋点系统发送的消息,来决定是否开启圈选或热力图模式。

_addMessageListener = () => {
  eventUtil.on(win, 'message', (event) => {
    if(event.data){
      try {
        const data = JSON.parse(event.data);
        const { mode, status } = data;
        if (mode === MODE.CIRCLE_SELECT) {
          if (status === 'on') {
            this.mode = mode;
            this._autoHoverCollection();
            this._appendWLSStyle();
            this._removeHeatmapCanvas();
          } else if (status === 'off') {
            this.mode = '';
            this._autoHoverCollectionOff();
            this._removeWLSStyle();
          }
        } else if (mode === MODE.HEATMAP) {
          if (status === 'on') {
            this.mode = mode;
            this._autoHoverCollection();
            this._appendWLSStyle();
            this._fetchHeatmap().then((res) => {
              this._drawHeatmap(res.data.data);
            });
          } else if (status === 'off') {
            this.mode = '';
            this._autoHoverCollectionOff();
            this._removeWLSStyle();
            this._removeHeatmapCanvas();
          }
        }
      } catch (e) {
        console.log(e);
      }
    }
  })
}

圈选模式

当开启圈选模式时,sdk会自动采集"hover事件",在页面中插入一段css(元素被圈选时会加上圈选类名,这段css就是圈选类名的样式)

if (status === 'on') {
  this.mode = mode;
  this._autoHoverCollection();
  this._appendWLSStyle();
  this._removeHeatmapCanvas();
}

元素hover时会增加一个圈选类名,并阻止页面跳转等默认事件,同时将数据发送给埋点平台。
埋点平台接收到这个数据就可以自主做圈选分析了。

_autoHoverHandle = (e) => {
  try {
    const { event, targetElement } = getEvent(e);
    const assignData = {
      et: 'mouseenter',
      ed: 'auto_hover',
    }
    const logData = this._getLogData(e, assignData);
    if (this.mode === MODE.CIRCLE_SELECT || this.mode === MODE.HEATMAP) {
      this._selectElement(event, targetElement);
      this._postMessage(logData);
    }
  } catch (err) {
    console.log(err);
  }
}

_selectElement = (event, targetElement) => {
  const elems = doc.getElementsByClassName(WLS_CLICK_SELECT);
  for (let i = 0, len = elems.length; i < len; i ++) {
    elems[i].classList.remove(WLS_CLICK_SELECT);
  }
  eventUtil.stopDefault(event);
  targetElement.classList.add(WLS_CLICK_SELECT);
}

热力图

当开启热力图时会向用户自己配置的heatmapUrl请求当前页面的热力图数据,绘制热力图。

if (status === 'on') {
  this.mode = mode;
  this._autoHoverCollection();
  this._appendWLSStyle();
  this._fetchHeatmap().then((res) => {
    this._drawHeatmap(res.data.data);
  });
}

小番茄
67 声望5 粉丝