英文:
Removing white lines from Highcharts column chart
问题
我有一个Highcharts柱状图,我正在尝试构建它,但里面有一些随机的白线,我似乎无法删除。有人有任何想法?
JsFiddle链接:https://jsfiddle.net/LiamFlavelle/cks8otgp/148/
第一条白线出现在x值为1673308800000和1673395200000之间。每个x值都是一个日期,它们之间相隔86,400,000毫秒(即一天),我看不到这些日期周围有任何区别。
英文:
I have a Highcharts column chart that I am trying to build and it has some random white lines in it that I can't seem to remove. Anyone have any ideas?
JsFiddle: https://jsfiddle.net/LiamFlavelle/cks8otgp/148/
The first white lines appear at an between x values of 1673308800000 and 1673395200000. Each x value is a date and have 86,400,000 ms (i.e. a day) between them, and I can't see any differences around these dates.
// Code block - please ignore, you can't submit a JSFiddle without it
答案1
得分: 1
这似乎是浏览器中 SVG 渲染的问题。根据 SVG 的宽度、屏幕分辨率、选择的间隔以及可能的月相,线条的位置会有所不同,有时甚至不会显示。这个效果在这个SO线程或者这个线程中有讨论。
显然,最佳解决方案是设置 shape-rendering: crispEdges
(在 CSS 中或作为一个属性)。出于某种原因,这在这里不起作用。在原始的示例中,您设置了 CSS shape-rendering: crispEdges
;我还尝试将其设置为单独的 path
元素的属性,但没有效果。
另一个提出的解决方案是沿着它们的顺序方向延长矩形,这种情况下是 x 方向。在这个上下文中这是有意义的,我们可以添加一个安全的长度,因为下一个矩形会重叠在前一个上面。这就是我所做的,但这是一个非常巧妙的解决方案 - 在 render
事件处理程序中更改 svg
元素。这只是原始图表选项的补充部分:
let options = {
chart: {
events: {
render(ev){
const svg = ev.target.renderTo.getElementsByTagName('svg')[0];
//svg.setAttribute("shape-rendering", "crispEdges"); // 不起作用
const svgPaths = Array.from(svg.getElementsByTagName('path'));
svgPaths.forEach(
svgPath => {
//svgPath.setAttribute("shape-rendering", "crispEdges"); // 不起作用
let extended = false;
const d = svgPath.getAttribute("d"),
dMod = d.replaceAll(/A 0 0 [\s\d]+(?=\w)/g, '') // 移除零半径弧线
.replaceAll( // 在矩形长度上添加 +1
/M (\d+) (\d+) L (\d+) L (\d+) L L /g,
(...match) => {
extended = true;
const m1 = match[1],
m2 = match[2],
m3 = parseFloat(match[3]) + 1,
m4 = match[4];
return `M ${m1} ${m2} L ${m3} ${m2} L ${m3} ${m4} L ${m1} ${m4} L ${m1} ${m2}`;
}
);
if(extended){
svgPath.setAttribute("d", dMod);
}
}
);
}
}
}
}
这是带有这个补充的forked fiddle。
英文:
This appears to be a problem with svg rendering in browsers. I get the lines at different positions (or not at all) depending on the svg width, screen resolution, selected interval and possibly the moon phase. That effect is discussed for instance in this SO thread, or this one.
Apparently the best solution is to set shape-rendering: crispEdges
(in css or as an attribute). For some reason, this doesn't work here. In the original fiddle you set the css shape-rendering: crispEdges
; I tried also to set it as an attribute to individual path
elements. No effect.
The other proposed solution is to lengthen the rectangles in the direction of their sequence, the x direction in this case. This makes sense in this context, we can add a safe length, since the next rectangle will overlap the previous one. That is what I did, but this is a very hacky solution - changing the svg
elements in a render
event handler. Here is just the supplemental part to the original chart options:
let options = {
chart: {
events: {
render(ev){
const svg = ev.target.renderTo.getElementsByTagName('svg')[0];
//svg.setAttribute("shape-rendering", "crispEdges"); // not working
const svgPaths = Array.from(svg.getElementsByTagName('path'));
svgPaths.forEach(
svgPath => {
//svgPath.setAttribute("shape-rendering", "crispEdges"); // not working
let extended = false;
const d = svgPath.getAttribute("d"),
dMod = d.replaceAll(/A 0 0 [\s\d]+(?=\w)/g, '') // remove zero radii arcs
.replaceAll( // add +1 to rectangles length
/M (\d+) (\d+) L (\d+) L (\d+) L L /g,
(...match) => {
extended = true;
const m1 = match[1],
m2 = match[2],
m3 = parseFloat(match[3]) + 1,
m4 = match[4];
return `M ${m1} ${m2} L ${m3} ${m2} L ${m3} ${m4} L ${m1} ${m4} L ${m1} ${m2}`;
}
);
if(extended){
svgPath.setAttribute("d", dMod);
}
}
);
}
}
}
}
and this is the forked fiddle with that addition.
答案2
得分: 1
Highcharts内置选项可控制此行为。在Highcharts API中,我们可以阅读:
crisp: boolean
当为true时,将每个点或柱边缘舍入到最近的像素,以便在屏幕上呈现清晰。在某些情况下,当有大量密集堆叠的柱时,这会导致柱宽或柱间距可见差异。在这些情况下,将crisp设置为false可能看起来更好,即使每个柱都呈现为模糊状态。默认为true。
作为解决方案,您可以禁用crisp
:
plotOptions: {
...,
column: {
crisp: false,
...
}
}
在线演示: https://jsfiddle.net/BlackLabel/p21Lho37/
API 参考: https://api.highcharts.com/highcharts/series.column.crisp
英文:
Highcharts has a built-in option to control this behaviour. In Highcharts API we can read:
> crisp: boolean
>
> When true, each point or column edge is rounded to its nearest pixel
> in order to render sharp on screen. In some cases, when there are a
> lot of densely packed columns, this leads to visible difference in
> column widths or distance between columns. In these cases, setting
> crisp to false may look better, even though each column is rendered
> blurry. Defaults to true.
As a solution, you can disable crisp
:
plotOptions: {
...,
column: {
crisp: false,
...
}
}
Live demo: https://jsfiddle.net/BlackLabel/p21Lho37/
API Reference: https://api.highcharts.com/highcharts/series.column.crisp
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论