Skip to content

[Bug] updateSpec: background is not re-rendered when spec.background and spec.theme change in the same call #4649

Description

@chendaxin-tk

Version

2.1.6 (also reproduces on 2.1.5)

Link to Minimal Reproduction

https://gist.github.com/chendaxin-tk/dfb94e188970055a1ddadc2332194c23

Self-contained HTML — save it and open in a browser, it loads vchart 2.1.6 from unpkg and prints the result on the page.

Steps to Reproduce

  1. Render a chart whose spec.background is the mark form { fill: <gradient> }, with spec.theme.background = 'transparent' (the canvas base color has to be transparent, otherwise the gradient's alpha composites against it).
  2. Call updateSpec() with a spec where background is a color string ('#4e83fd') and theme.background is back to an opaque color ('#ffffff').
  3. Look at the canvas.

A plain updateSpec(spec) is enough — no extra arguments needed.

Current Behavior

The canvas still paints the old gradient. Sampling the bottom-right pixel:

after render : pixel=255,159,67   stage.background=transparent
after update : pixel=255,159,67   stage.background=#4e83fd     <-- still the gradient

Note stage.background is updated correctly to #4e83fd. The problem is that the background mark created from the previous { fill } spec is never rebuilt or removed, and it covers the whole viewBox — so the corrected canvas base color is invisible and nothing changes on screen.

Isolating it — same repro, only what changes in the update spec varies:

# changed in updateSpec result
A background and theme ❌ old gradient stays
B background only, theme untouched ✅ blue
C background and theme, called as updateSpec(spec, false, { reuse: false, morph: false }, { change: true, reMake: true }) ✅ blue

Expected Behavior

Case A should behave like case B — the new background should be painted.

Probable Cause

In core/vchart.js, updateSpec only compares background when the theme is unchanged:

isEqual(lastSpec.theme, this._spec.theme)
  ? (isEqual(this._spec.background, lastSpec.background) || (result.reMake = !0, result.changeBackground = !0))
  : result.changeTheme = !0;

When both change in the same call, the ternary takes the changeTheme branch, so reMake / changeBackground are never set and the background mark is not rebuilt. setBackground() still runs indirectly via _setCurrentTheme()_updateCurrentTheme(), which is why stage.background looks right while the canvas does not change.

This looks like a remaining gap in the fix for #3054, which covered the case where only background changes.

Forcing reMake: true (case C above) is a workaround, but it rebuilds the whole chart.

Additional observation (could not minimize — treat as a lead, not a confirmed repro)

In a larger application the same gradient → solid transition throws instead of silently keeping the old background:

TypeError: Cannot read properties of undefined (reading 'group')
    at GroupMark._compileProduct (...)

which aborts the entire updateSpec. In mark/base/base-mark.js, _compileProduct guards option on two lines but dereferences it bare on a third:

_compileProduct(option) {
    this.commit(), this._context = null == option ? void 0 : option.context;   // guarded
    const product = this.getProduct();
    if (this._visible) {
        if (isValid(product)) option.group && product.parent !== option.group && option.group.appendChild(product);   // NOT guarded
        else {
            if (!this.getCompiler().isInited) return;
            this._initProduct(null == option ? void 0 : option.group);         // guarded
        }

I was not able to reproduce this one in isolation, so I am reporting it only as a pointer — the inconsistent guarding is visible statically and may or may not be related to the main issue above.

Environment

  • @visactor/vchart 2.1.6 (UMD build from unpkg) and 2.1.5
  • Chromium (Playwright), Linux

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions