我有一个需求,在这里我必须创建一个自定义小部件,使用Am图表。但我面临的问题是,在加载库之前,调用am4core函数。
HTML代码
<com-sap-sample-helloworld5></com-sap-sample-helloworld5>Js码
(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()函数。
您还可以检查小提琴中的日志,以了解我面临的问题。
提前谢谢。
发布于 2020-08-02 08:45:45
我从Promise.all开始,但最后使用了一个阿姆海图问题,该阿姆海图问题需要按顺序加载。
等待ES7将完成这项工作
您已经走到了一半,但是停止了异步部分并继续使用同步loadLibs,在加载完成时,您似乎很难尝试标记元素。
在这里,库按顺序加载,其中包含一个泛型的loadScripts函数,
根据AmCharts为多个自定义元素做好准备,脚本将只加载一次:
(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);
});
}
});
})();<my-element></my-element>
您可以将所有移动到(现在标记为async ) connectedCallback中。
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多次运行,则需要检查是否已加载脚本
发布于 2020-08-01 23:44:20
将启动am4core的代码的一部分移动到单独的文件中,并像其他文件一样加载它,但也要更改loadScript功能,以使用defer:
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)
});
}顺便说一句,我认为把标签放在一起总是更好,所以修改最后一行:
document.head.appendChild(script)至:
var scriptTag = document.head.getElementsByTagName('script')[0];
scriptTag.parentNode.insertBefore(script, scriptTag.nextSibling);https://stackoverflow.com/questions/63209130
复制相似问题