javascriptvisualizationapache-echarts

Echarts heatmap decal patterns


I'm trying to have an accessibility decal patterns-enabled discrete values heatmap in Echarts. I've tried a lot of syntaxes & browsed through the doc and the Web and here is the code sticking most to what the documentation states, according to me:

Echarts examples editor

We can see here this piece of code:

aria: {
        decal: {
          show: true,
          decals: [{symbol: ['circle', 'rect', 'triangle']}]
        }
      }

Unfortunately, there is only one decal pattern whatever the background colour (hence value) of the cell is, which defeats the principle of decal patterns by itself.

I've tried to read this (amongst other things): Echarts doc but I can't figure out what I'm missing.

Any ideas?

I'd like to have a different decal pattern for each group of values of the heatmap: same cell colour = same cell pattern. It's for colour-blind people. I use Echarts 5.4.3 and can go to 5.5 if needed.


Solution

  • Disclaimer - I am not an eCharts user. The suggestion provided below is a result of fiddling about the eCharts playground, going through their documentation, and looking at the differences between working decal code snippets and your provided code.

    Notes will be provided below the snippet.

    ECharts 5.5 is used in this example.

    var dom = document.getElementById('chart-container');
    var myChart = echarts.init(dom, null, {
      renderer: 'canvas',
      useDirtyRect: false
    });
    var app = {};
    
    var option;
    
    function createDecal(color, symbol,symbolSize) {
      return {
        color: color,
        symbol: symbol,
        symbolSize: symbolSize,
        dashArrayX: 6,
        dashArrayY: 7
      };
    }
    
    const vect  = 'path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z';
    const img = 'image://https://placehold.co/10x10/00F/000000';
    const svg = 'image://https://www.svgrepo.com/show/434342/sun.svg';
    const b64 = 'image://data:image/xml+svg,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjwhLS0gVXBsb2FkZWQgdG86IFNWRyBSZXBvLCB3d3cuc3ZncmVwby5jb20sIEdlbmVyYXRvcjogU1ZHIFJlcG8gTWl4ZXIgVG9vbHMgLS0+DQo8c3ZnIGZpbGw9IiMwMDAwMDAiIHdpZHRoPSI4MDBweCIgaGVpZ2h0PSI4MDBweCIgdmlld0JveD0iMCAwIDMyIDMyIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+DQo8dGl0bGU+c25vd2ZsYWtlPC90aXRsZT4NCjxwYXRoIGQ9Ik0yOC41MjcgMTcuMDEzbC00LjcyMyAyLjYyNi02LjMwMy0zLjYzOSA2LjI5OS0zLjYzNyA0LjczNSAyLjYyNWMwLjEwNSAwLjA1OSAwLjIzIDAuMDk0IDAuMzYzIDAuMDk0IDAuNDE0IDAgMC43NS0wLjMzNiAwLjc1LTAuNzUgMC0wLjI4MS0wLjE1NC0wLjUyNi0wLjM4My0wLjY1NGwtMC4wMDQtMC4wMDItMy45NDYtMi4xODggMy4xODUtMS44MzljMC4yMzEtMC4xMzEgMC4zODUtMC4zNzUgMC4zODUtMC42NTUgMC0wLjQxNC0wLjMzNi0wLjc1LTAuNzUtMC43NS0wLjE0MiAwLTAuMjc1IDAuMDQwLTAuMzg4IDAuMTA4bDAuMDAzLTAuMDAyLTMuMTgyIDEuODM3IDAuMDcyLTQuNTA5YzAtMC4wMDMgMC0wLjAwNyAwLTAuMDExIDAtMC40MS0wLjMyOS0wLjc0NC0wLjczOC0wLjc1MWgtMC4wMDFjLTAuNDA5IDAuMDEwLTAuNzM5IDAuMzMyLTAuNzYyIDAuNzM2bC0wIDAuMDAyLTAuMDg3IDUuNDA2LTYuMzA0IDMuNjM5di03LjI3Nmw0LjY0My0yLjc4MmMwLjIxOC0wLjEzNCAwLjM2Mi0wLjM3MSAwLjM2Mi0wLjY0MiAwLTAuNDE0LTAuMzM2LTAuNzUtMC43NS0wLjc1LTAuMTQxIDAtMC4yNzMgMC4wMzktMC4zODUgMC4xMDZsMC4wMDMtMC4wMDItMy44NzMgMi4zMnYtMy42NzZjMC0wLjQxNC0wLjMzNi0wLjc1LTAuNzUtMC43NXMtMC43NSAwLjMzNi0wLjc1IDAuNzV2MCAzLjY3NWwtMy44NjQtMi4zMjFjLTAuMTEtMC4wNjctMC4yNDMtMC4xMDctMC4zODYtMC4xMDctMC40MTQgMC0wLjc0OSAwLjMzNi0wLjc0OSAwLjc0OSAwIDAuMjcxIDAuMTQ0IDAuNTA5IDAuMzYgMC42NDFsMC4wMDMgMC4wMDIgNC42MzYgMi43ODR2Ny4yNzdsLTYuMzAyLTMuNjM4LTAuMDg4LTUuNDA5Yy0wLjAwNy0wLjQwOS0wLjM0LTAuNzM4LTAuNzUtMC43MzgtMC40MTQgMC0wLjc1IDAuMzM2LTAuNzUgMC43NSAwIDAuMDA0IDAgMC4wMDggMCAwLjAxMnYtMC4wMDFsMC4wNzMgNC41MTEtMy4xODMtMS44MzdjLTAuMTEtMC4wNjctMC4yNDMtMC4xMDYtMC4zODUtMC4xMDYtMC40MTQgMC0wLjc1IDAuMzM2LTAuNzUgMC43NSAwIDAuMjggMC4xNTQgMC41MjQgMC4zODEgMC42NTNsMC4wMDQgMC4wMDIgMy4xODMgMS44MzgtMy45NDQgMi4xODZjLTAuMjMyIDAuMTMtMC4zODcgMC4zNzUtMC4zODcgMC42NTYgMCAwLjQxNCAwLjMzNiAwLjc1IDAuNzUgMC43NSAwLjEzMyAwIDAuMjU5LTAuMDM1IDAuMzY3LTAuMDk2bC0wLjAwNCAwLjAwMiA0LjczMy0yLjYyNCA2LjMgMy42MzgtNi4zIDMuNjM3LTQuNzMxLTIuNjI5Yy0wLjEwNS0wLjA1OS0wLjIzMS0wLjA5NC0wLjM2NC0wLjA5NC0wLjQxNCAwLTAuNzUgMC4zMzYtMC43NSAwLjc1IDAgMC4yOCAwLjE1NCAwLjUyNSAwLjM4MiAwLjY1M2wwLjAwNCAwLjAwMiAzLjk0NCAyLjE5NC0zLjE4MyAxLjgzOGMtMC4yMjYgMC4xMzItMC4zNzUgMC4zNzQtMC4zNzUgMC42NSAwIDAuNDE1IDAuMzM2IDAuNzUxIDAuNzUxIDAuNzUxIDAgMCAwIDAgMC4wMDEgMGgtMGMwLjEzOC0wLjAwMSAwLjI2Ni0wLjAzNyAwLjM3OC0wLjEwMmwtMC4wMDQgMC4wMDIgMy4xODMtMS44MzgtMC4wNzkgNC41MDZjLTAgMC4wMDQtMCAwLjAwOC0wIDAuMDEyIDAgMC40MSAwLjMyOCAwLjc0NCAwLjczNyAwLjc1MmgwLjAxM2MwLjQwOS0wIDAuNzQyLTAuMzI4IDAuNzUtMC43MzZ2LTAuMDAxbDAuMDk0LTUuNDA4IDYuMy0zLjYzOHY3LjI3NGwtNC42NDEgMi43ODhjLTAuMjIyIDAuMTMzLTAuMzY5IDAuMzcyLTAuMzY5IDAuNjQ2IDAgMC40MTQgMC4zMzYgMC43NSAwLjc1IDAuNzUgMC4xNDUgMCAwLjI4LTAuMDQxIDAuMzk1LTAuMTEybC0wLjAwMyAwLjAwMiAzLjg2Ny0yLjMyM3YzLjY3N2MwIDAuNDE0IDAuMzM2IDAuNzUgMC43NSAwLjc1czAuNzUtMC4zMzYgMC43NS0wLjc1djAtMy42NzVsMy44NjkgMi4zMTdjMC4xMDkgMC4wNjcgMC4yNDIgMC4xMDcgMC4zODQgMC4xMDcgMCAwIDAuMDAxIDAgMC4wMDEgMGgtMGMwLjQxNC0wLjAwMSAwLjc0OS0wLjMzNiAwLjc0OS0wLjc1IDAtMC4yNzItMC4xNDQtMC41MDktMC4zNjEtMC42NDFsLTAuMDAzLTAuMDAyLTQuNjM5LTIuNzc5di03LjI3OWw2LjI5OCAzLjYzNiAwLjA5NCA1LjQxNGMwLjAwOCAwLjQwOCAwLjM0MSAwLjczNiAwLjc1IDAuNzM2aDAuMDE0YzAuNDA4LTAuMDA4IDAuNzM2LTAuMzQxIDAuNzM2LTAuNzUgMC0wLjAwNS0wLTAuMDA5LTAtMC4wMTR2MC4wMDFsLTAuMDc5LTQuNTEyIDMuMTg2IDEuODRjMC4xMDcgMC4wNjMgMC4yMzcgMC4xIDAuMzc0IDAuMSAwLjI3NyAwIDAuNTE4LTAuMTQ5IDAuNjQ5LTAuMzcxbDAuMDAyLTAuMDA0YzAuMDYzLTAuMTA4IDAuMS0wLjIzNyAwLjEtMC4zNzUgMC0wLjI3Ny0wLjE1LTAuNTE4LTAuMzcyLTAuNjQ4bC0wLjAwNC0wLjAwMi0zLjE3OS0xLjgzNSAzLjkzNy0yLjE5YzAuMjMzLTAuMTMgMC4zODgtMC4zNzYgMC4zODgtMC42NTcgMC0wLjQxNS0wLjMzNi0wLjc1MS0wLjc1MS0wLjc1MS0wLjEzNSAwLTAuMjYyIDAuMDM2LTAuMzcyIDAuMDk4bDAuMDA0LTAuMDAyeiIvPg0KPC9zdmc+';
    const svgpath = 'path://M28.527 17.013l-4.723 2.626-6.303-3.639 6.299-3.637 4.735 2.625c0.105 0.059 0.23 0.094 0.363 0.094 0.414 0 0.75-0.336 0.75-0.75 0-0.281-0.154-0.526-0.383-0.654l-0.004-0.002-3.946-2.188 3.185-1.839c0.231-0.131 0.385-0.375 0.385-0.655 0-0.414-0.336-0.75-0.75-0.75-0.142 0-0.275 0.040-0.388 0.108l0.003-0.002-3.182 1.837 0.072-4.509c0-0.003 0-0.007 0-0.011 0-0.41-0.329-0.744-0.738-0.751h-0.001c-0.409 0.010-0.739 0.332-0.762 0.736l-0 0.002-0.087 5.406-6.304 3.639v-7.276l4.643-2.782c0.218-0.134 0.362-0.371 0.362-0.642 0-0.414-0.336-0.75-0.75-0.75-0.141 0-0.273 0.039-0.385 0.106l0.003-0.002-3.873 2.32v-3.676c0-0.414-0.336-0.75-0.75-0.75s-0.75 0.336-0.75 0.75v0 3.675l-3.864-2.321c-0.11-0.067-0.243-0.107-0.386-0.107-0.414 0-0.749 0.336-0.749 0.749 0 0.271 0.144 0.509 0.36 0.641l0.003 0.002 4.636 2.784v7.277l-6.302-3.638-0.088-5.409c-0.007-0.409-0.34-0.738-0.75-0.738-0.414 0-0.75 0.336-0.75 0.75 0 0.004 0 0.008 0 0.012v-0.001l0.073 4.511-3.183-1.837c-0.11-0.067-0.243-0.106-0.385-0.106-0.414 0-0.75 0.336-0.75 0.75 0 0.28 0.154 0.524 0.381 0.653l0.004 0.002 3.183 1.838-3.944 2.186c-0.232 0.13-0.387 0.375-0.387 0.656 0 0.414 0.336 0.75 0.75 0.75 0.133 0 0.259-0.035 0.367-0.096l-0.004 0.002 4.733-2.624 6.3 3.638-6.3 3.637-4.731-2.629c-0.105-0.059-0.231-0.094-0.364-0.094-0.414 0-0.75 0.336-0.75 0.75 0 0.28 0.154 0.525 0.382 0.653l0.004 0.002 3.944 2.194-3.183 1.838c-0.226 0.132-0.375 0.374-0.375 0.65 0 0.415 0.336 0.751 0.751 0.751 0 0 0 0 0.001 0h-0c0.138-0.001 0.266-0.037 0.378-0.102l-0.004 0.002 3.183-1.838-0.079 4.506c-0 0.004-0 0.008-0 0.012 0 0.41 0.328 0.744 0.737 0.752h0.013c0.409-0 0.742-0.328 0.75-0.736v-0.001l0.094-5.408 6.3-3.638v7.274l-4.641 2.788c-0.222 0.133-0.369 0.372-0.369 0.646 0 0.414 0.336 0.75 0.75 0.75 0.145 0 0.28-0.041 0.395-0.112l-0.003 0.002 3.867-2.323v3.677c0 0.414 0.336 0.75 0.75 0.75s0.75-0.336 0.75-0.75v0-3.675l3.869 2.317c0.109 0.067 0.242 0.107 0.384 0.107 0 0 0.001 0 0.001 0h-0c0.414-0.001 0.749-0.336 0.749-0.75 0-0.272-0.144-0.509-0.361-0.641l-0.003-0.002-4.639-2.779v-7.279l6.298 3.636 0.094 5.414c0.008 0.408 0.341 0.736 0.75 0.736h0.014c0.408-0.008 0.736-0.341 0.736-0.75 0-0.005-0-0.009-0-0.014v0.001l-0.079-4.512 3.186 1.84c0.107 0.063 0.237 0.1 0.374 0.1 0.277 0 0.518-0.149 0.649-0.371l0.002-0.004c0.063-0.108 0.1-0.237 0.1-0.375 0-0.277-0.15-0.518-0.372-0.648l-0.004-0.002-3.179-1.835 3.937-2.19c0.233-0.13 0.388-0.376 0.388-0.657 0-0.415-0.336-0.751-0.751-0.751-0.135 0-0.262 0.036-0.372 0.098l0.004-0.002z';
    const yetAnother = 'path://M136.71078,90.7149424 C135.038663,90.084817 133.319214,89.8204828 131.637995,89.8987366 C131.93792,88.5693311 132.022117,87.2371959 131.901965,85.9319035 C131.475516,81.1970909 128.414369,76.8944942 123.681104,75.0882862 C118.812669,73.2488659 113.532803,74.556888 110.072058,78.0014222 C111.44425,78.0132512 112.836467,78.2716709 114.184082,78.7876003 C120.385569,81.1311211 123.498145,88.0593162 121.156545,94.2582038 C120.289538,96.5421242 118.80038,98.4052027 116.960324,99.7405227 C113.796773,102.011704 109.591905,102.714169 105.683776,101.228711 C99.4827445,98.8915594 96.3669821,91.9606345 98.7113134,85.7581072 C99.0176102,84.9537305 99.4044636,84.2007647 99.8609505,83.4869258 L99.8545788,83.4869258 C99.8545788,83.4869258 99.8545788,83.4869258 99.8545788,83.4932953 C101.850742,80.3754255 103.561544,76.9968612 104.927364,73.3990041 C115.528966,45.4164295 101.427934,14.127175 73.4261234,3.52605368 C45.4215819,-7.07142797 14.1333382,7.02472855 3.52900521,35.0104878 C0.629425582,42.6470623 -0.42099504,50.523403 0.149272308,58.1686218 C0.16110547,58.4206719 0.185226914,58.6786366 0.209348358,58.9366014 C2.47266801,84.9182432 19.2184117,108.595036 45.2413538,118.442737 C71.7121355,128.45559 100.448968,121.413198 119.352898,102.762395 C122.585626,99.6263266 127.465895,98.4657129 131.950208,100.160455 C137.34704,102.203699 140.39954,107.712861 139.559386,113.191995 C141.579216,111.769777 143.215378,109.750646 144.163851,107.256987 C146.676122,100.628613 143.33553,93.2204304 136.71078,90.7149424 ZZ';
    const pngb64 = 'image://data:image/png;base64,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';
    
    const symbols = [
        '', svgpath,'square',
        'circle', 'rect', vect,
        'triangle', 'arrow', 'pin',
        'diamond','roundRect',img,
        yetAnother,b64,pngb64
    ];
    
    let decals = [];
    
    symbols.forEach(function (item) {
      let color = 'black';
      let size = 1;
      if(item === svgpath) {
        size = 1.5;
      }
      
      decals.push(createDecal(color, item, size));
    });
    
    
    // prettier-ignore
    const hours = [
        '12a', '1a', '2a', '3a', '4a', '5a', '6a',
        '7a', '8a', '9a', '10a', '11a',
        '12p', '1p', '2p', '3p', '4p', '5p',
        '6p', '7p', '8p', '9p', '10p', '11p'
    ];
    // prettier-ignore
    const days = [
        'Saturday', 'Friday', 'Thursday',
        'Wednesday', 'Tuesday', 'Monday', 'Sunday'
    ];
    // prettier-ignore
    const data = [
        [0, 0, 5], [0, 1, 1], [0, 2, 0], [0, 3, 0], [0, 4, 0], [0, 5, 0],
        [0, 6, 0], [0, 7, 0], [0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 11, 2],
        [0, 12, 4], [0, 13, 1], [0, 14, 1], [0, 15, 3], [0, 16, 4], [0, 17, 6],
        [0, 18, 4], [0, 19, 4], [0, 20, 3], [0, 21, 3], [0, 22, 2], [0, 23, 5],
        [1, 0, 7], [1, 1, 0], [1, 2, 0], [1, 3, 0], [1, 4, 0], [1, 5, 0],
        [1, 6, 0], [1, 7, 0], [1, 8, 0], [1, 9, 0], [1, 10, 5], [1, 11, 2],
        [1, 12, 2], [1, 13, 6], [1, 14, 9], [1, 15, 11], [1, 16, 6], [1, 17, 7],
        [1, 18, 8], [1, 19, 12], [1, 20, 5], [1, 21, 5], [1, 22, 7], [1, 23, 2],
        [2, 0, 1], [2, 1, 1], [2, 2, 0], [2, 3, 0], [2, 4, 0], [2, 5, 0],
        [2, 6, 0], [2, 7, 0], [2, 8, 0], [2, 9, 0], [2, 10, 3], [2, 11, 2],
        [2, 12, 1], [2, 13, 9], [2, 14, 8], [2, 15, 10], [2, 16, 6], [2, 17, 5],
        [2, 18, 5], [2, 19, 5], [2, 20, 7], [2, 21, 4], [2, 22, 2], [2, 23, 4],
        [3, 0, 7], [3, 1, 3], [3, 2, 0], [3, 3, 0], [3, 4, 0], [3, 5, 0],
        [3, 6, 0], [3, 7, 0], [3, 8, 1], [3, 9, 0], [3, 10, 5], [3, 11, 4],
        [3, 12, 7], [3, 13, 14], [3, 14, 13], [3, 15, 12], [3, 16, 9], [3, 17, 5],
        [3, 18, 5], [3, 19, 10], [3, 20, 6], [3, 21, 4], [3, 22, 4], [3, 23, 1],
        [4, 0, 1], [4, 1, 3], [4, 2, 0], [4, 3, 0], [4, 4, 0], [4, 5, 1],
        [4, 6, 0], [4, 7, 0], [4, 8, 0], [4, 9, 2], [4, 10, 4], [4, 11, 4],
        [4, 12, 2], [4, 13, 4], [4, 14, 4], [4, 15, 14], [4, 16, 12], [4, 17, 1],
        [4, 18, 8], [4, 19, 5], [4, 20, 3], [4, 21, 7], [4, 22, 3], [4, 23, 0],
        [5, 0, 2], [5, 1, 1], [5, 2, 0], [5, 3, 3], [5, 4, 0], [5, 5, 0],
        [5, 6, 0], [5, 7, 0], [5, 8, 2], [5, 9, 0], [5, 10, 4], [5, 11, 1],
        [5, 12, 5], [5, 13, 10], [5, 14, 5], [5, 15, 7], [5, 16, 11], [5, 17, 6],
        [5, 18, 0], [5, 19, 5], [5, 20, 3], [5, 21, 4], [5, 22, 2], [5, 23, 0],
        [6, 0, 1], [6, 1, 0], [6, 2, 0], [6, 3, 0], [6, 4, 0], [6, 5, 0],
        [6, 6, 0], [6, 7, 0], [6, 8, 0], [6, 9, 0], [6, 10, 1], [6, 11, 0],
        [6, 12, 2], [6, 13, 1], [6, 14, 3], [6, 15, 4], [6, 16, 0], [6, 17, 0],
        [6, 18, 0], [6, 19, 0], [6, 20, 1], [6, 21, 2], [6, 22, 2], [6, 23, 6]]
        .map(function (item) {
    
      let icon = decals[item[2]];
      let myVal = item[2] || '-';
    
        return {
            value: [item[1], item[0], myVal],
            itemStyle: {
                decal: icon
            }
        };
    });
    
    option = {
        tooltip: {
            position: 'top'
        },
        grid: {
            height: '50%',
            top: '10%'
        },
        xAxis: {
            type: 'category',
            data: hours,
            splitArea: {
            show: true
            }
        },
        yAxis: {
            type: 'category',
            data: days,
            splitArea: {
                show: true
            }
        },
        aria: {
        enabled: true
        },
        series: [{
        name: 'Punch Card',
        type: 'heatmap',
        data: data,
        label: {
          show: true
        },
        emphasis: {
          itemStyle: {
            shadowBlur: 10,
            shadowColor: 'rgba(0, 0, 0, 0.5)'
          }
        }
      }],
        visualMap: {
        min: 0,
        max: 10,
        calculable: true,
        orient: 'horizontal',
        left: 'center',
        bottom: '15%'
        }
    };
    
    //console.log(data)
    
    if (option && typeof option === 'object') {
      myChart.setOption(option);
    }
    
    window.addEventListener('resize', myChart.resize);
    * {
      margin: 0;
      padding: 0;
    }
    #chart-container {
      position: relative;
      height: 100vh;
      overflow: hidden;
    }
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <title>Apache ECharts Demo</title>
    </head>
    <body>
      <div id="chart-container"></div>
      <script src="https://fastly.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js"></script>
    </body>
    </html>


    Notes

    I am using a few things to apply specific decals to specific values, and, in doing so, achieving your requirement - specific colour is tied to a specific decal (red = square, yellow = triangle, and so on).

    The function

    First, let's take a look at the createDecal function.

    function createDecal(color, symbol,symbolSize) {
        return {
            color: color,
            symbol: symbol,
            symbolSize: symbolSize,
            dashArrayX: 6,
            dashArrayY: 7
        };
    }
    

    The function itself is nothing special - it takes the provided colour, symbol, and the desired symbol size. Based on that, it's returning an object of decal properties. Though it's not really needed, I've included the dashArrayX and dashArrayY to demonstrate how you can control the distance between the symbols inside a decal, since without them, the symbols seemed to be too tiny, and playing around with their size gave results which I personally disliked. I discovered the use of dash arrays in the official documentation, when reading about decals. More on the dash arrays themselves (along with some code examples) can be found here. In case the link goes down:

    The basic pattern of the decal pattern is an infinite loop in the form of Pattern - Blank - Pattern - Blank - Pattern - Blank both horizontally and vertically, respectively. By setting the length of each pattern and blank, complex pattern effects can be achieved.

    dashArrayX controls the horizontal pattern pattern. When its value is of type number or number[], it is similar to SVG stroke-dasharray.

    • If it is of type number, it means that the pattern and the blank space are of this value respectively. For example, 5 means the pattern with width 5 is displayed first, then 5 pixels empty, then the pattern with width 5 is displayed...

    • In the case of number[] type, it means that the pattern and empty space are loops of an array of values. For example: [5, 10, 2, 6] means the pattern is 5 pixels wide, then 10 pixels empty, then the pattern is 2 pixels wide, then 6 pixels empty, then the pattern is 5 pixels wide...

    • If of type (number | number[])[], it means that each row is a loop with an array of values for the pattern and blank space. For example: [10, [2, 5]] means that the first line will be 10 pixels by 10 pixels and empty space, the second line will be 2 pixels by 2 pixels and empty space, and the third line will be 10 pixels by 10 pixels and empty space...

    The symbols

    Now, the function is called while I'm looping through an array of symbols, called... Well... symbols. The array is manually prefilled with symbols supported by eCharts:

    The symbol type of the decal. If it is in the type of string[], it means the symbols are used one by one.

    Icon types provided by ECharts includes 'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow', 'none'

    ... but I am also experimenting with images - both raster and vector, in their URL form, and in their base64 form, because:

    [...] It can be set to an image with 'image://url', in which URL is the link to an image, or dataURI of an image.

    [...] Icons can be set to arbitrary vector path via 'path://' in ECharts

    Some of these will seem not to be working when you test them on a smaller resolution (and it is something to think about, when your requirements are considered) - for example, in the SO snippet, and in eCharts, some of the images are simply not rendering. But, when viewed on CodePen, for example, the images load normally.

    The decals

    In any case, both the function and the symbols array are here to help us fill up the decals array of properties. I'm doing this inside the array mapping. There, I'm constructing an array of graph item objects, each of which has their own label, values, and their own styles:

        {
            value: [item[1], item[0], myVal],
            itemStyle: {
                decal: icon
            }
        }
    

    This setup was applied by experimenting on the solution I linked in the comments: Add pattern/decals to maps on echarts for single series . The keypoint is that every value has to have a separate styling, if you want them to be distinguishable for those who are unable to distinguish between the colours.

    You can also modify the logic within the mapping - you don't have to make apply a separate decal symbol to individual values. You could group them, instead. For example, if the current value is between so and so, apply symbol X, if it's betwen such and such, apply symbol Y, and so on.

    In any case, once you form your data array of graph entries, simply pass it on to the option as the value for the series key.