- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用dygraphs来制作一种多 channel /多轨波形查看器,以浏览例如数字逻辑信号。此处的示例呈现如下内容:
显然,我需要同步两个轨道(即当我放大一个轨道时,另一个轨道也应该相应地放大) - 否则,这个没有多大用处。
我已经准备了这里讨论的代码的要点:https://gist.github.com/sdaau/2d21ff7d88f03118bd5b31fac66d2588 ;并且应该可以通过 bl.ocks.org 渲染示例(另请参阅 here ),或者如果您在浏览器中本地运行 .html 文件(我已经使用 Firefox 74 进行了测试)
问题是:
Is there an Dygraph has loaded event? 中解释了其原因。 :
If you pass CSV data or an array to the Dygraphs constructor, it will be called synchronously. If you pass a URL, it will be called asynchronously.
但是,问题是,我需要使用 .csv URL,但从逻辑上讲,我总是考虑同步调用;例如:
load_g1();
load_g2();
sync_g1g2();
... 如图所示,这会中断轴同步;以及实际上与同步一起使用的异步调用类型:
function load_g1() {
...
g1.ready(function() {
function load_g2() {
...
g2.ready(function() {
sync_g1g2();
});
}
load_g2();
});
}
...也就是“回调 hell ”,确实让我很难管理代码。
所以,我见过这样的问题:
...显然做到这一点的方法是使用 Promises - 不幸的是,我不太精通 JavaScript,而且我不能说这是否或如何应用于此 dygraphs 代码。
所以,总结一下:有没有办法用 dygraph 重写对 .csv 代码异步加载的调用,以便最终我可以按顺序编写类似这些命令的内容(在示例中的 Initialize() 中)? :
load_g1();
load_g2();
sync_g1g2();
作为引用,我将粘贴下面的 test_03_dygraphs_async_csv.html
代码:
<!DOCTYPE html>
<link rel="stylesheet" href="http://dygraphs.com/2.1.0/dygraph.css">
<title>Test 03: dygraphs asynchronous (URL .csv -> synchronize() OK)</title>
<style>
#graphdiv1, #graphdiv2 {
display: inline-block;
vertical-align: top;
}
#legend1, #legend2 {
display: inline-block;
vertical-align: top;
}
</style>
<h2>Test 03: dygraphs asynchronous (URL .csv -> synchronize() OK)</h2>
<hr/>
<div id="legend1" style="height:40px;">.</div>
<div id="graphdiv1"
style="width:98%; height:200px;"></div>
<div id="legend2" style="height:40px;">.</div>
<div id="graphdiv2"
style="width:98%; height:200px;"></div>
<script type="text/javascript" src="http://dygraphs.com/2.1.0/dygraph.js"></script>
<script type="text/javascript" src="http://dygraphs.com/2.1.0/extras/synchronizer.js"></script>
<script type="text/javascript">
// http://dygraphs.com/tests/plotters.html
// Darken a color
function darkenColor(colorStr) {
// Defined in dygraph-utils.js
var color = Dygraph.toRGB_(colorStr);
color.r = Math.floor((255 + color.r) / 2);
color.g = Math.floor((255 + color.g) / 2);
color.b = Math.floor((255 + color.b) / 2);
return 'rgb(' + color.r + ',' + color.g + ',' + color.b + ')';
}
// This function draws bars for a single series.
function barChartPlotter(e) {
var ctx = e.drawingContext;
var points = e.points;
var y_bottom = e.dygraph.toDomYCoord(0);
ctx.fillStyle = darkenColor(e.color);
//// Find the minimum separation between x-values. .. fixed
var bar_width = Math.floor(2.0);
// Do the actual plotting.
for (var i = 0; i < points.length; i++) {
var p = points[i];
var center_x = p.canvasx;
ctx.fillRect(center_x - bar_width / 2, p.canvasy,
bar_width, y_bottom - p.canvasy);
ctx.strokeRect(center_x - bar_width / 2, p.canvasy,
bar_width, y_bottom - p.canvasy);
}
}
function legendFormatter(data) {
if (data.x == null) {
// This happens when there's no selection and {legend: 'always'} is set.
return '<br>' + data.series.map(function(series) { return series.dashHTML + ' ' + series.labelHTML }).join('<br>');
}
var html = this.getLabels()[0] + ': ' + data.xHTML;
data.series.forEach(function(series) {
if (!series.isVisible) return;
var labeledData = series.labelHTML + ': ' + series.yHTML;
if (series.isHighlighted) {
labeledData = '<b>' + labeledData + '</b>';
}
html += '<br>' + series.dashHTML + ' ' + labeledData;
});
return html;
}
var g1, g2;
function load_g1() {
g1 = new Dygraph(
document.getElementById("graphdiv1"),
//"x,val1\n" +
//"0,0\n" +
//"18790378,1\n" +
//"19111992,0\n" +
//"20107172,1\n" +
//"21101338,0\n" +
//"183224018,0\n",
"https://gist.githubusercontent.com/sdaau/2d21ff7d88f03118bd5b31fac66d2588/raw/val1_data.csv",
{ // options
animatedZooms: true,
stepPlot: true,
axes: {
x: {
drawGrid: false
},
},
includeZero: true,
legend: 'always',
labelsKMB: true,
labelsDiv: document.getElementById('legend1'),
legendFormatter: legendFormatter,
}
);
// NOTE: SO:26316435 "If you pass CSV data or an array to the Dygraphs constructor, it will be called synchronously. If you pass a URL, it will be called asynchronously."
g1.ready(function() {
load_g2();
});
}
function load_g2() {
g2 = new Dygraph(
document.getElementById("graphdiv2"),
//"x,val2\n" +
//"0,0\n" +
//"18790378,0\n" +
//"19111992,10\n" +
//"20107172,40\n" +
//"21101338,30\n" +
//"22095808,20\n" +
//"23091420,50\n" +
//"24085288,10\n" +
//"25080336,50\n" +
//"26075516,40\n" +
//"27069272,20\n",
"https://gist.githubusercontent.com/sdaau/2d21ff7d88f03118bd5b31fac66d2588/raw/val2_data.csv",
{ // options
//title: 'val2', // no need for title (y axis label) here, if using fixed ("always") legend as separate div - shown there.
animatedZooms: true,
plotter: barChartPlotter,
axes: {
x: {
drawGrid: false
},
},
includeZero: true,
legend: 'always', // needs to be always, if we want the legend fixed, that is, not reparented to canvas, as it is for follow, which might fail with bad values
labelsKMB: true, // seemingly only for y values, not x?
labelsDiv: document.getElementById('legend2'),
legendFormatter: legendFormatter,
}
);
// NOTE: SO:26316435 "If you pass CSV data or an array to the Dygraphs constructor, it will be called synchronously. If you pass a URL, it will be called asynchronously."
g2.ready(function() {
sync_g1g2();
});
}
function sync_g1g2() {
g1.updateOptions({
dateWindow: g2.xAxisExtremes() // ok, works
});
var sync = Dygraph.synchronize(g1, g2, { // options
zoom: true,
selection: true,
range: false, // if you wish to only sync the x-axis.
});
// charts are now synchronized
}
function Initialize(evt) {
load_g1();
}
Initialize();
</script>
最佳答案
您基本上需要返回一个新的 Promise,然后在完成后调用解析来代替下一个操作,例如,您的 load_g1
函数将如下所示(我删除了一些为了示例而注释)
function load_g1() {
return new Promise(function(resolve, reject) {
g1 = new Dygraph(
document.getElementById('graphdiv1'),
'https://gist.githubusercontent.com/sdaau/2d21ff7d88f03118bd5b31fac66d2588/raw/val1_data.csv',
{
// options
animatedZooms: true,
stepPlot: true,
axes: {
x: {
drawGrid: false,
},
},
includeZero: true,
legend: 'always',
labelsKMB: true,
labelsDiv: document.getElementById('legend1'),
legendFormatter,
},
);
// NOTE: SO:26316435 "If you pass CSV data or an array to the Dygraphs constructor, it will be called synchronously. If you pass a URL, it will be called asynchronously."
g1.ready(function() {
resolve();
});
});
}
您的 load_g2
函数如下所示
function load_g2() {
return new Promise(function(resolve, reject) {
g2 = new Dygraph(
document.getElementById('graphdiv2'),
'https://gist.githubusercontent.com/sdaau/2d21ff7d88f03118bd5b31fac66d2588/raw/val2_data.csv',
{
// options
// title: 'val2', // no need for title (y axis label) here, if using fixed ("always") legend as separate div - shown there.
animatedZooms: true,
plotter: barChartPlotter,
axes: {
x: {
drawGrid: false,
},
},
includeZero: true,
legend: 'always', // needs to be always, if we want the legend fixed, that is, not reparented to canvas, as it is for follow, which might fail with bad values
labelsKMB: true, // seemingly only for y values, not x?
labelsDiv: document.getElementById('legend2'),
legendFormatter,
},
);
// NOTE: SO:26316435 "If you pass CSV data or an array to the Dygraphs constructor, it will be called synchronously. If you pass a URL, it will be called asynchronously."
g2.ready(function() {
resolve();
});
});
}
你的sync_g1g2
看起来像这样
function sync_g1g2() {
return new Promise(function(resolve, reject) {
g1.updateOptions({
dateWindow: g2.xAxisExtremes(), // ok, works
});
const sync = Dygraph.synchronize(g1, g2, {
// options
zoom: true,
selection: true,
range: false, // if you wish to only sync the x-axis.
});
// charts are now synchronized
resolve();
});
}
看看我如何调用 resolve
而不是下一个操作,这意味着我们可以将您的 Initialize
函数更改为以下
async function Initialize(evt) {
await load_g1();
await load_g2();
await sync_g1g2();
}
通过将Initialize
函数定义为async
,我们可以使用await
表达式。 await
将等待 promise 解决,然后再继续下一行。
还值得注意的是,我们在此示例中没有使用 reject
函数,但这值得在未来的用例中研究。
一旦你掌握了Promise
的窍门,你就永远不会回头!如果这没有意义,请大声喊我。
关于javascript - 以类似同步的方式重写异步dygraphs JS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60831822/
我习惯于使用 Apache 服务器,所以当启用 mod_rewrite 时,我可以创建一个 htaccess 文件并使用 URL 重写。 这是我的 htaccess 文件: RewriteEngine
我正在尝试编写一个 mixin 来修改输出的父选择器。这个想法是,在调用 mixin 的情况下,父选择器需要对其进行字符串替换。我有大部分工作,但我不知道如何吞下 & . .test { @inc
我有一个本地目录(上传)和一个 S3 桶设置。 当用户上传图片时,文件存储在本地目录:/uploads/member_id/image_name30 分钟后,系统将文件上传到 S3 使用相同的路径:s
我正在尝试使用以下内容重写代理页面的正文链接: sub_filter http://proxied.page.come http://local.page.com; sub_filte
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 1年前关闭。 Improve this questi
我尝试在我的 JSF 应用程序中使用“重写”(http://ocpsoft.org/rewrite/)。 一切都很好,我已经创建了规则: .addRule(Join.path("/profile/{p
我可以在 AEM 中大致看到两种 URL 重写方法: /etc/map/http(s)下的Sling映射(sling:Mapping) 使用链接重写器/TransformerFactory 重写 UR
我有一个 onclick 函数,我想将 anchor 添加到 href 值。我不想更改 URL,因为我需要该网站仍然可以为没有 javascript 的人/出于 SEO 目的而运行。所以这是我尝试使用
我必须在 UILabel 中显示货币和价格。在一个标签中,但使用不同的字体大小。现在看起来像这样: ...我这样做是重写drawTextInRect:,如下所示: - (void)drawTextIn
我正在尝试使用以下内容进行重定向: RewriteRule ^reviews/area/Santa-Barbara%2F$"/reviews/area/santa-barbara" [R=301,NC
我使用 FOSUserBundle 并且我想覆盖他的 registerAction Controller 。我阅读了与覆盖 FOSUserBundle Controller 相关的文档,但它不起作用。
我正在尝试让 URL 重写在我的网站上运行。这是我的 .htaccess 的内容: RewriteEngine On RewriteRule ^blog/?$ index.php?page=blog
好吧,这让我发疯了......我正在尝试像这样重写我的网址: Now: http://www.somedomain.com/Somepage.aspx http://www.somedomain.co
final方法不能在子类中重写。但凭借 Scala 的魔力,这似乎是可能的。 考虑以下示例: trait Test { final def doIt(s: String): String = s
我有一个类似下面的查询: Select ser.key From dbo.Enrlmt ser Where ser.wd >= @FromDate AND ser.wd ser.wd
我是 nginx 的新手,只是想做一些我认为应该很简单的事情。如果我这样做:- curl http://localhost:8008/12345678 我希望返回 index.html 页面。但是我得
我们的一位客户创建了一个二维码,其中 url 中包含一个空格。 我将如何编写处理此问题的 nginx 重定向? 在字符串中使用诸如“%20”之类的东西的几次尝试似乎会导致 nginx 出错或使 con
我正在尝试覆盖 appendChild 方法,以便我可以控制动态创建的元素并在插入页面之前根据需要修改它们。我尝试了这个示例代码,只是为了看看它是否可以完成: var f = Element.prot
我目前正在使用以下功能,当用户单击某处以确定是否隐藏下拉菜单(在 react 中)。一切正常,但当我单击正文时,它会记录以下内容。 我尝试重写它几次,但我找不到解决这个问题的方法。 Uncaught
我正在开发一个 Spring Integration/Boot 应用程序。我使用多文档 application.yml (src/main/resources/application.yml) 来设置
我是一名优秀的程序员,十分优秀!