VisActor / VisActor/VChart

[Bug] render result is inconsistent before and after datazoom moving

Open
#4,042 1 comment 0 reactions 2 assignees View on GitHub

@xiaoluoHe is already working on this.

Since Jun 19, 2025.

bug
Dominant language
TypeScript
Stars
1.8k
Forks
221
Avg merge
1d 6h
Merged PRs (30d)
26

Description

Version

1.12.14

Link to Minimal Reproduction

null

Steps to Reproduce
function formatNumberToTenThousand(num, decimalPlaces = 2, unitStyle) {
  if (typeof num !== 'number') {
    return '-'; // 非数字类型返回 -
  }
  if (num < 0) {
    return `-${formatNumberToTenThousand(Math.abs(num), decimalPlaces, unitStyle)}`; // 处理负数
  }

  // 新增大单位判断逻辑
  const units = [
    { threshold: 100000000, divisor: 100000000, unit: '亿' }, // 1亿
    // { threshold: 10000000, divisor: 10000000, unit: '千万' }, // 1千万
    // { threshold: 1000000, divisor: 1000000, unit: '百万' }, // 1百万
    { threshold: 10000, divisor: 10000, unit: '万' }, // 1万
  ];

  // 查找匹配的单位
  const matchedUnit = units.find((unit) => num >= unit.threshold);

  if (matchedUnit) {
    const value = num / matchedUnit.divisor;
    const fixedValue = value.toFixed(decimalPlaces);

    // // 万单位格式化(增加千分位)
    // const valuePart = (num / 10000).toFixed(decimalPlaces).replace(/\B(?=(\d{3})+(?!\d))/g, ',');

    // 添加千分位并格式化
    const valuePart = fixedValue.includes('.')
      ? fixedValue.replace(/(\d)(?=(\d{3})+\.)/g, '$1,')
      : Number(fixedValue).toLocaleString();

    if (unitStyle) {
      return `${valuePart}<span style="${unitStyle}">${matchedUnit.unit}</span>`;
    }
    return `${valuePart}${matchedUnit.unit}`;
  }

  // 千分位格式化(小于1万)
  return num.toLocaleString('en-US', {
    minimumFractionDigits: 0,
    maximumFractionDigits: decimalPlaces,
  });
}

function formatNumberToPercentage(num) {
  if (num === null || num === undefined) {
    return '-';
  }
  if (typeof num !== 'number') {
    return '-';
  }
  const percentage = (num * 100).toFixed(2);
  return `${percentage}%`;
}

const spec = {
  "type": "bar", 
   title: {
    visible: true,
    text: "地域分布",
    textStyle: {
      fontSize: 12,
      lineHeight: 18,
    },
  },
  "data": [
    {
      "id": "horizontalBarData",
      "values": [
        {
          "name": "广东",
          "value": 2152188,
          "percent": 0.09553189059340318
        },
        {
          "name": "江苏",
          "value": 1619691,
          "percent": 0.07189527281404776
        },
        {
          "name": "河南",
          "value": 1561747,
          "percent": 0.06932323920520682
        },
        {
          "name": "山东",
          "value": 1503274,
          "percent": 0.06672772420434812
        },
        {
          "name": "四川",
          "value": 1455915,
          "percent": 0.06462554037718572
        },
        {
          "name": "浙江",
          "value": 1392015,
          "percent": 0.06178913026388779
        },
        {
          "name": "河北",
          "value": 1040775,
          "percent": 0.04619819617633274
        },
        {
          "name": "湖北",
          "value": 1038831,
          "percent": 0.046111905389787336
        },
        {
          "name": "湖南",
          "value": 930692,
          "percent": 0.04131180283514061
        },
        {
          "name": "陕西",
          "value": 896006,
          "percent": 0.03977215148631663
        },
        {
          "name": "安徽",
          "value": 887653,
          "percent": 0.03940137631141244
        },
        {
          "name": "福建",
          "value": 748169,
          "percent": 0.03320992360025048
        },
        {
          "name": "江西",
          "value": 725247,
          "percent": 0.03219245579716729
        },
        {
          "name": "山西",
          "value": 685430,
          "percent": 0.030425048262250485
        },
        {
          "name": "辽宁",
          "value": 568686,
          "percent": 0.02524298468999924
        },
        {
          "name": "重庆",
          "value": 552976,
          "percent": 0.024545645051815976
        },
        {
          "name": "广西",
          "value": 521468,
          "percent": 0.023147059608157265
        },
        {
          "name": "贵州",
          "value": 489247,
          "percent": 0.021716825331778974
        },
        {
          "name": "云南",
          "value": 472549,
          "percent": 0.020975630088088067
        },
        {
          "name": "上海",
          "value": 472234,
          "percent": 0.020961647784712656
        },
        {
          "name": "北京",
          "value": 407114,
          "percent": 0.018071083988500422
        },
        {
          "name": "新疆",
          "value": 381173,
          "percent": 0.016919608014336698
        },
        {
          "name": "黑龙江",
          "value": 373560,
          "percent": 0.016581680155298557
        },
        {
          "name": "甘肃",
          "value": 327979,
          "percent": 0.014558418662744045
        },
        {
          "name": "吉林",
          "value": 309830,
          "percent": 0.013752816046996874
        },
        {
          "name": "内蒙古",
          "value": 296377,
          "percent": 0.013155660722205056
        },
        {
          "name": "天津",
          "value": 266422,
          "percent": 0.011826010253600366
        },
        {
          "name": "海南",
          "value": 143117,
          "percent": 0.006352715276758389
        },
        {
          "name": "宁夏",
          "value": 111102,
          "percent": 0.00493162498290497
        },
        {
          "name": "未知",
          "value": 85262,
          "percent": 0.0037846322234743163
        },
        {
          "name": "青海",
          "value": 49995,
          "percent": 0.002219191292869021
        },
        {
          "name": "西藏",
          "value": 14963,
          "percent": 0.0006641816044644296
        },
        {
          "name": "香港",
          "value": 6571,
          "percent": 0.00029167528723757045
        },
        {
          "name": "中区社区",
          "value": 1804,
          "percent": 0.00008007642948966323
        }
      ]
    }
  ],
  direction: 'horizontal',
  xField: 'value',
  yField: 'name',
  seriesField: 'name',
  height: 300,
  padding: { right: 140, left: 0 },
  legends: {
    visible: true,
    orient: 'top',
    position: 'middle',
  },
  axes: [
    {
      orient: 'bottom',
      visible: false,
      nice: false,
    },
    {
      orient: 'left',
      maxWidth: 120,
      label: {
        autoLimit: true,
      },
      domainLine: {
        visible: false,
      },
      tick: {
        visible: false,
      },
    },
  ],
  stackCornerRadius: 0,
  bar: {
    style: {
      height: 16,
    },
  },
  barBackground: {
    visible: true,
    style: {
      height: 16,
    },
    state: {
      hover: {
        stroke: '#D9D9D9',
        lineWidth: 1,
      },
    },
  },
  crosshair: {
    yField: {
      visible: false,
    },
  },
  extensionMark: [
    {
      type: 'text',
      dataId: 'barData',
      visible: true,
      style: {
        text: (datum) => `${formatNumberToTenThousand(datum?.value)}人 ${formatNumberToPercentage(datum?.percent)}`,
        fontSize: 12,
        x: (_datum, ctx) => {
          return ctx.getRegion().getLayoutRect().width + 16;
        },
        y: (datum, ctx) => {
          return ctx.valueToY([datum.name]) + ctx.yBandwidth() / 2;
        },
        textBaseline: 'middle',
        textAlign: 'left',
        fill: '#595959',
        size: 20,
      },
    },
  ],
  tooltip: {
    mark: {
      content: {
        value: (datum) => `${formatNumberToTenThousand(datum?.value)}`,
      },
    },
    dimension: {
      content: {
        value: (datum) => `${formatNumberToTenThousand(datum?.value)}`,
      },
    },
  },
  dataZoom: {
    visible: true,
    orient: 'right',
    valueField: 'name',
    field: 'name',
    showDetail: false,
    start: 0,
    end: 8 / 34,
    offsetX: 130,
    offsetY: 0,
    padding: 0,
    roamScroll: true,
  },
};

const vchart = new VChart(spec, { dom: CONTAINER_ID });

vchart.renderSync();
Current Behavior

before:
Image
after:
Image

Expected Behavior

consistant render result

Environment
- OS:
- Browser:
- Framework:
Any additional comments?

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.