javascript - 如何在 amCharts 中调用 am4core 之前加载库?
问题描述
我有一个要求,我必须使用 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中的日志以了解我面临的问题。
提前致谢。
解决方案
我从Promise.all开始,但最终遇到了Amcharts需要按顺序加载的问题。
ES7 等待将完成这项工作
您已经完成了一半,但停止了 async 部分并继续使用 sync 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>
您可以移动(现在标记的)connectedCallback中的所有内容async
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/
推荐阅读
- python - 由于反复更改 sha256,pip install 失败(错误:这些包与需求文件中的哈希不匹配)
- charts - Chart的PUG渲染
- php - 将文件从本地网站上传到 Blob 存储
- python - PIL 将文本添加到 gif 帧会为图片添加噪点
- java - 如何检查时间 SIMpleDateFormat?
- css - 在图像上制作完美的圆形
- javascript - 如何在 React 中为每个用户输入文本?
- c# - ActiveMQ 连接的消费者不消费消息
- reactjs - 页面刷新时丢失上下文
- python - 引发 AttributeError:响应内容不是文本 Scarpy 代理池。怎么解决?