Giter VIP home page Giter VIP logo

chart2music's People

Contributors

ayjayt avatar dependabot[bot] avatar julianna-ciq avatar julianna-langston avatar spmealin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

chart2music's Issues

Suggestion: appending sonify instruction to original alt text when available

Currently, when alt attribute and its corresponding value exist within an image element, c2m does not add any sonification instruction message. What if you append the sonification instruction to the original alt value by its default behavior, and make its behavior configurable for the users (e.g., options for append, override, none)?

Reproducible Example

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <script src="https://cdn.jsdelivr.net/npm/chart2music"></script>
</head>

<body>

    <img src="mychart.png" id="MyChart" alt="Original alt text by content author." />

    <script>
        c2mChart({
            type: "bar",
            element: document.getElementById("MyChart"),
            data: [1, 2, 3]
        });
    </script>
</body>

</html>

Do you have plans for supporting other chart types?

I was wondering if you had any plans for supporting the following chart types:

  • Boxplot.

  • Scatter plot.

  • Heat map.

  • Histogram.

  • Geospatial map.

  • Segmented (stacked) bar plot within each level.

  • Dodged (side-by-side) bar plot within each level.

I know, we cannot cover everything at once, but it would be great if we could prioritize some chart types. FYI, our team has been working on SVG-based accessible charts for bar plot, boxplot, heat map, and scatter plot. Will share our progress as well going forward. We are also trying to keep the same json metadata format in our own module to be compatible with C2M in the long run.

docs: Gallery of supported chart types

Provide a gallery of different chart types and features on a page. The charts should be directly embedded, but should include links to a codepen, so that developers can see how it was put together.

Chart type examples:

  • bar
  • line
  • bar-line
  • band
  • box
  • candlestick
  • histogram
  • heatmap
  • correlation matrix
  • pie chart
  • donut chart
  • scatter plot

Features:

  • grouped chart
  • mixed chart types
  • logarithmic axes
  • time axes
  • labels

Feature Request: Info dialog for annotations

Support his new top-level property:

{
    info: {
        notes: [
            "Data from BLS, World Bank, FiveThirtyEight"
        ]
    }
}

Add a new keyboard shortcut, "i", to open an info dialog. In this dialog, all of the notes should be listed in an unordered list. Only plain text is supported.

New Feature: Support `string` x values

Let's say you want to create a simple bar chart that shows how many moon Mercury, Venus, Earth, and Mars have. You could do that in a couple of ways:

Option 1: Using formats

const planets = ["Mercury", "Venus", "Earth", "Mars"];
c2mChart({
  type: "bar",
  data: [0,0,1,2],
  axes: {
    x: {
      format: (index) => planets[index]
    }
  }
});

Option 2: Using valueLabels

const planets = ["Mercury", "Venus", "Earth", "Mars"];
c2mChart({
  type: "bar",
  data: [0,0,1,2],
  axes: {
    x: {
      valueLabels: planets
    }
  }
});

However, this is separating out the data with the labels. If we kept the 2 together, we could instead do something like this:

c2mChart({
  type: "bar",
  data: [
    {x: "Mercury", y: 0},
    {x: "Venus", y: 0},
    {x: "Earth", y: 1},
    {x: "Mars", y: 2}
  ]
});

Note that this isn't simply a matter of finding a new way to do the same thing. The data value supports data points that are either numbers or objects; if the data points are object, then x is required and must be a number. If you need to use an object (eg, the chart is a box plot, or you want to leverage the custom property for a callback), then you need to use a numeric x value, even when it doesn't make sense.

Here is the data for a chart showing the first 4 planets, showing how close and how far they get from the sun. Note how each data point has an x value that simply duplicates its own index:

const planets = ["Mercury", "Venus", "Earth", "Mars"];
c2mChart({
  type: "bar",
  data: [
    {
      x: 0,
      high: .466, // Measured in Astronomical Units
      low: .307
    },
    {
      x: 1,
      high: .728,
      low: .718
    },
    {
      x: 2,
      high: 1.016,
      low: .983
    },
    {
      x: 3,
      high: 1.666
      low: 1.381
    },
  ],
  axes: {
    x: {
      valueLabels: planets
    }
  }
});

In this case, it makes more sense to be able to just put down:

{x: "Mercury", high: .466, low: .307}

instead of duplicating index values and juggling where the data was placed.

Suggestion: using `aria` application role for the sonified charts

Sonified image elements by c2m require screen readers' focus mode/forms mode. Do you have any special reasons that you did not implement "application" role for the users not having to manually switch between modes? I have also noticed that SAS Graphic Accelerator used "application" role.

The following example automatically switches to screen readers' focus/forms mode when it gets focused via tab key.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <script src="https://cdn.jsdelivr.net/npm/chart2music"></script>
</head>

<body>

    <img src="mychart.png" id="MyChart" role="application"/>

    <script>
        c2mChart({
            type: "bar",
            element: document.getElementById("MyChart"),
            data: [1, 2, 3]
        });
    </script>
</body>

</html>

Support ID for focus changes

Add id as a supported property for all data points

Whenever data is changed, keep track of the ID of the data point that's in focus. If the data changes, but a data point with the focus ID is currently specified, and no focus point is provided, keep the data point with the current focus ID.

This means that the order of precedence to determine which data point has focus when data changes is:

  1. The data point specified by the setData function
  2. The data point with currently focused ID (if specified and available)
  3. The first data point

ECharts integration success

Great package, easy to work with 🥇
Noticed your recent post on the ECharts board and got intrigued. ECharts currently does not support keyboard commands.
But chart2music does! So I played with two of your examples and got it rocking - chart2music on ECharts.
Custom hotkeys is a nice feature. I added '+' and '-' for zoom in & out. It could help with EChart issues like this one.
Hope many more people will benefit from your work. Thank you.

image

New Feature: Audio Engine: Support sound effects

Support sound effects in the audio engine.

The AudioEngine interface should include the functions:

  • getAvailableSoundEffects(): string[]
  • playSoundEffect(effect_name: string, panning: number, duration: number): {err: null | string}

The sound effects that the AudioEngine should support are:

  • ping - a short, high-pitched sound that rises rapidly and falls rapidly
  • chime - a medium-length, high-pitched sound that rises rapidly and falls slowly

When calling getAvailableSoundEffects, it should return the names of sound effects available. In this case, it should return [ping, chime]. The order of the returned effects is not meaningful.

When playSoundEffect is called, it should play the requested sound. If there is no error, it should return {err: null}. If the requested doesn't exist, it should return an error message:

{
  err: "Requested sound 'bad' is not available. The available sounds are: 'ping', 'chime'"
}

The requested sound effect should be played at the provided panning.

The provided duration relates to the duration of individual data points. The sound doesn't need to take as long as the duration, but should try to be shorter than the duration when possible.

Create User Guide for C2M

Provide instructions for how end-users would interact with Chart2Music.

Instructions should include all of the current keyboard and mobile interactions.

Mobile device support

I was wondering if C2M sonification could be also access via mobile devices, such as iOS and Android. My quick test with iPhone does not seem to work, but please correct me if I am wrong.

Doesn't work with directly embeded raw svg

The following example does not work. Simply speaking, sonification is not generated with a directly embedded svg object.

Reproducible Example

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <script src="https://cdn.jsdelivr.net/npm/chart2music"></script>
</head>

<body>

    <svg id='MyChart' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' class='svglite'
        width='504.00pt' height='360.00pt' viewBox='0 0 504.00 360.00'>
        <defs>
            <style type='text/css'>
                <![CDATA[
                .svglite line,
                .svglite polyline,
                .svglite polygon,
                .svglite path,
                .svglite rect,
                .svglite circle {
                    fill: none;
                    stroke: #000000;
                    stroke-linecap: round;
                    stroke-linejoin: round;
                    stroke-miterlimit: 10.00;
                }

                .svglite text {
                    white-space: pre;
                }
                ]]>
            </style>
        </defs>
        <rect width='100%' height='100%' style='stroke: none; fill: #FFFFFF;' />
        <defs>
            <clipPath id='cpMC4wMHw1MDQuMDB8MC4wMHwzNjAuMDA='>
                <rect x='0.00' y='0.00' width='504.00' height='360.00' />
            </clipPath>
        </defs>
        <g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHwzNjAuMDA=)'>
            <rect x='0.00' y='0.00' width='504.00' height='360.00'
                style='stroke-width: 1.07; stroke: #FFFFFF; fill: #FFFFFF;' />
        </g>
        <defs>
            <clipPath id='cpMzMuMjR8NDk4LjUyfDUuNDh8MzI4LjI3'>
                <rect x='33.24' y='5.48' width='465.28' height='322.79' />
            </clipPath>
        </defs>
        <g clip-path='url(#cpMzMuMjR8NDk4LjUyfDUuNDh8MzI4LjI3)'>
            <rect x='33.24' y='5.48' width='465.28' height='322.79'
                style='stroke-width: 1.07; stroke: none; fill: #EBEBEB;' />
            <polyline points='33.24,266.27 498.52,266.27 '
                style='stroke-width: 0.53; stroke: #FFFFFF; stroke-linecap: butt;' />
            <polyline points='33.24,171.61 498.52,171.61 '
                style='stroke-width: 0.53; stroke: #FFFFFF; stroke-linecap: butt;' />
            <polyline points='33.24,76.95 498.52,76.95 '
                style='stroke-width: 0.53; stroke: #FFFFFF; stroke-linecap: butt;' />
            <polyline points='33.24,313.60 498.52,313.60 '
                style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
            <polyline points='33.24,218.94 498.52,218.94 '
                style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
            <polyline points='33.24,124.28 498.52,124.28 '
                style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
            <polyline points='33.24,29.62 498.52,29.62 '
                style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
            <polyline points='72.01,328.27 72.01,5.48 '
                style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
            <polyline points='136.64,328.27 136.64,5.48 '
                style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
            <polyline points='201.26,328.27 201.26,5.48 '
                style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
            <polyline points='265.88,328.27 265.88,5.48 '
                style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
            <polyline points='330.50,328.27 330.50,5.48 '
                style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
            <polyline points='395.12,328.27 395.12,5.48 '
                style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
            <polyline points='459.75,328.27 459.75,5.48 '
                style='stroke-width: 1.07; stroke: #FFFFFF; stroke-linecap: butt;' />
            <rect x='42.93' y='289.93' width='58.16' height='23.67'
                style='stroke-width: 1.07; stroke: none; stroke-linecap: square; stroke-linejoin: miter; fill: #595959;' />
            <rect x='107.56' y='91.15' width='58.16' height='222.45'
                style='stroke-width: 1.07; stroke: none; stroke-linecap: square; stroke-linejoin: miter; fill: #595959;' />
            <rect x='172.18' y='119.55' width='58.16' height='194.05'
                style='stroke-width: 1.07; stroke: none; stroke-linecap: square; stroke-linejoin: miter; fill: #595959;' />
            <rect x='236.80' y='261.54' width='58.16' height='52.06'
                style='stroke-width: 1.07; stroke: none; stroke-linecap: square; stroke-linejoin: miter; fill: #595959;' />
            <rect x='301.42' y='157.41' width='58.16' height='156.19'
                style='stroke-width: 1.07; stroke: none; stroke-linecap: square; stroke-linejoin: miter; fill: #595959;' />
            <rect x='366.04' y='147.94' width='58.16' height='165.66'
                style='stroke-width: 1.07; stroke: none; stroke-linecap: square; stroke-linejoin: miter; fill: #595959;' />
            <rect x='430.67' y='20.15' width='58.16' height='293.45'
                style='stroke-width: 1.07; stroke: none; stroke-linecap: square; stroke-linejoin: miter; fill: #595959;' />
        </g>
        <g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHwzNjAuMDA=)'>
            <text x='28.31' y='316.75' text-anchor='end' style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";'
                textLength='4.90px' lengthAdjust='spacingAndGlyphs'>0</text>
            <text x='28.31' y='222.09' text-anchor='end' style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";'
                textLength='9.79px' lengthAdjust='spacingAndGlyphs'>20</text>
            <text x='28.31' y='127.43' text-anchor='end' style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";'
                textLength='9.79px' lengthAdjust='spacingAndGlyphs'>40</text>
            <text x='28.31' y='32.77' text-anchor='end' style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";'
                textLength='9.79px' lengthAdjust='spacingAndGlyphs'>60</text>
            <polyline points='30.50,313.60 33.24,313.60 '
                style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
            <polyline points='30.50,218.94 33.24,218.94 '
                style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
            <polyline points='30.50,124.28 33.24,124.28 '
                style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
            <polyline points='30.50,29.62 33.24,29.62 '
                style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
            <polyline points='72.01,331.01 72.01,328.27 '
                style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
            <polyline points='136.64,331.01 136.64,328.27 '
                style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
            <polyline points='201.26,331.01 201.26,328.27 '
                style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
            <polyline points='265.88,331.01 265.88,328.27 '
                style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
            <polyline points='330.50,331.01 330.50,328.27 '
                style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
            <polyline points='395.12,331.01 395.12,328.27 '
                style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
            <polyline points='459.75,331.01 459.75,328.27 '
                style='stroke-width: 1.07; stroke: #333333; stroke-linecap: butt;' />
            <text x='72.01' y='339.50' text-anchor='middle'
                style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";' textLength='29.36px'
                lengthAdjust='spacingAndGlyphs'>2seater</text>
            <text x='136.64' y='339.50' text-anchor='middle'
                style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";' textLength='33.26px'
                lengthAdjust='spacingAndGlyphs'>compact</text>
            <text x='201.26' y='339.50' text-anchor='middle'
                style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";' textLength='29.82px'
                lengthAdjust='spacingAndGlyphs'>midsize</text>
            <text x='265.88' y='339.50' text-anchor='middle'
                style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";' textLength='30.32px'
                lengthAdjust='spacingAndGlyphs'>minivan</text>
            <text x='330.50' y='339.50' text-anchor='middle'
                style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";' textLength='25.44px'
                lengthAdjust='spacingAndGlyphs'>pickup</text>
            <text x='395.12' y='339.50' text-anchor='middle'
                style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";' textLength='47.46px'
                lengthAdjust='spacingAndGlyphs'>subcompact</text>
            <text x='459.75' y='339.50' text-anchor='middle'
                style='font-size: 8.80px;fill: #4D4D4D; font-family: "Arial";' textLength='13.69px'
                lengthAdjust='spacingAndGlyphs'>suv</text>
            <text x='265.88' y='352.10' text-anchor='middle' style='font-size: 11.00px; font-family: "Arial";'
                textLength='25.06px' lengthAdjust='spacingAndGlyphs'>class</text>
            <text transform='translate(13.36,166.88) rotate(-90)' text-anchor='middle'
                style='font-size: 11.00px; font-family: "Arial";' textLength='26.92px'
                lengthAdjust='spacingAndGlyphs'>count</text>
        </g>
    </svg>


    <script>
        c2mChart({
            type: "bar",
            element: document.getElementById("MyChart"),
            data: [1, 2, 3]
        });
    </script>
</body>

</html>

Provide a warning message layer

Example situation
A visual chart shows a scatter plot and a violin plot. While chart2music supports scatter plots, it doesn't support violin plots. I want to make the scatter plot accessible to users, but I don't want to hide the fact that there's a violin plot also present in the visuals.

Request
There should be a way to communicate inaccessible layers. Maybe the user is told that there are 2 layers. They go to the first one, a scatter plot, and can navigate as normal. They navigate to the second layer, like "Chart contains unsupported chart type: violin plot.", perhaps optionally with some kind of alt text.

Cannot reproduce minimal example

Thanks for working on and releasing such a great open-source project!

I was attempting to reproduce a minimal example using the instruction provided in readme. However, the following code does not produce any sonification layers. Could you please help me better understand what's wrong with my code below?

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <script src="https://cdn.jsdelivr.net/npm/chart2music"></script>
</head>

<body>

    <img src="mychart.png" id="MyChart" />

    <script>
        c2mChart({
            type: "bar",
            element: document.getElementById("MyChart"),
            data: [1, 2, 3]
        });
    </script>
</body>

</html>

Bug with changing groups

Steps:

  1. Have a chart with 2 groups: A, B
  2. User focuses on group B
  3. Call setCategoryVisibility("A", false)
  4. User moves right

There are console errors.

Proposal: Add i18n + some translations.

Caption box is currently in english.

If it's amenable to you, I would be willing to add international support and could provide translations in german and spanish!

Would want approval before I start the work, it would be done over the course of months.

Add candlestick chart example

Please correct me if I am wrong, but there does not seem to be a candlestick chart example. It would be great if a sample chart could be added.

Suggestions for heatmaps and correlation matrices

I appreciate the new support for heatmaps and correlation matrices. I would like to open a discussion for the following items:

  • Add a vertical autoplay feature.

Horizontal autoplay is possible with ctrl+shift+left/right arrows; there is no way to autoswipe cells in a vertical direction.

  • Consider up/down arrows to jump between different rows.

I understand that you borrowed the same concepts using pg-up/down keys from multi-line charts and grouped box plot. Given that heatmaps and matrices are grid form and well-mapped with standard arrow key layout, wouldn't it be more cognitively accessible and easier to press? In heatmap consisting of two categorical variables, both horizontal and vertical navigations are changing groups anyway. I think there is no strong reason to keep using pg up/down keys only for vertical nav given this characteristic.

New chart type: Treemap

DataVizCatalogue lists the following chart types as representing hierarchies through proportions:

Note that DataVizCatalogue also lists tree diagrams as a way of representing hierachies. However, since a tree diagram doesn't necessarily convey quantifiable data, it is excluded from this feature request

Data points for treemaps would contain:

  • X, optional, representing the order of the items. By default, it will be the index if not provided
  • Y, required, matching the visual of size/volume
  • Y2, optional, matching the visual of color gradient
  • Label, optional
  • toGroup: optional, the name of the group to drill down to. By default, if it has a label and that label matches the name of the other group, the label will double as the toGroup if one isn't specified

Interactions:

  • Left/right arrow keys would navigate from biggest to smallest within the group
  • Alt+Down, Alt+Up would drill up or down between hierarchies

Here's how this chart.js example treemap would be represented

{
    type: "treemap",
    axes: {
        y: {
            label: "Area",
            format: (value) => value.toLocaleString() + " km2"
        }
    },
    data: {
        Region: [
            {label: "West", y: 4851705},
            {label: "South", y: 2383947},
            {label: "Midwest", y: 2128257},
            {label: "Northeast", y: 469615},
        ],
        West: [
            {label: "Pacific", y: 2615082},
            {label: "Mountain", y: 2236623},
        ],
        South: [
            {label: "West South Central", y: 1150090},
            {label: "South Atlantic", y: 758843},
            {label: "East South Central", y: 475014}
        ],
        Midwest: [
            {label: "West North Central", y: 1347716},
            {label: "East North Central", y: 780541}
        ],
        Northeast: [
            {label: "Middle Atlantic", y: 283168},
            {label: "New England", y: 186447},
        ],
        Pacific: [
            {label: "Alaska", y: 1723337},
            {label: "California", y: 423972},
            {label: "Oregon", y: 254799},
            {label: "Washington", y: 184661},
            {label: "Hawaii", y: 28313}
        ],
        Mountain: [
            {label: "Montana", y: 380831},
            {label: "New Mexico", y: 314917},
            {label: "Arizona", y: 295234},
            {label: "Nevada", y: 286380},
            {label: "Colorado", y: 269601},
            {label: "Utah", y: 219882},
            {label: "Wyoming", y: 253335},
            {label: "Idaho", y: 216443}
        ],
        "West South Central": [
            {label: "Texas", y: 695662},
            {label: "Oklahoma", y: 181037},
            {label: "Arkansas", y: 137732},
            {label: "Louisiana", y: 135659}
        ],
        "South Atlantic": [
            {label: "Florida", y: 170312},
            {label: "Georgia", y: 153910},
            {label: "North Carolina", y: 139391},
            {label: "Virginia", y: 110787},
            {label: "South Carolina", y: 82933},
            {label: "West Virginia", y: 62756},
            {label: "Maryland", y: 32131},
            {label: "Delaware", y: 6446}
        ],
        "East South Central": [
            {label: "Alabama", y: 135767},
            {label: "Mississippi", y: 125438},
            {label: "Tennessee", y: 109153},
            {label: "Kentucky", y: 104656}
        ],
        "West North Central": [
            {label: "Minnesota", y: 225163},
            {label: "Kansas", y: 213100},
            {label: "Nebraska", y: 200330},
            {label: "South Dakota", y: 199729},
            {label: "North Dakota", y: 183108},
            {label: "Missouri", y: 180540},
            {label: "Iowa", y: 145746}
        ],
        "East North Central": [
            {label: "Michigan", y: 250487},
            {label: "Wisconsin", y: 169635},
            {label: "Illinois", y: 149995},
            {label: "Ohio", y: 116098},
            {label: "Indiana", y: 94326}
        ],
        "Middle Atlantic": [
            {label: "New York", y: 141297},
            {label: "Pennsylvania", y: 119280}
            {label: "New Jersey", y: 22591}
        ],
        "New England": [
            {label: "Maine", y: 91633},
            {label: "Massachusetts", y: 27336},
            {label: "Vermont", y: 24906},
            {label: "New Hampshire", y: 24214},
            {label: "Connecticut", y: 14357},
            {label: "Rhode Island", y: 4001}
        ]
    }
}

The first group, "Region", will be the first-shown label. When you drill down on the label "South", you'll move to the group "South".

New Feature: Audio Engine: Resonance

Expand the playDataPoint function to include a resonance value. resonance will be a number between 0 and 1, indicating a percent of the maximum amount of resonance that can be played. By default, the value is 0.

When this is included, the data point should have resonance/reverb/echo-y version of the data point being played. This will be used in bubble plots and area bar charts to represent the volume of the data point.

We expect users to get rough, estimated vibes from this sonification. We want users to be able to tell if something is "a lot", "a little", or "a medium amount". The user does not need to be able to distinguish small differences between data points.

Tethering C2M with SVG plot dynamically

When SVG file contains manipulable DOM tree, is it possible to embed C2M's keyboard and visual highlight events into SVG elements?

For example, the following SVG barplot has 7 bars denoted with <rect> tag and some id patterns. I can retrieve them via svg.querySelectorAll("g[id^='geom_rect.'] rect");.

I want to dynamically and visually highlight each bar element that moves along with C2M sonification from left to right. I have done this by using our team's own js module, but I am currently looking for an integrated solution.

barplot

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="730.19px" height="730.19px" viewBox="0 0 730.19 730.19" version="1.1">
  <metadata xmlns:gridsvg="http://www.stat.auckland.ac.nz/~paul/R/gridSVG/">
    <gridsvg:generator name="gridSVG" version="1.7-4" time="2022-08-07 21:32:46" />
    <gridsvg:argument name="name" value="barplot.svg" />
    <gridsvg:argument name="exportCoords" value="none" />
    <gridsvg:argument name="exportMappings" value="none" />
    <gridsvg:argument name="exportJS" value="none" />
    <gridsvg:argument name="res" value="72" />
    <gridsvg:argument name="prefix" value="" />
    <gridsvg:argument name="addClasses" value="FALSE" />
    <gridsvg:argument name="indent" value="TRUE" />
    <gridsvg:argument name="htmlWrapper" value="FALSE" />
    <gridsvg:argument name="usePaths" value="vpPaths" />
    <gridsvg:argument name="uniqueNames" value="TRUE" />
    <gridsvg:separator name="id.sep" value="." />
    <gridsvg:separator name="gPath.sep" value="::" />
    <gridsvg:separator name="vpPath.sep" value="::" />
  </metadata>
  <g transform="translate(0, 730.19) scale(1, -1)">
    <g id="gridSVG" fill="rgb(255,255,255)" stroke="rgb(0,0,0)" stroke-dasharray="none" stroke-width="0.75" font-size="12" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" opacity="1" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
      <g id="layout.1">
        <g id="layout.2">
          <defs>
            <clipPath id="layout::background.1-9-12-1.1.clipPath">
              <rect x="0" y="0" width="730.19" height="730.19" fill="none" stroke="none" />
            </clipPath>
          </defs>
          <g id="layout::background.1-9-12-1.1" clip-path="url(#layout::background.1-9-12-1.1.clipPath)">
            <g id="background.1-9-12-1.1">
              <rect id="background.1-9-12-1.1.1" x="0" y="0" width="730.19" height="730.19" transform="" stroke-width="1.07" stroke="rgb(255,255,255)" fill="rgb(255,255,255)" stroke-dasharray="none" stroke-opacity="1" fill-opacity="1" />
            </g>
          </g>
          <defs>
            <clipPath id="layout::panel.7-5-7-5.1.clipPath">
              <rect x="33.48" y="31.91" width="691.24" height="692.8" fill="none" stroke="none" />
            </clipPath>
          </defs>
          <g id="layout::panel.7-5-7-5.1" clip-path="url(#layout::panel.7-5-7-5.1.clipPath)">
            <g id="panel.7-5-7-5.1">
              <g id="grill.gTree.67.1">
                <g id="panel.background..rect.60.1">
                  <rect id="panel.background..rect.60.1.1" x="33.48" y="31.91" width="691.24" height="692.8" transform="" stroke-width="1.07" stroke="none" fill="rgb(235,235,235)" stroke-dasharray="none" stroke-opacity="0" fill-opacity="1" />
                </g>
                <g id="panel.grid.minor.y..polyline.62.1">
                  <polyline id="panel.grid.minor.y..polyline.62.1.1" points="33.48,164.99 724.72,164.99" stroke="rgb(255,255,255)" fill="none" stroke-width="0.53" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                  <polyline id="panel.grid.minor.y..polyline.62.1.2" points="33.48,368.15 724.72,368.15" stroke="rgb(255,255,255)" fill="none" stroke-width="0.53" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                  <polyline id="panel.grid.minor.y..polyline.62.1.3" points="33.48,571.32 724.72,571.32" stroke="rgb(255,255,255)" fill="none" stroke-width="0.53" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                </g>
                <g id="panel.grid.major.y..polyline.64.1">
                  <polyline id="panel.grid.major.y..polyline.64.1.1" points="33.48,63.4 724.72,63.4" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                  <polyline id="panel.grid.major.y..polyline.64.1.2" points="33.48,266.57 724.72,266.57" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                  <polyline id="panel.grid.major.y..polyline.64.1.3" points="33.48,469.74 724.72,469.74" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                  <polyline id="panel.grid.major.y..polyline.64.1.4" points="33.48,672.91 724.72,672.91" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                </g>
                <g id="panel.grid.major.x..polyline.66.1">
                  <polyline id="panel.grid.major.x..polyline.66.1.1" points="91.08,31.91 91.08,724.72" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                  <polyline id="panel.grid.major.x..polyline.66.1.2" points="187.09,31.91 187.09,724.72" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                  <polyline id="panel.grid.major.x..polyline.66.1.3" points="283.09,31.91 283.09,724.72" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                  <polyline id="panel.grid.major.x..polyline.66.1.4" points="379.1,31.91 379.1,724.72" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                  <polyline id="panel.grid.major.x..polyline.66.1.5" points="475.1,31.91 475.1,724.72" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                  <polyline id="panel.grid.major.x..polyline.66.1.6" points="571.11,31.91 571.11,724.72" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                  <polyline id="panel.grid.major.x..polyline.66.1.7" points="667.11,31.91 667.11,724.72" stroke="rgb(255,255,255)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                </g>
              </g>
              <g id="geom_rect.rect.56.1">
                <rect id="geom_rect.rect.56.1.1" x="47.88" y="63.4" width="86.4" height="50.79" transform="" stroke="none" fill="rgb(89,89,89)" stroke-width="1.07" stroke-dasharray="none" stroke-linejoin="miter" stroke-linecap="square" stroke-opacity="0" fill-opacity="1" />
                <rect id="geom_rect.rect.56.1.2" x="143.88" y="63.4" width="86.4" height="477.45" transform="" stroke="none" fill="rgb(89,89,89)" stroke-width="1.07" stroke-dasharray="none" stroke-linejoin="miter" stroke-linecap="square" stroke-opacity="0" fill-opacity="1" />
                <rect id="geom_rect.rect.56.1.3" x="239.89" y="63.4" width="86.4" height="416.5" transform="" stroke="none" fill="rgb(89,89,89)" stroke-width="1.07" stroke-dasharray="none" stroke-linejoin="miter" stroke-linecap="square" stroke-opacity="0" fill-opacity="1" />
                <rect id="geom_rect.rect.56.1.4" x="335.89" y="63.4" width="86.4" height="111.74" transform="" stroke="none" fill="rgb(89,89,89)" stroke-width="1.07" stroke-dasharray="none" stroke-linejoin="miter" stroke-linecap="square" stroke-opacity="0" fill-opacity="1" />
                <rect id="geom_rect.rect.56.1.5" x="431.9" y="63.4" width="86.4" height="335.23" transform="" stroke="none" fill="rgb(89,89,89)" stroke-width="1.07" stroke-dasharray="none" stroke-linejoin="miter" stroke-linecap="square" stroke-opacity="0" fill-opacity="1" />
                <rect id="geom_rect.rect.56.1.6" x="527.9" y="63.4" width="86.4" height="355.54" transform="" stroke="none" fill="rgb(89,89,89)" stroke-width="1.07" stroke-dasharray="none" stroke-linejoin="miter" stroke-linecap="square" stroke-opacity="0" fill-opacity="1" />
                <rect id="geom_rect.rect.56.1.7" x="623.91" y="63.4" width="86.4" height="629.82" transform="" stroke="none" fill="rgb(89,89,89)" stroke-width="1.07" stroke-dasharray="none" stroke-linejoin="miter" stroke-linecap="square" stroke-opacity="0" fill-opacity="1" />
              </g>
            </g>
          </g>
          <g id="layout::spacer.8-6-8-6.1" />
          <g id="layout::spacer.8-4-8-4.1" />
          <g id="layout::spacer.6-6-6-6.1" />
          <g id="layout::spacer.6-4-6-4.1" />
          <g id="layout::axis-t.6-5-6-5.1" />
          <g id="layout::axis-l.7-4-7-4.1">
            <g id="layout::axis-l.7-4-7-4::GRID.VP.16.1">
              <g id="axis-l.7-4-7-4.1">
                <g id="layout::axis-l.7-4-7-4::GRID.VP.16::axis.1">
                  <g id="axis.1">
                    <g id="layout::axis-l.7-4-7-4::GRID.VP.16::axis::axis.1-1-1-1.1">
                      <g id="layout::axis-l.7-4-7-4::GRID.VP.16::axis::axis.1-1-1-1::GRID.VP.14.1" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" stroke-opacity="1" font-weight="normal" font-style="normal">
                        <g id="layout::axis-l.7-4-7-4::GRID.VP.16::axis::axis.1-1-1-1::GRID.VP.14::GRID.VP.15.1">
                          <g id="axis.1-1-1-1.1">
                            <g id="GRID.text.74.1">
                              <g id="GRID.text.74.1.1" transform="translate(28.55, 63.4)" stroke-width="0.1">
                                <g id="GRID.text.74.1.1.scale" transform="scale(1, -1)">
                                  <text x="0" y="0" id="GRID.text.74.1.1.text" text-anchor="end" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
                                    <tspan id="GRID.text.74.1.1.tspan.1" dy="3.23" x="0">0</tspan>
                                  </text>
                                </g>
                              </g>
                              <g id="GRID.text.74.1.2" transform="translate(28.55, 266.57)" stroke-width="0.1">
                                <g id="GRID.text.74.1.2.scale" transform="scale(1, -1)">
                                  <text x="0" y="0" id="GRID.text.74.1.2.text" text-anchor="end" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
                                    <tspan id="GRID.text.74.1.2.tspan.1" dy="3.23" x="0">20</tspan>
                                  </text>
                                </g>
                              </g>
                              <g id="GRID.text.74.1.3" transform="translate(28.55, 469.74)" stroke-width="0.1">
                                <g id="GRID.text.74.1.3.scale" transform="scale(1, -1)">
                                  <text x="0" y="0" id="GRID.text.74.1.3.text" text-anchor="end" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
                                    <tspan id="GRID.text.74.1.3.tspan.1" dy="3.23" x="0">40</tspan>
                                  </text>
                                </g>
                              </g>
                              <g id="GRID.text.74.1.4" transform="translate(28.55, 672.91)" stroke-width="0.1">
                                <g id="GRID.text.74.1.4.scale" transform="scale(1, -1)">
                                  <text x="0" y="0" id="GRID.text.74.1.4.text" text-anchor="end" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
                                    <tspan id="GRID.text.74.1.4.tspan.1" dy="3.23" x="0">60</tspan>
                                  </text>
                                </g>
                              </g>
                            </g>
                          </g>
                        </g>
                      </g>
                    </g>
                    <g id="layout::axis-l.7-4-7-4::GRID.VP.16::axis::axis.1-2-1-2.1">
                      <g id="axis.1-2-1-2.1">
                        <polyline id="axis.1-2-1-2.1.1" points="30.74,63.4 33.48,63.4" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                        <polyline id="axis.1-2-1-2.1.2" points="30.74,266.57 33.48,266.57" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                        <polyline id="axis.1-2-1-2.1.3" points="30.74,469.74 33.48,469.74" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                        <polyline id="axis.1-2-1-2.1.4" points="30.74,672.91 33.48,672.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                      </g>
                    </g>
                  </g>
                </g>
              </g>
            </g>
          </g>
          <g id="layout::axis-r.7-6-7-6.1" />
          <g id="layout::axis-b.8-5-8-5.1">
            <g id="layout::axis-b.8-5-8-5::GRID.VP.13.1">
              <g id="axis-b.8-5-8-5.1">
                <g id="layout::axis-b.8-5-8-5::GRID.VP.13::axis.1">
                  <g id="axis.2">
                    <g id="layout::axis-b.8-5-8-5::GRID.VP.13::axis::axis.1-1-1-1.1">
                      <g id="axis.1-1-1-1.2">
                        <polyline id="axis.1-1-1-1.2.1" points="91.08,29.17 91.08,31.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                        <polyline id="axis.1-1-1-1.2.2" points="187.09,29.17 187.09,31.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                        <polyline id="axis.1-1-1-1.2.3" points="283.09,29.17 283.09,31.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                        <polyline id="axis.1-1-1-1.2.4" points="379.1,29.17 379.1,31.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                        <polyline id="axis.1-1-1-1.2.5" points="475.1,29.17 475.1,31.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                        <polyline id="axis.1-1-1-1.2.6" points="571.11,29.17 571.11,31.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                        <polyline id="axis.1-1-1-1.2.7" points="667.11,29.17 667.11,31.91" stroke="rgb(51,51,51)" fill="none" stroke-width="1.07" stroke-dasharray="none" stroke-linecap="butt" stroke-opacity="1" fill-opacity="1" />
                      </g>
                    </g>
                    <g id="layout::axis-b.8-5-8-5::GRID.VP.13::axis::axis.2-1-2-1.1">
                      <g id="layout::axis-b.8-5-8-5::GRID.VP.13::axis::axis.2-1-2-1::GRID.VP.11.1" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" stroke-opacity="1" font-weight="normal" font-style="normal">
                        <g id="layout::axis-b.8-5-8-5::GRID.VP.13::axis::axis.2-1-2-1::GRID.VP.11::GRID.VP.12.1">
                          <g id="axis.2-1-2-1.1">
                            <g id="GRID.text.70.1">
                              <g id="GRID.text.70.1.1" transform="translate(91.08, 26.98)" stroke-width="0.1">
                                <g id="GRID.text.70.1.1.scale" transform="scale(1, -1)">
                                  <text x="0" y="0" id="GRID.text.70.1.1.text" text-anchor="middle" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
                                    <tspan id="GRID.text.70.1.1.tspan.1" dy="6.46" x="0">2seater</tspan>
                                  </text>
                                </g>
                              </g>
                              <g id="GRID.text.70.1.2" transform="translate(187.09, 26.98)" stroke-width="0.1">
                                <g id="GRID.text.70.1.2.scale" transform="scale(1, -1)">
                                  <text x="0" y="0" id="GRID.text.70.1.2.text" text-anchor="middle" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
                                    <tspan id="GRID.text.70.1.2.tspan.1" dy="6.46" x="0">compact</tspan>
                                  </text>
                                </g>
                              </g>
                              <g id="GRID.text.70.1.3" transform="translate(283.09, 26.98)" stroke-width="0.1">
                                <g id="GRID.text.70.1.3.scale" transform="scale(1, -1)">
                                  <text x="0" y="0" id="GRID.text.70.1.3.text" text-anchor="middle" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
                                    <tspan id="GRID.text.70.1.3.tspan.1" dy="6.46" x="0">midsize</tspan>
                                  </text>
                                </g>
                              </g>
                              <g id="GRID.text.70.1.4" transform="translate(379.1, 26.98)" stroke-width="0.1">
                                <g id="GRID.text.70.1.4.scale" transform="scale(1, -1)">
                                  <text x="0" y="0" id="GRID.text.70.1.4.text" text-anchor="middle" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
                                    <tspan id="GRID.text.70.1.4.tspan.1" dy="6.46" x="0">minivan</tspan>
                                  </text>
                                </g>
                              </g>
                              <g id="GRID.text.70.1.5" transform="translate(475.1, 26.98)" stroke-width="0.1">
                                <g id="GRID.text.70.1.5.scale" transform="scale(1, -1)">
                                  <text x="0" y="0" id="GRID.text.70.1.5.text" text-anchor="middle" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
                                    <tspan id="GRID.text.70.1.5.tspan.1" dy="6.46" x="0">pickup</tspan>
                                  </text>
                                </g>
                              </g>
                              <g id="GRID.text.70.1.6" transform="translate(571.11, 26.98)" stroke-width="0.1">
                                <g id="GRID.text.70.1.6.scale" transform="scale(1, -1)">
                                  <text x="0" y="0" id="GRID.text.70.1.6.text" text-anchor="middle" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
                                    <tspan id="GRID.text.70.1.6.tspan.1" dy="6.46" x="0">subcompact</tspan>
                                  </text>
                                </g>
                              </g>
                              <g id="GRID.text.70.1.7" transform="translate(667.11, 26.98)" stroke-width="0.1">
                                <g id="GRID.text.70.1.7.scale" transform="scale(1, -1)">
                                  <text x="0" y="0" id="GRID.text.70.1.7.text" text-anchor="middle" font-size="8.8" stroke="rgb(77,77,77)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(77,77,77)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
                                    <tspan id="GRID.text.70.1.7.tspan.1" dy="6.46" x="0">suv</tspan>
                                  </text>
                                </g>
                              </g>
                            </g>
                          </g>
                        </g>
                      </g>
                    </g>
                  </g>
                </g>
              </g>
            </g>
          </g>
          <g id="layout::xlab-t.5-5-5-5.1" />
          <g id="layout::xlab-b.9-5-9-5.1">
            <g id="layout::xlab-b.9-5-9-5::GRID.VP.17.1" font-size="11" stroke="rgb(0,0,0)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" stroke-opacity="1" font-weight="normal" font-style="normal">
              <g id="layout::xlab-b.9-5-9-5::GRID.VP.17::GRID.VP.18.1">
                <g id="xlab-b.9-5-9-5.1">
                  <g id="GRID.text.78.1">
                    <g id="GRID.text.78.1.1" transform="translate(379.1, 15.8)" stroke-width="0.1">
                      <g id="GRID.text.78.1.1.scale" transform="scale(1, -1)">
                        <text x="0" y="0" id="GRID.text.78.1.1.text" text-anchor="middle" font-size="11" stroke="rgb(0,0,0)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(0,0,0)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
                          <tspan id="GRID.text.78.1.1.tspan.1" dy="7.9" x="0">class</tspan>
                        </text>
                      </g>
                    </g>
                  </g>
                </g>
              </g>
            </g>
          </g>
          <g id="layout::ylab-l.7-3-7-3.1">
            <g id="layout::ylab-l.7-3-7-3::GRID.VP.19.1" font-size="11" stroke="rgb(0,0,0)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" stroke-opacity="1" font-weight="normal" font-style="normal">
              <g id="layout::ylab-l.7-3-7-3::GRID.VP.19::GRID.VP.20.1">
                <g id="ylab-l.7-3-7-3.1">
                  <g id="GRID.text.81.1">
                    <g id="GRID.text.81.1.1" transform="translate(5.48, 378.31)" stroke-width="0.1">
                      <g id="GRID.text.81.1.1.scale" transform="scale(1, -1)">
                        <text x="0" y="0" id="GRID.text.81.1.1.text" transform="rotate(-90)" text-anchor="middle" font-size="11" stroke="rgb(0,0,0)" font-family="Helvetica, Arial, FreeSans, Liberation Sans, Nimbus Sans L, sans-serif" fill="rgb(0,0,0)" stroke-opacity="1" fill-opacity="1" font-weight="normal" font-style="normal">
                          <tspan id="GRID.text.81.1.1.tspan.1" dy="7.9" x="0">count</tspan>
                        </text>
                      </g>
                    </g>
                  </g>
                </g>
              </g>
            </g>
          </g>
          <g id="layout::ylab-r.7-7-7-7.1" />
          <g id="layout::subtitle.4-5-4-5.1" />
          <g id="layout::title.3-5-3-5.1" />
          <g id="layout::caption.10-5-10-5.1" />
          <g id="layout::tag.2-2-2-2.1" />
        </g>
      </g>
    </g>
  </g>
</svg>

Ability to customize the stat range combinations for band, candlestick, and boxplot

For band, candlestick, and boxplot, we can either hear one stat separately or all stats altogether. However, I would like to customize the range chord. For example, I would like to hear open and close for candlestick chart vs. high and low. It would be great if users could customize the stat range combination following their needs.

Consider representing data patterns in unicode braille

this technique has been already demonstrated in other solutions, such as accessible graphs as well as brailleChart.

  • Line chart, candle plot, bar plot and histogram can use line-type braille pattern like ⣀⡠⠤⠔⠒⠊⠉

  • Boxplot: We may be able to represent boxplot pattern in braille unicode like this. I created this randomly, but this can show you my ideas (this has three outliers): ⠒⠒⠒⠿⠇⠿⠿⠒⠒⠒⠒ ⠠⠈⠠

  • Heat map braille pattern: we could  display different dot patterns to represent different colors row by row just like below:⠿⠿⠿⠿⠿⠿⠿⠀⠇⠇⠇⠇⠇⠇⠇⠀⠣⠣⠣⠣⠣⠣⠣⠀⠭⠭⠭⠭⠭⠭⠭

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.