Skip to content

Conversation

@fnlearner
Copy link
Contributor

This commit adds the renderDistribution2 function, which is used to render a kernel density estimation (KDE) sparkline chart within a given HTML element.

This commit adds the `renderDistribution2` function, which is used to
render a kernel density estimation (KDE) sparkline chart within a given
HTML element.
@gemini-code-assist
Copy link

Summary of Changes

Hello @fnlearner, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new renderDistribution2 function, enabling the rendering of kernel density estimation (KDE) sparkline charts. It includes the necessary underlying utility functions for data processing, scaling, and SVG path generation, along with an example demonstrating its usage. The primary goal is to expand the charting capabilities with a compact visualization for data distributions.

Highlights

  • New Sparkline Chart: Introduced renderDistribution2 to create kernel density estimation (KDE) sparkline charts, expanding the available visualization types.
  • Core Chart Utilities: Added new data utility functions (max, extent, mean) and path generation functions (curveBasis, createCurvePath, ticks) to support the new chart rendering capabilities.
  • Example Integration: Included an example usage of the new renderDistribution2 function in example/main.tsx with mock data to demonstrate its implementation.
  • Selection Data Binding: Enhanced the Selection utility with a datum method for binding data to elements, mirroring common D3.js patterns.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@fnlearner
Copy link
Contributor Author

/gemini review

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new renderDistribution2 function to create kernel density estimation (KDE) sparkline charts, along with several new utility functions for data processing, path creation, and scales. The overall implementation is a great addition.

My review includes several suggestions to improve the code quality, maintainability, and correctness. I've identified a critical bug in renderDistribution2 that could cause the chart to render twice. I've also pointed out opportunities to improve code clarity by renaming interfaces, refactoring complex logic, adding documentation, and using more descriptive error messages. Additionally, there are suggestions to enhance type safety in some of the new utility functions.

Comment on lines 122 to 135
// 使用新的 createSvg 函数来创建和选择 SVG 元素
const svgD3 = createSvg(container, width, height);

const pathData = createCurvePath(xScale, finalYScale, density);

svgD3
.append('path')
.attr('class', 'mypath')
.datum(density)
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('stroke-width', 2)
.attr('stroke-linejoin', 'round')
.attr('d', pathData);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This block of code is executed unconditionally. However, if wordElement is provided and sparkLinePosition is 'up' or 'down', the sparkline is already rendered inside the if block at lines 84-120. This causes the sparkline to be rendered twice. This block should be wrapped in an else statement corresponding to the if on line 84 to prevent this.

import { createCurvePath, createSvg, extent, max, mean, scaleLinear } from '../utils';
import { ticks } from '../utils/scales';

export interface Distribution1Config {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The interface is named Distribution1Config, but it's used for the renderDistribution2 function. This is confusing and could lead to errors. Please rename it to Distribution2Config for clarity and consistency, and update its usage on line 16.

Suggested change
export interface Distribution1Config {
export interface Distribution2Config {

Comment on lines 11 to 15
/**
*
* @param container
* @param config
*/

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The JSDoc for renderDistribution2 is empty. Please add a description of what the function does, its parameters (container, config), and any important details about its behavior, such as how it renders the KDE sparkline. Good documentation is crucial for maintainability.

* @param container
* @param config
*/
export const renderDistribution2 = (container: Element, config: Distribution1Config) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Following the suggestion to rename the Distribution1Config interface, please update the type here to Distribution2Config.

Suggested change
export const renderDistribution2 = (container: Element, config: Distribution1Config) => {
export const renderDistribution2 = (container: Element, config: Distribution2Config) => {

height = 20;
}

// 清理旧的SVG

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This comment is in Chinese, while the rest of the codebase is in English. For consistency and to ensure all developers can understand the comments, please translate it to English.

// Clear old SVG


const valueExtent = extent(values);
if (valueExtent[0] === undefined) {
throw new Error('Error');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The error message "Error" is not descriptive. When an error is thrown, it should provide context about what went wrong. Please provide a more informative error message.

    throw new Error('Input data is empty or invalid, cannot calculate value extent.');


const xScale = scaleLinear(valueExtent, [padding, width - padding]);

const kde = kernelDensityEstimator(kernelEpanechnikov(7), ticks(valueExtent, 40));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The numbers 7 and 40 are used here without explanation, making the code harder to understand. Please define them as named constants with comments explaining their purpose (e.g., KDE_BANDWIDTH, TICK_COUNT).

  const KDE_BANDWIDTH = 7; // Controls the smoothness of the KDE plot.
  const TICK_COUNT = 40; // Number of points to sample for the density estimation.
  const kde = kernelDensityEstimator(kernelEpanechnikov(KDE_BANDWIDTH), ticks(valueExtent, TICK_COUNT));

Comment on lines 9 to 11
if (values.length === 0) {
return undefined;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This check for values.length === 0 is redundant because the check !array || array.length === 0 at the beginning of the function already handles empty arrays. You can safely remove this block.

nodes(): Element[] {
return [...this.elements];
}
datum(data): Selection {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The data parameter in the datum method has an implicit any type. To improve type safety, you should provide an explicit type. Using a generic D would be the most flexible and type-safe approach.

Suggested change
datum(data): Selection {
datum<D>(data: D): Selection {

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new renderDistribution2 function for rendering kernel density estimation sparkline charts. The changes include adding the new function, updating imports and exports, and adding a mock data file. The review focuses on potential improvements in error handling and code clarity.

Comment on lines 74 to 77
// Store the data on the element, a common D3 practice
// You can also use a private field on the Selection instance.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(el as any).__data__ = data;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Storing data directly on DOM elements using __data__ is generally discouraged as it pollutes the DOM and can lead to conflicts with other libraries or frameworks. Consider using a WeakMap to associate data with DOM elements instead. This provides a cleaner and more encapsulated way to manage data.

Here's how you can implement this using a WeakMap:

const dataMap = new WeakMap<Element, any>();

this.elements.forEach((el) => {
  dataMap.set(el, data);
});
    const dataMap = new WeakMap<Element, any>();

    this.elements.forEach((el) => {
      dataMap.set(el, data);
    });
    return this;

Comment on lines 72 to 73
if (valueExtent[0] === undefined) {
throw new Error('Error');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This error handling could be improved. Throwing a generic Error object doesn't provide much context. Consider providing a more specific error message to aid in debugging. Also, it might be better to return null or an empty svg element instead of throwing an error, to prevent the entire chart from failing to render if the data is invalid.

For example, the error message could be Data extent is undefined, cannot render chart.

};
};

// A simplified implementation of d3.curveBasis

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This comment is redundant. It's restating the obvious. Remove it to improve code clarity.

Comment on lines 67 to 69
while (container.firstChild) {
container.removeChild(container.firstChild);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Consider using container.innerHTML = ''; instead of the while loop for clearing the SVG. This is generally faster and more concise.

  container.innerHTML = '';

@BQXBQX BQXBQX self-assigned this Sep 25, 2025
@codecov-commenter
Copy link

codecov-commenter commented Oct 2, 2025

Codecov Report

❌ Patch coverage is 10.11236% with 80 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.57%. Comparing base (a57446b) to head (f3679f3).

Files with missing lines Patch % Lines
src/charts/utils/paths.ts 5.88% 32 Missing ⚠️
src/charts/utils/scales.ts 3.57% 27 Missing ⚠️
src/charts/utils/data.ts 12.50% 21 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #139      +/-   ##
==========================================
- Coverage   91.48%   85.57%   -5.91%     
==========================================
  Files          67       68       +1     
  Lines        1139     1227      +88     
  Branches      235      235              
==========================================
+ Hits         1042     1050       +8     
- Misses         97      177      +80     
Flag Coverage Δ
t8 85.57% <10.11%> (-5.91%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/charts/index.ts 100.00% <100.00%> (ø)
src/charts/utils/index.ts 100.00% <100.00%> (ø)
src/charts/utils/data.ts 12.50% <12.50%> (ø)
src/charts/utils/scales.ts 34.14% <3.57%> (-65.86%) ⬇️
src/charts/utils/paths.ts 65.59% <5.88%> (-34.41%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@BQXBQX BQXBQX merged commit 63e402a into antvis:main Oct 4, 2025
1 check passed
@fnlearner fnlearner deleted the f/sparkline branch October 7, 2025 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants