如何在 amCharts 中调用 am4core 之前加载库?
How to load libraries before am4core is called in amCharts?
我有一个要求,我必须使用 Amcharts 创建一个自定义小部件。但是我面临的问题是在加载库之前调用了 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() 函数。
您也可以查看 jsfiddle 中的日志以了解我遇到的问题。
提前致谢。
将您触发 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);
我从, but ended up on an Amcharts Issue开始说Amcharts需要按顺序加载
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
}
如果 connectedCallback 运行多次,因为你移动了 DOM 个节点,你需要检查已经加载的脚本
JSFiddle 中的上述代码:https://jsfiddle.net/CustomElementsExamples/wz79gbum/
我有一个要求,我必须使用 Amcharts 创建一个自定义小部件。但是我面临的问题是在加载库之前调用了 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() 函数。
您也可以查看 jsfiddle 中的日志以了解我遇到的问题。
提前致谢。
将您触发 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);
我从
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
}
如果 connectedCallback 运行多次,因为你移动了 DOM 个节点,你需要检查已经加载的脚本
JSFiddle 中的上述代码:https://jsfiddle.net/CustomElementsExamples/wz79gbum/