布局结构

  • window获取元素的布局信息 可获得视窗数据

image.png

  • wapper内外两层div包裹实际内容 第一层div=placeholder 占位有宽高的数据 无实际内容 另一层随窗口滚动计算位置fixed
  • onResize重计算位置
  • 开始渲染时 并未触发固钉效果,将正常渲染目标组件,后续计算可以拿到正常渲染时的宽高数据
  • 留下来占位的一般需要不影响整体样式 比方说开始固钉效果后 原有展示没有很大缺陷

代码实现

  1. // 第一层size监听 用于处理容器size变化
  2. <ResizeObserver
  3. onResize={() => {
  4. this.updatePosition();
  5. }}
  6. >
  7. <div {...props} ref={this.savePlaceholderNode}>
  8. {affixStyle && <div style={placeholderStyle} aria-hidden="true" />}
  9. <div className={className} ref={this.saveFixedNode} style={affixStyle}>
  10. // 第二层size监听 用于处理内容size变化 有可能top或者bottom变化
  11. <ResizeObserver
  12. onResize={() => {
  13. this.updatePosition();
  14. }}
  15. >
  16. {children}
  17. </ResizeObserver>
  18. </div>
  19. </div>
  20. // 计算逻辑
  21. // 固钉的样式数据 宽高等
  22. const targetRect = getTargetRect(targetNode);
  23. // 占位的样式数据 宽高等
  24. const placeholderReact = getTargetRect(this.placeholderNode);
  25. const fixedTop = getFixedTop(placeholderReact, targetRect, offsetTop);
  26. const fixedBottom = getFixedBottom(placeholderReact, targetRect, offsetBottom);
  27. if (fixedTop !== undefined) {
  28. newState.affixStyle = {
  29. position: 'fixed',
  30. top: fixedTop,
  31. width: placeholderReact.width, // 固钉的宽高以原本正常渲染的内容宽高为基准
  32. height: placeholderReact.height,
  33. };
  34. newState.placeholderStyle = {
  35. width: placeholderReact.width, // 当固钉开始fixed的时候 placeholder需要拿到正常渲染时的宽高占位
  36. height: placeholderReact.height,
  37. };
  38. // 下方固定
  39. } else if (fixedBottom !== undefined) {
  40. newState.affixStyle = {
  41. position: 'fixed',
  42. bottom: fixedBottom,
  43. width: placeholderReact.width,
  44. height: placeholderReact.height,
  45. };
  46. newState.placeholderStyle = {
  47. width: placeholderReact.width,
  48. height: placeholderReact.height,
  49. };