Skip to content

ctx.fillStyle will be assigned with an ECharts-style gradient object #14322

@marcong95

Description

@marcong95

Version

5.0.2

Reproduction link

https://codepen.io/marcong95/pen/mdOqeLo?editors=0011

Steps to reproduce

Draw a line chart with a linear gradient as areaStyle, sometime, ctx.fillStyle will be assigned with an object which is illegal for CanvasRenderingContext2D. Then it will set to a legal one soon.

It's ok somehow when using ECharts in browser, but when I use it in uni-app with mpvue-echarts, which all the canvas operations will be proxied by uni-app. It throws an error, cuz fillStyle is in illegal value type.

What is expected?

ctx.fillStyle is only accepts one of the following:

A DOMString parsed as CSS value;
A CanvasGradient object (a linear or radial gradient);
A CanvasPattern object (a repeating image).

according to: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle

What is actually happening?

ctx.fillStyle was assigned with an ECharts-style gradient object like:

{
  "colorStops": [
    {
      "offset": 0,
      "color": "#3875f6"
    },
    {
      "offset": 1,
      "color": "#c0e4fc"
    }
  ],
  "x": 0,
  "y": 0,
  "x2": 0,
  "y2": 1,
  "type": "linear",
  "global": false
}

For whom may meet the same issue, which use ECharts in uni-app following https://ask.dcloud.net.cn/article/38568:

Exception like the following may be thrown:

TypeError: Invalid attempt to spread non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.

You can do the following modification for temporary fix:

in Line 36 of wx-canvas.js, there is an Object.defineProperty invocation, replace it with

      Object.defineProperty(ctx, style, {
        set: (value) => {
          if ((style !== 'fillStyle' && style !== 'strokeStyle') ||
            (value !== 'none' && value !== null)
          ) {
            if (style === 'fillStyle' && value.type && !value.data) {
              const { type, x, y, x2, y2, colorStops } = value;
              switch (type) {
                case 'linear':
                  value = {
                    type,
                    data: [x, y, x2, y2],
                    colorStop: colorStops
                  };
                  break;
                default:
                  console.error(
                    'fillStyle set with non-uni gradient object',
                    style, value);
              }
              return;
            }
            ctx[`set${style.charAt(0).toUpperCase()}${style.slice(1)}`](value);
          }
        }
      });

If you want to use other types of gradient like radial gradient, you may have to modify it accordingly yourself

Metadata

Metadata

Assignees

Labels

bugcompatibilityenThis issue is in EnglishstaleInactive for a long time. Will be closed in 7 days.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions