首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在am4core调用amCharts之前加载库?

如何在am4core调用amCharts之前加载库?
EN

Stack Overflow用户
提问于 2020-08-01 19:14:10
回答 2查看 449关注 0票数 0

我有一个需求,在这里我必须创建一个自定义小部件,使用Am图表。但我面临的问题是,在加载库之前,调用am4core函数。

HTML代码

代码语言:javascript
复制
<com-sap-sample-helloworld5></com-sap-sample-helloworld5>

Js码

代码语言:javascript
复制
(function () {
  const amchartscorejs = "https://www.amcharts.com/lib/4/core.js";
  const amchartschartsjs = "https://www.amcharts.com/lib/4/charts.js";
  const amchartsanimatedjs = "https://www.amcharts.com/lib/4/themes/animated.js";
  const vennchartjs = "https://cdn.amcharts.com/lib/4/plugins/venn.js";
  async function LoadLibs() {
    console.log("LoadLibs");
    try {
      await loadScript(amchartscorejs);
      await loadScript(amchartschartsjs);
      await loadScript(amchartsanimatedjs);
      await loadScript(vennchartjs);
    } catch (e) {
      alert(e);
    } finally {
      that._firstConnection = 1;
    }
  }
  LoadLibs();
  function loadScript(src) {
    console.log("LoadScript");
    return new Promise(function (resolve, reject) {
      let script = document.createElement("script");
      script.src = src;
      script.onload = () => {
        console.log("Load: " + src);
        resolve(script);
      };
      script.onerror = () => reject(new Error(`Script load error for ${src}`));
      document.head.appendChild(script);
    });
  }
  let template = document.createElement("template");
  template.innerHTML = `<div id="chartdiv" width="100%" height="500px"></div>`;
  customElements.define(
    "com-sap-sample-helloworld5",
    class HelloWorld extends HTMLElement {
      constructor() {
        super();
        let shadowRoot = this.attachShadow({
          mode: "open",
        });
        shadowRoot.appendChild(template.content.cloneNode(true));
        this._firstConnection = false;
        this.addEventListener("click", (event) => {
          var event = new Event("onClick");
          this.dispatchEvent(event);
        });
      }
      //Fired when the widget is added to the html DOM of the page
      connectedCallback() {
        this._firstConnection = true;
        this.redraw();
      }
      //Fired when the widget is removed from the html DOM of the page (e.g. by hide)
      disconnectedCallback() {}
      //When the custom widget is updated, the Custom Widget SDK framework executes this function first
      onCustomWidgetBeforeUpdate(oChangedProperties) {}
      //When the custom widget is updated, the Custom Widget SDK framework executes this function after the update
      onCustomWidgetAfterUpdate(oChangedProperties) {
        if (this._firstConnection) {
          this.redraw();
        }
      }
      //When the custom widget is removed from the canvas or the analytic application is closed
      onCustomWidgetDestroy() {}
      //When the custom widget is resized on the canvas, the Custom Widget SDK framework executes the following JavaScript function call on the custom widget
      // Commented out by default
      /*
    onCustomWidgetResize(width, height){
    
    }
    */
      get chartType() {
        return this.chartTypeValue;
      }
      set chartType(value) {
        this.chartTypeValue = value;
      }

      redraw() {
        console.log("redraw function");
        // Themes begin
        am4core.useTheme(am4themes_animated);
        // Themes end
        var data = [
          { name: "A", value: 10 },
          {
            name: "B",
            value: 10,
          },
          {
            name: "C",
            value: 10,
          },
          {
            name: "X",
            value: 2,
            sets: ["A", "B"],
          },
          {
            name: "Y",
            value: 2,
            sets: ["A", "C"],
          },
          {
            name: "Z",
            value: 2,
            sets: ["B", "C"],
          },
          {
            name: "Q",
            value: 1,
            sets: ["A", "B", "C"],
          },
        ];

        var chart = am4core.create("chartdiv", am4plugins_venn.VennDiagram);
        var series = chart.series.push(new am4plugins_venn.VennSeries());
        series.dataFields.category = "name";
        series.dataFields.value = "value";
        series.dataFields.intersections = "sets";
        series.data = data;
        chart.legend = new am4charts.Legend();
        chart.legend.marginTop = 40;
      }
    }
  );
})();

请告诉我应该做哪些更改,以便首先加载amCharts库,然后调用redraw()函数。

您还可以检查小提琴中的日志,以了解我面临的问题。

提前谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-08-02 08:45:45

我从Promise.all开始,但最后使用了一个阿姆海图问题,该阿姆海图问题需要按顺序加载。

等待ES7将完成这项工作

您已经走到了一半,但是停止了异步部分并继续使用同步loadLibs,在加载完成时,您似乎很难尝试标记元素。

在这里,库按顺序加载,其中包含一个泛型的loadScripts函数,

根据AmCharts为多个自定义元素做好准备,脚本将只加载一次:

代码语言:javascript
复制
(function() {
  function log() {
    let args = [...arguments];
    //console.log(`%c ${args.shift()} `, "background:lightgreen", ...args); //Chrome!
    document.body.append(args.join` `,document.createElement('BR'));
  }
  log("start IIFE script");
  async function loadScripts() {
    const load = (src) => new Promise((resolve, reject) => {
      const script = document.createElement('script');
      script.src = `https://www.amcharts.com/lib/4/${src}.js`;
      if (document.querySelector(`[src="${script.src}"]`)) resolve();
      log("load", script.src)
      script.onload = resolve;
      //script.onerror = () => reject(new Error(`Script load error for ${src}`));
      document.head.append(script)
    });
    await load("core"); // must be loaded first
    await load("charts");
    await load("themes/animated");
    await load("plugins/venn");
    return "return not even required";
  }
  customElements.define('my-element', class extends HTMLElement {
    connectedCallback() {
      this.attachShadow({mode: "open"}).innerHTML = `<div>Executing:</div>`;
      log('connectedCallback');
      loadScripts().then(result => {
        log('done loading', result);
      });
    }
  });

})();
代码语言:javascript
复制
<my-element></my-element>

您可以将所有移动到(现在标记为async ) connectedCallback中。

代码语言:javascript
复制
  async connectedCallback() {
    const load = (src) => new Promise((resolve, reject) => {
      let script = document.createElement('script');
      script.src = `https://www.amcharts.com/lib/4/${src}.js`;
      //if (document.querySelector(`[src="${script.src}"]`)) resolve();
      script.onload = resolve;
      this.append(script); // fine, doesn't really matter where SCRIPT is injected
    });
    await load("core");
    await load("charts");
    await load("themes/animated");
    await load("plugins/venn");
    // Loaded all
  }

如果由于移动DOM节点而使connectedCallback多次运行,则需要检查是否已加载脚本

票数 2
EN

Stack Overflow用户

发布于 2020-08-01 23:44:20

将启动am4core的代码的一部分移动到单独的文件中,并像其他文件一样加载它,但也要更改loadScript功能,以使用defer:

代码语言:javascript
复制
 function loadScript(src)
{
console.log("LoadScript");
  return new Promise(function(resolve, reject) 
{
    let script = document.createElement('script');
    script.src = src;
    script.defer = true;

    script.onload = () => {console.log("Load: " + src); resolve(script);}
    script.onerror = () => reject(new Error(`Script load error for ${src}`));

    document.head.appendChild(script)
  });
}

顺便说一句,我认为把标签放在一起总是更好,所以修改最后一行:

代码语言:javascript
复制
document.head.appendChild(script)

至:

代码语言:javascript
复制
var scriptTag = document.head.getElementsByTagName('script')[0];
scriptTag.parentNode.insertBefore(script, scriptTag.nextSibling);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63209130

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档