最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • G2Plot 不能重交互?结合 CreatePortal 为所欲为吧

    正文概述 掘金(蚂蚁金服数据体验技术)   2021-01-27   401

    Preface

    React 和 G2Plot 都不了解的同学请先移步官网,如果你熟悉其一,可以往下看了,这篇文章主要介绍怎么将两者结合起来,在 G2Plot 提供的图表上进行富操作。

    Annotations

    G2Plot 提供 Annotation 作为图表的辅助元素,主要用于在图表上标识额外的标记注解,目前包括 line、text、image、html等10种类型。类型虽多,但每种类型的配置项都有一定的限制,在复杂业务场景显得很鸡肋,毕竟是 canvas 不是 html。

    其它几个类型比较简单也没有太多操作空间,以 type: 'html' 为例,一个简单的辅助标记如下:

    annotations: [
      {
        type: "html",
        position: ["1995", 4.9],
        html: '<p>辅助标记</p>'
      }
    ],
    

    G2Plot 不能重交互?结合 CreatePortal 为所欲为吧

    从示例可以看出,html 类型是支持 html 字符串的,在 React Vue 横行的时代,我相信没有人愿意去拼接 html 字符串了,除非迫不得已。

    ReactDOM

    Render

    既然 type: 'html' 模式支持 html 字符串,不知你是否想到 ReactDOM,配合 ReactDOM 几乎可以完美实现了,简单改造之后效果如下。

    annotations: [
      {
        type: "html",
        position: ["1995", 4.9],
        html: () => {
          const ele = document.createElement("div");
          ReactDom.render(<Annotation />, ele);
          return ele;
        }
      }
    ],
    

    G2Plot 不能重交互?结合 CreatePortal 为所欲为吧

    看上去已经很完美,但业务实际要复杂的多,很简单的一种情况,如果图表容器有 overflow: 'hidden' 的配置,会看到如下效果。

    G2Plot 不能重交互?结合 CreatePortal 为所欲为吧

    Annotation 被截断了,增加容器高度或是 Annotation 组件添加滚动条,往往都不是最佳解法。

    CreatePortal

    为了解决上述问题,让 Annotation 不受限于父容器,我们可以借助 CreatePortal 将 Annotation 渲染到任意我们期望的 DOM 树上,以 body 为例。

      const getAnnotationHtml = () => {
        const ele = document.createElement("div");
        ele.id = "annotation-box";
        ReactDOM.render(
          <>
            {ReactDOM.createPortal(
              <Annotation />,
              document.getElementsByTagName("body")[0]
            )}
          </>,
          ele
        );
        return ele;
      };
    

    G2Plot 不能重交互?结合 CreatePortal 为所欲为吧G2Plot 不能重交互?结合 CreatePortal 为所欲为吧

    Annotation 正确渲染在 body 里面了,但并不是我们期望的效果,因为 Annotaion 没有渲染在 HTMLElement id['annotation-box'] 里面, 所以位置偏离了。

    其实正常情况下,如果 Annotation 的内容过多,也不宜直接展示,因为太太太遮挡内容了,我们简单的添加个交互(onmousemove)。

    // 全量代码请查看示例代码
    annotations: [
      {
        type: "html",
        position: ["1995", 4.9],
        html: getAnnotationHtml()
      }
    ]
    
    const getPosition = (targetElement) => {
      const { top, left, right } = targetElement.getBoundingClientRect();
      // 需要考虑有滚动条时的情况
      const boxTop =
            top -
            document.documentElement.clientTop +
            document.documentElement.scrollTop;
      const boxLeft =
            left -
            document.documentElement.clientLeft +
            document.documentElement.scrollLeft;
      const body = document.getElementsByTagName("body")[0];
      const { width } = body.getBoundingClientRect();
      const boxWdith = 230; // 容器宽度
      const offsetX = width - right < boxWdith ? boxWdith - (width - right) : 0; // 考虑超出右侧的情况
      return {
        left: boxLeft - offsetX,
        top: boxTop
      };
    };
    
    const showAnnotationComponent = (e) => {
      const exist = document.querySelector("#annotaion-component");
      if (!exist) {
        const targetElement = e.currentTarget.parentNode.getElementsByClassName(
          "annotation-box"
        )[0];
        const { top, left } = getPosition(targetElement);
        ReactDOM.render(
          <>
           {ReactDOM.createPortal(
              <div
               id="annotaion-component"
               style={{ position: "absolute", left, top }}
              >
                <Annotation />
              </div>,
              document.getElementsByTagName("body")[0]
            )}
            </>,
            targetElement
        );
      } else {
        // todo set display
      }
    };
    
    const getAnnotationHtml = () => {
      const ele = document.createElement("div");
      ele.innerHTML = '<span>查看详情</span><div class="annotation-box"></div>';
      ele.onmousemove = (e) => {
        showAnnotationComponent(e);
      };
      return ele;
    };
    

    当鼠标移动到查看详情上时,即使父容器设置了 overFlow: 'hidden' 也不影响,效果如下:

    G2Plot 不能重交互?结合 CreatePortal 为所欲为吧

    onmouseleave 等事件,根据业务需求处理就行了。

    What's more?

    其实类似问题不少,有时候可以绕过,有时则不能,当遇到时可以考虑下 CreatePortal,例如典型的 tooltip ,我们可结合 customContent 迎刃而解。

    G2Plot 不能重交互?结合 CreatePortal 为所欲为吧

    示例代码地址: codesandbox.io/s/annotatio…


    起源地下载网 » G2Plot 不能重交互?结合 CreatePortal 为所欲为吧

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元