VisActor / VChart

VChart, more than just a cross-platform charting library, but also an expressive data storyteller.
https://www.visactor.io/vchart
MIT License
992 stars 72 forks source link

[Bug] zero tick not update when resize chart #2538

Open skie1997 opened 7 months ago

skie1997 commented 7 months ago

Version

1.10.2

Link to Minimal Reproduction

vscreen

Steps to Reproduce

const computeTickCount = (args) => {
  const { axisLength, rangeSize, labelStyle } = args ?? {}
  // const { width, height } = context._chart.getViewRect()
  // const viewSize = draft.orient === 'top' || draft.orient === 'bottom' ? width : height
  const labelSize = labelStyle?.fontSize ?? 12

  // 图表库多次计算tickCount时, 抛出的axisLength / rangeSize有差异, 导致tick计算结果有问题
  // 暂时计算一个大概的差值消弭差异, 待图表库修复
  let deltaSpace = 0
  // if(draft.orient === 'top' || draft.orient === 'bottom') {
    const measureLabelSize = 10
    deltaSpace = measureLabelSize * 4
  // } else {
  //   const legendHeight = 15
  //   const dimensionLabelSize = 20
  //   deltaSpace = dimensionLabelSize * 1.5 + legendHeight * 1.5 + 30
  // }

  const size = axisLength || (rangeSize - deltaSpace)
  const density = 0.4
  const tickCount = Math.ceil(
    (size / (labelSize * 1.5)) * density,
  )
  return tickCount < 2 ? 2 : tickCount
}
const spec = {
    "type": "bar",
    "xField": [
        "HqlYadRdHJ5c",
        "30001"
    ],
    "yField": [
        "10002"
    ],
    "direction": "vertical",
    "sortDataByAxis": true,
    "seriesField": "30001",
    "padding": {
        "left": 6,
        "right": 6,
        "top": 6,
        "bottom": 6
    },
    "labelLayout": "region",
    "data": [
        {
            "id": "data",
            "values": [
                {
                    "10001": "Profit",
                    "10002": 2000,
                    "10003": "rAkCnq1kbI7W",
                    "30001": "2023",
                    "HqlYadRdHJ5c": "Labels测试维度名称是一个长字符串",
                    "rAkCnq1kbI7W": 2000,
                    "7ti8XuX4kcY1": "2023"
                },
                {
                    "10001": "Profit",
                    "10002": 4500,
                    "10003": "rAkCnq1kbI7W",
                    "30001": "2022",
                    "HqlYadRdHJ5c": "Labels测试维度名称是一个长字符串",
                    "rAkCnq1kbI7W": 4500,
                    "7ti8XuX4kcY1": "2022"
                },
                {
                    "10001": "Profit",
                    "10002": 3000,
                    "10003": "rAkCnq1kbI7W",
                    "30001": "2023",
                    "HqlYadRdHJ5c": "FurnFurn测试增加一些长度",
                    "rAkCnq1kbI7W": 3000,
                    "7ti8XuX4kcY1": "2023"
                },
                {
                    "10001": "Profit",
                    "10002": 6700,
                    "10003": "rAkCnq1kbI7W",
                    "30001": "2022",
                    "HqlYadRdHJ5c": "FurnFurn测试增加一些长度",
                    "rAkCnq1kbI7W": 6700,
                    "7ti8XuX4kcY1": "2022"
                },
                {
                    "10001": "Profit",
                    "10002": 1899,
                    "10003": "rAkCnq1kbI7W",
                    "30001": "2023",
                    "HqlYadRdHJ5c": "Art是艺术的意思",
                    "rAkCnq1kbI7W": 1899,
                    "7ti8XuX4kcY1": "2023"
                },
                {
                    "10001": "Profit",
                    "10002": 4444,
                    "10003": "rAkCnq1kbI7W",
                    "30001": "2022",
                    "HqlYadRdHJ5c": "Art是艺术的意思",
                    "rAkCnq1kbI7W": 4444,
                    "7ti8XuX4kcY1": "2022"
                }
            ],
            "fields": {
                "10001": {
                    "alias": "指标名称"
                },
                "10002": {
                    "alias": "指标值"
                },
                "30001": {
                    "alias": "图例项",
                    "domain": [
                        "2023",
                        "2022"
                    ],
                    "sortIndex": 0,
                    "lockStatisticsByDomain": true
                },
                "HqlYadRdHJ5c": {
                    "alias": "Product",
                    "domain": [
                        "Labels测试维度名称是一个长字符串",
                        "Labels测试维度名称是一个长字符串",
                        "FurnFurn测试增加一些长度",
                        "FurnFurn测试增加一些长度",
                        "Art是艺术的意思",
                        "Art是艺术的意思"
                    ],
                    "sortIndex": 0,
                    "lockStatisticsByDomain": true
                },
                "7ti8XuX4kcY1": {
                    "alias": "Year"
                },
                "rAkCnq1kbI7W": {
                    "alias": "Profit"
                }
            }
        }
    ],
    "stackInverse": true,
    "axes": [
        {
            "type": "band",
            "tick": {
                "style": {
                    "strokeOpacity": 0.2
                },
                "visible": false
            },
            "grid": {
                "visible": false,
                "style": {
                    "zIndex": 150,
                    "stroke": "#FFFFFF",
                    "lineWidth": 1,
                    "lineDash": []
                }
            },
            "orient": "bottom",
            "visible": true,
            "domainLine": {
                "visible": false,
                "style": {
                    "lineWidth": 1,
                    "stroke": "#d5d7e2"
                }
            },
            "title": {
                "visible": true,
                "space": 5,
                "text": "",
                "style": {
                    "fontSize": 12,
                    "fill": "rgba(255,255,255,0.5)",
                    "fontFamily": "D-DIN",
                    "fontWeight": "normal"
                }
            },
            "maxHeight": null,
            "autoIndent": false,
            "sampling": false,
            "zIndex": 200,
            "label": {
                "visible": true,
                "space": 4,
                "style": {
                    "fontSize": 25,
                    "fill": "rgba(255,255,255,0.65)",
                    "angle": 0,
                    "fontFamily": "D-DIN",
                    "fontWeight": "normal",
                    "direction": "horizontal",
                    "maxLineWidth": 174
                },
                "autoHide": true,
                "autoHideMethod": "greedy",
                "flush": true,
                "lastVisible": true,
                "autoHideSeparation": 4
            },
            "hover": true,
            "background": {
                "visible": true,
                "state": {
                    "hover": {
                        "fillOpacity": 0.08,
                        "fill": "#141414"
                    },
                    "hover_reverse": {
                        "fillOpacity": 0.08,
                        "fill": "#141414"
                    }
                }
            },
            "paddingInner": 0.18,
            "paddingOuter": 0.18,
            "ticks": true
        },
        {
            "type": "linear",
            "tick": {
                "size": 4,
                "visible": true,
                "tickMode": "d3",
                tickCount: (args) => computeTickCount(args)
            },
            "niceType": "rough",
            "zIndex": 200,
            "grid": {
                "visible": true
            },
            "orient": "left",
            "visible": true,
            "domainLine": {
                "visible": false,
                "style": {
                    "lineWidth": 1,
                    "stroke": "#d5d7e2"
                }
            },
            "title": {
                "visible": false,
                "text": "",
                "space": 8,
                "style": {
                    "fontSize": 12,
                    "fill": "rgba(255,255,255,0.5)",
                    "fontFamily": "D-DIN",
                    "fontWeight": "normal"
                }
            },
            "autoIndent": false,
            "sampling": false,
            "label": {
                "visible": true,
                "space": 6,
                "flush": true,
                "padding": 0,
                "style": {
                    "fontSize": 30,
                    "maxLineWidth": 174,
                    "fill": "rgba(255,255,255,0.65)",
                    "angle": 0,
                    "fontFamily": "D-DIN",
                    "fontWeight": "normal",
                    "dy": -1,
                    "direction": "horizontal"
                },
                "autoHide": true,
                "autoHideMethod": "greedy",
                "autoHideSeparation": 4,
                "rotateAngle": [
                    null
                ],
                "labelOverlap": "custom",
                "tighten": false
            },
            "background": {
                "visible": true,
                "state": {
                    "hover": {
                        "fillOpacity": 0.08,
                        "fill": "#141414"
                    },
                    "hover_reverse": {
                        "fillOpacity": 0.08,
                        "fill": "#141414"
                    }
                }
            },
            "innerOffset": {
                "top": 0
            },
            "zero": false,
            "nice": true,
            "paddingInner": 0.18,
            "paddingOuter": 0.18,
            "maxWidth": 180,
            "ticks": true
        },
        {
            "type": "linear",
            "tick": {
                "size": 4,
                "visible": true,
                "tickMode": "d3"
            },
            "niceType": "rough",
            "zIndex": 200,
            "grid": {
                "visible": false
            },
            "orient": "right",
            "visible": true,
            "domainLine": {
                "visible": false
            },
            "title": {
                "visible": false,
                "text": "",
                "space": 8,
                "style": {
                    "fontSize": 12,
                    "fill": "rgba(255,255,255,0.5)",
                    "fontFamily": "D-DIN",
                    "fontWeight": "normal"
                }
            },
            "autoIndent": false,
            "sampling": false,
            "label": {
                "visible": true,
                "space": 6,
                "flush": true,
                "padding": 0,
                "style": {
                    "visible": false,
                    "fontSize": 30,
                    "maxLineWidth": 174,
                    "fill": "rgba(255,255,255,0.65)",
                    "angle": 0,
                    "fontFamily": "D-DIN",
                    "fontWeight": "normal",
                    "dy": -1,
                    "direction": "horizontal"
                },
                "autoHide": true,
                "autoHideMethod": "greedy",
                "autoHideSeparation": 4,
                "rotateAngle": [
                    null
                ],
                "labelOverlap": "custom",
                "tighten": false
            },
            "background": {
                "visible": true,
                "state": {
                    "hover": {
                        "fillOpacity": 0.08,
                        "fill": "#141414"
                    },
                    "hover_reverse": {
                        "fillOpacity": 0.08,
                        "fill": "#141414"
                    }
                }
            },
            "innerOffset": {
                "top": 0
            },
            "zero": false,
            "nice": true,
            "paddingInner": 0.18,
            "paddingOuter": 0.18,
            "maxWidth": 180,
            "ticks": true
        }
    ],
    "color": {
        "field": "30001",
        "type": "ordinal",
        "range": [
            "rgb(0,110,255)",
            "rgb(0,229,229)"
        ],
        "specified": {}
    },
    "colorGradient": {
        "type": "linear",
        "x0": {
            "field": "30001",
            "type": "ordinal",
            "range": [
                0,
                0
            ]
        },
        "y0": {
            "field": "30001",
            "type": "ordinal",
            "range": [
                1,
                1
            ]
        },
        "x1": {
            "field": "30001",
            "type": "ordinal",
            "range": [
                0.00001,
                0.00001
            ]
        },
        "y1": {
            "field": "30001",
            "type": "ordinal",
            "range": [
                0,
                0
            ]
        },
        "stops": [
            {
                "offset": 0,
                "color": {
                    "field": "30001",
                    "type": "ordinal",
                    "range": [
                        "rgba(0,110,255,0.2)",
                        "rgba(0,229,229,0.2)"
                    ]
                }
            },
            {
                "offset": 1,
                "color": {
                    "field": "30001",
                    "type": "ordinal",
                    "range": [
                        "rgb(0,110,255)",
                        "rgb(0,229,229)"
                    ]
                }
            }
        ]
    },
    "legends": [
        {
            "type": "discrete",
            "visible": true,
            "id": "legend-discrete",
            "orient": "top",
            "position": "end",
            "layoutType": "normal",
            "maxRow": 1,
            "title": {
                "textStyle": {
                    "fontSize": 12,
                    "fill": "rgba(255,255,255,0.45)"
                }
            },
            "layoutLevel": 70,
            "item": {
                "focus": true,
                "focusIconStyle": {
                    "size": 14
                },
                "maxWidth": 400,
                "spaceRow": 0,
                "spaceCol": 0,
                "padding": {
                    "left": 10,
                    "right": -10,
                    "top": 0,
                    "bottom": 5
                },
                "background": {
                    "visible": false,
                    "style": {
                        "fillOpacity": 0.001
                    }
                },
                "label": {
                    "style": {
                        "fontSize": 12,
                        "fill": "rgba(255,255,255,0.45)",
                        "fontFamily": "D-DIN",
                        "fontWeight": "normal"
                    },
                    "state": {
                        "unSelected": {
                            "fillOpacity": 0.2
                        }
                    }
                },
                "shape": {
                    "style": {
                        "lineWidth": 0,
                        "symbolType": "square",
                        "size": 12,
                        "fillOpacity": 1,
                        "width": 12,
                        "height": 7.416
                    }
                }
            },
            "pager": {
                "layout": "horizontal",
                "padding": 0,
                "textStyle": {},
                "space": 0,
                "handler": {
                    "preShape": "triangleLeft",
                    "nextShape": "triangleRight",
                    "style": {},
                    "state": {
                        "disable": {}
                    }
                }
            },
            "alignSelf": "end",
            "padding": {
                "left": 10,
                "right": 0,
                "top": 0,
                "bottom": 12
            }
        }
    ],
    "label": {
        "visible": false,
        "offset": 3,
        "overlap": {
            "hideOnHit": true,
            "avoidBaseMark": false,
            "strategy": [
                {
                    "type": "position",
                    "position": []
                }
            ],
            "clampForce": true
        },
        "style": {
            "fontSize": 10,
            "fontFamily": "D-DIN",
            "fontWeight": "normal",
            "zIndex": 400,
            "lineHeight": "100%",
            "fill": "rgba(255,255,255,1)",
            "strokeOpacity": 0
        },
        "position": "outside",
        "smartInvert": false,
        "fontWeight": "normal"
    },
    "tooltip": {
        "visible": true,
        "renderMode": "canvas",
        "mark": {
            "visible": true
        },
        "style": {
            "panel": {
                "padding": {
                    "top": 5,
                    "bottom": 10,
                    "left": 10,
                    "right": 10
                },
                "backgroundColor": "rgba(8, 28, 48, 0.95)",
                "border": {
                    "color": "#CFCFCF",
                    "width": 0,
                    "radius": 2
                },
                "shadow": {
                    "x": 0,
                    "y": 4,
                    "blur": 12,
                    "spread": 0,
                    "color": "rgba(0, 0, 0, 0.2)"
                }
            },
            "titleLabel": {
                "fontSize": 14,
                "fontColor": "#FFF",
                "fontWeight": "bold",
                "fontFamily": "D-DIN",
                "align": "left",
                "lineHeight": 18
            },
            "keyLabel": {
                "fontSize": 12,
                "fontColor": "rgba(255,255,255,0.65)",
                "fontWeight": "normal",
                "fontFamily": "SourceHanSansCN-Normal",
                "align": "left",
                "lineHeight": 18
            },
            "valueLabel": {
                "fontSize": 12,
                "fontColor": "#FFF",
                "fontWeight": "normal",
                "fontFamily": "D-DIN",
                "align": "right",
                "lineHeight": 18
            },
            "shape": {
                "size": 10,
                "spacing": 10
            },
            "spaceRow": 10
        },
        "dimension": {
            "visible": true
        }
    },
    "hover": {
        "enable": true
    },
    "select": {
        "enable": true
    },
    "bar": {
        "state": {
            "hover": {
                "cursor": "pointer",
                "fillOpacity": 0.8,
                "stroke": "#58595B",
                "lineWidth": 1,
                "zIndex": 500
            },
            "selected": {
                "cursor": "pointer",
                "fillOpacity": 1,
                "stroke": "#58595B",
                "lineWidth": 1
            },
            "selected_reverse": {
                "fillOpacity": 0.3,
                "lineWidth": 0.3
            }
        },
        "style": {
            "cornerRadius": 0,
            "fill": {
                "gradient": "linear",
                "x0": 0,
                "y0": 1,
                "stops": [
                    {
                        "offset": 0
                    },
                    {
                        "offset": 1
                    }
                ]
            },
            "lineWidth": 2,
            "stroke": {
                "gradient": "linear",
                "x0": 0,
                "y0": 1,
                "stops": [
                    {
                        "offset": 0
                    },
                    {
                        "offset": 1
                    }
                ]
            }
        }
    },
    "region": [
        {
            "clip": true
        }
    ],
    "background": "rgba(0, 0, 0, 1)",
    "animation": false,
    "crosshair": {
        "xField": {
            "visible": true,
            "line": {
                "type": "rect",
                "style": {
                    "fillOpacity": 1,
                    "fill": "rgba(80,156,255,0.1)"
                }
            }
        },
        "gridZIndex": 100,
        "yField": {
            "line": {
                "style": {
                    "fillOpacity": 1,
                    "fill": "rgba(80,156,255,0.1)"
                }
            },
            "visible": false
        }
    },
    "morph": {
        "enable": false
    },
    "fillOpacity": {
        "fillOpacity": 1
    },
    "axesPadding": true,
    "plotLayout": {
        "clip": false
    },
    "scales": [
        {
            "id": "gradientFillStop0",
            "type": "ordinal",
            "range": [
                "rgba(0,110,255,0.2)",
                "rgba(0,229,229,0.2)",
                "rgba(46,85,234,0.2)",
                "rgba(184,231,254,0.2)",
                "rgba(0,214,137,0.2)",
                "rgba(183,249,245,0.2)",
                "rgba(251,204,113,0.2)",
                "rgba(244,110,80,0.2)"
            ],
            "domain": [
                {
                    "dataId": "data",
                    "fields": [
                        "30001"
                    ]
                }
            ]
        },
        {
            "id": "gradientFillStop1",
            "type": "ordinal",
            "range": [
                "rgb(0,110,255)",
                "rgb(0,229,229)",
                "rgb(46,85,234)",
                "rgb(184,231,254)",
                "rgb(0,214,137)",
                "rgb(183,249,245)",
                "rgb(251,204,113)",
                "rgb(244,110,80)"
            ],
            "domain": [
                {
                    "dataId": "data",
                    "fields": [
                        "30001"
                    ]
                }
            ]
        },
        {
            "id": "gradientStrokeStop0",
            "type": "ordinal",
            "range": [
                "rgba(51, 139, 255, 0.2)",
                "rgba(25, 255, 255, 0.2)",
                "rgba(92, 123, 239, 0.2)",
                "rgba(234, 248, 255, 0.2)",
                "rgba(10, 255, 167, 0.2)",
                "rgba(230, 253, 252, 0.2)",
                "rgba(252, 222, 163, 0.2)",
                "rgba(247, 150, 128, 0.2)"
            ],
            "domain": [
                {
                    "dataId": "data",
                    "fields": [
                        "30001"
                    ]
                }
            ]
        },
        {
            "id": "gradientStrokeStop1",
            "type": "ordinal",
            "range": [
                "rgba(51, 139, 255, 1)",
                "rgba(25, 255, 255, 1)",
                "rgba(92, 123, 239, 1)",
                "rgba(234, 248, 255, 1)",
                "rgba(10, 255, 167, 1)",
                "rgba(230, 253, 252, 1)",
                "rgba(252, 222, 163, 1)",
                "rgba(247, 150, 128, 1)"
            ],
            "domain": [
                {
                    "dataId": "data",
                    "fields": [
                        "30001"
                    ]
                }
            ]
        },
        {
            "id": "gradientX1",
            "type": "ordinal",
            "range": [
                0.00001,
                0.00001,
                0.00001,
                0.00001,
                0.00001,
                0.00001,
                0.00001,
                0.00001
            ],
            "domain": [
                {
                    "dataId": "data",
                    "fields": [
                        "30001"
                    ]
                }
            ]
        },
        {
            "id": "gradientY1",
            "type": "ordinal",
            "range": [
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0
            ],
            "domain": [
                {
                    "dataId": "data",
                    "fields": [
                        "30001"
                    ]
                }
            ]
        }
    ],
    "barWidth": "40%",
    "barBackground": {
        "fieldLevel": 0,
        "visible": false,
        "interactive": false,
        "style": {
            "cornerRadius": 0,
            "fill": "rgba(255,255,255,1)",
            "fillOpacity": 0.25
        }
    },
    "animationAppear": {
        "bar": {
            "type": "growHeightIn",
            "oneByOne": false,
            "duration": 1000,
            "delayAfter": 4000,
            "loop": true
        }
    },
    "animationEnter": {
        "bar": {
            "type": "growHeightIn",
            "oneByOne": false,
            "duration": 1000,
            "delayAfter": 4000,
            "loop": false
        }
    },
    "animationUpdate": {
        "bar": {
            "type": "growHeightIn",
            "oneByOne": false,
            "duration": 1000,
            "delayAfter": 4000,
            "loop": false
        }
    },
    "hash": "419311acd1adac5992d8109037595a13"
}
const vchart = new VChart(spec, { dom: CONTAINER_ID });
vchart.renderSync();

// Just for the convenience of console debugging, DO NOT COPY!
window['vchart'] = vchart;

Current Behavior

20240409110824_rec_

Expected Behavior

tick will update when resize chart

Environment

- OS:
- Browser:
- Framework:

Any additional comments?

No response

skie1997 commented 5 months ago

解决方式:width和height强制写入spec,resize后强制触发tick更新

AdoneZ commented 4 months ago

条形图在resize的时候会报错TypeError: Cannot read properties of null (reading 'isCollectionMark'),且会导致页面渲染卡死,设置width和height后就好了。