D3.js 在画布图表上的每个蜡烛顶部放置几个符号

D3.js 在画布图表上的每个蜡烛顶部放置几个符号,d3.js,d3fc,D3.js,D3fc,创建了一个我需要的简化示例。该系列共有50项。每个项目都有五个+符号的垂直列表 const data=[…数组(50).keys(); const container=document.querySelector('d3fc-canvas'); const xScale=d3.scaleLinear().domain([0,data.length-1]); const yScale=d3.scaleLinear().domain(fc.extentLinear()(data)); 常数系列=f

创建了一个我需要的简化示例。该系列共有50项。每个项目都有五个
+
符号的垂直列表

const data=[…数组(50).keys();
const container=document.querySelector('d3fc-canvas');
const xScale=d3.scaleLinear().domain([0,data.length-1]);
const yScale=d3.scaleLinear().domain(fc.extentLinear()(data));
常数系列=fc
.seriesCanvasPoint()
.xScale(xScale)
.yScale(yScale)
.crossValue((_,i)=>i)
.main值(d=>d)
.size((u,i)=>0)
.装饰((上下文、基准)=>{
//在当前值上方绘制5个符号
for(设i=0;i<5;i++){
常数y=yScale.invert(基准+i)
context.textAlign='center';
context.fillStyle='#000';
context.font='25px Arial';
context.fillText('+',0,0);
上下文翻译(0,y);
}
});
d3.选择(容器)
.on('draw',()=>{
系列(数据);
})
.on('measure',()=>{
常数{
宽度,
高度
}=事件细节;
X刻度范围([0,宽度]);
Y刻度范围([高度,0]);
const ctx=container.querySelector('canvas').getContext('2d');
系列.背景(ctx);
});
container.requestRedraw()
正文{
颜色:#1b1e23;
字体大小:小;
字体系列:无衬线;
高度:计算(100vh-2米);
边缘:1米;
显示器:flex;
}
正文>*{
flex:自动;
}
.域名,
.gridline-y,
.gridline-x,
.注释行>注释行{
笔画:当前颜色;
笔划不透明度:0.1;
}

首先,
缩放。反转
用于像素坐标,而不是相应的基准值。例如,当您在屏幕上单击时,这是相关的。在这种情况下,它不是工作的正确工具。您已经可以访问
datum
,因此只需调用
scaleY(datum.close)

但是,
d3fc
使用
canvas.translate()
将零点更改为
.mainvalue()
。因此,您不能简单地使用
scaleY(datum.close)
来获取闭合值的y坐标。而不是
(x,y)
,您要绘制的每个点变成
(0,y(箭头)-y(d.close))
。所以你需要改变逻辑来反映这一点

需要使用
context.translate()
清理您自己之后的错误,避免这样的事情几乎总是更好的


最后,我对您的
getMarks
函数有些困惑。如果你想画5个箭头均匀分布在你的酒吧,你需要有一个1/4的酒吧高度的差距。把它想象成街道上的树。如果树木相距10英尺,街道长100英尺,你会有11棵树,而不是10棵。正因为如此,我画了6个加号,而不是5个,因为否则它看起来有点失衡

const stream=fc.randomFinancial().stream();
常数数据=流。取(20);
常量scaleX=d3.scalePoint();
常量scaleY=d3.scaleLinear();
const yExtent=fc.extentLinear().accessors([d=>d.high,d=>d.low]);
const xExtent=fc.extentLinear().accessors([d=>d.date.getTime()]);
const gridlines=fc.annotationCanvasGridline();
const candlestick=fc.seriescanvas candlestick()
.crossValue((o,i)=>o.date.getTime())
.低值((o,i)=>o.low)
.高值((o,i)=>o.高)
.openValue((o,i)=>o.open)
.closeValue((o,i)=>o.close);
常数点=fc
.seriesCanvasPoint()
.crossValue((o,i)=>o.date.getTime())
.main值(d=>d.close)
.size((u,i)=>0)
.装饰((上下文、基准)=>{
常数箭头=获取标记(基准面打开、基准面关闭);
const top=scaleY(基准面关闭);
//我们需要一点偏移,因为“+”有20个像素高
我们希望它在中点,而不是在它上面。
常数偏移=10;
//在当前值上方绘制5个符号
for(设i=0;io.date.getTime());
scaleY.domain(yExtent(data));
图表
.xDomain(scaleX.domain())
.yDomain(scaleY.domain());
d3.选择(“#图表”)
.基准(数据)
.电话(图表);
}
renderChart();
设置间隔(renderChart,1000)
#图表{
高度:500px;
}


谢谢。很棒的解释和例子。符号在蜡烛中的分布不均匀。底部可能有两个符号,顶部可能有一个。在你指出D3FC在引擎盖下使用了
translate
之后,我意识到为什么我既不能使用绝对坐标也不能使用相对坐标。现在一切都有了意义。函数
getMarks
用于生成明确的基准值,而不是简单的偏移量,以明确符号值来自图表外部,不由蜡烛本身定义。我应该创建一个更好的例子,
getMarks
在蜡烛顶部和底部之间的范围内生成随机值!只是我不确定我是否在某个地方有遗留的bug/错误,直到我看到了
getMarks
的东西。很乐意帮忙