echarts Possibility to create Horizon charts

r1wp621o  于 2022-10-26  发布在  Echarts
关注(0)|答案(3)|浏览(351)

What problem does this feature solve?

Add Horizon representation.

Examples :

What does the proposed API look like?

Create new serie type horizon to show correct representation

v8wbuo2f

v8wbuo2f1#

Hi! We've received your issue and please be patient to get responded. 🎉
The average response time is expected to be within one day for weekdays.

In the meanwhile, please make sure that it containsa minimum reproducible demoand necessaryimagesto illustrate. Otherwise, our committers will ask you to do so.

  • A minimum reproducible demo* should contain as little data and components as possible but can still illustrate your problem. This is the best way for us to reproduce it and solve the problem faster.

You may also check out the API and chart option to get the answer.

If you don't get helped for a long time (over a week) or have an urgent question to ask, you may also send an email to dev@echarts.apache.org . Please attach the issue link if it's a technical question.

If you are interested in the project, you may also subscribe our mailing list .

Have a nice day! 🍵

efzxgjgh

efzxgjgh2#

After research, It's not simply to create this using the renderItem function. I found only examples using rect . In this case I want to use line with area to draw my lines.

I used this article to understand how Horizon works : https://bernatgel.github.io/karyoploter_tutorial/Tutorial/PlotHorizon/PlotHorizon.html

I test to cut my serie in 3 positive/negative parts. It works fine if I want to show them in different serie. But in the case they are in the same serie, it's very complicated to do that.

Any help or example to do that ?

For now This is my tests :

let base = +new Date(1988, 9, 3);
let oneDay = 24 * 3600 * 1000;
let data = [[base, Math.random() * 300]];
for (let i = 1; i < 20000; i++) {
  let now = new Date((base += oneDay));
  data.push([+now, Math.round((Math.random() - 0.5) * 20 + data[i - 1][1])]);
}

// test horizon part 
const max = Math.max(...data.map(i => i[1]));
const min = Math.min(...data.map(i => i[1]));
const moreDelta = Math.max(Math.abs(max), Math.abs(min));
const sectionSize = moreDelta / 3;
const horizonSeries = {
  max3 : [],
  max2 : [],
  max1 : [],
  min1 : [],
  min2 : [],
  min3 : [],
};

data.forEach(item => {
  let palier = Math.floor(Math.abs(item[1]) / sectionSize);
  let section;

  if (palier >= 3) {
    palier = 2;
  }

  if (item[1] < 0) {
    section = `min${palier+1}`;
  } else {
    section = `max${palier+1}`;
  }

  horizonSeries[section].push([item[0], Math.abs(item[1])]);

  const sections = Object.keys(horizonSeries);

  sections.forEach(sectionName => {
    if (sectionName !== section) {
      horizonSeries[sectionName].push([item[0], null]);
    }
  })
}); 

console.log(max, min, moreDelta, sectionSize, horizonSeries);

option = {
  tooltip: {
    trigger: 'axis',
    position: function (pt) {
      return [pt[0], '10%'];
    }
  },
  title: {
    left: 'center',
    text: 'Large Ara Chart'
  },
  toolbox: {
    feature: {
      dataZoom: {
        yAxisIndex: 'none'
      },
      restore: {},
      saveAsImage: {}
    }
  },
  xAxis: {
    type: 'time',
    boundaryGap: false
  },
  yAxis: {
    type: 'value',
    boundaryGap: [0, '100%']
  },
  dataZoom: [
    {
      type: 'inside',
      start: 0,
      end: 20
    },
    {
      start: 0,
      end: 20
    }
  ],
  series: [
    // {
    //   name: 'Fake Data',
    //   type: 'line',
    //   smooth: true,
    //   symbol: 'none',
    //   areaStyle: {},
    //   data: data
    // }
    {
      name : 'max3',
      type : 'line',
      symbol: 'none',
      areaStyle: {},
      data : horizonSeries.max3,
    },
    {
      name : 'max2',
      type : 'line',
      symbol: 'none',
      areaStyle: {},
      data : horizonSeries.max2,
    },
    {
      name : 'max1',
      type : 'line',
      symbol: 'none',
      areaStyle: {},
      data : horizonSeries.max1,
    },
    {
      name : 'min1',
      type : 'line',
      symbol: 'none',areaStyle: {},
      data : horizonSeries.min1,
    },
    {
      name : 'min2',
      type : 'line',
      symbol: 'none',
      areaStyle: {},
      data : horizonSeries.min2,
    },
    {
      name : 'min3',
      type : 'line',
      symbol: 'none',
      areaStyle: {},
      data : horizonSeries.min3,
    }
  ]
};

And this is the render :

ojsjcaue

ojsjcaue3#

I continue my investigation. I draw correctly one serie of horizon (using 6 series in echarts) with this code :

let base = +new Date(1988, 9, 3);
let oneDay = 24 * 3600 * 1000;
let data = [[base, Math.random() * 300]];
for (let i = 1; i < 800; i++) {
  let now = new Date((base += oneDay));
  data.push([+now, Math.round((Math.random() - 0.5) * 20 + data[i - 1][1])]);
}

// test horizon part 
const max = Math.max(...data.map(i => i[1]));
const min = Math.min(...data.map(i => i[1]));
const moreDelta = Math.max(Math.abs(max), Math.abs(min));
const sectionSize = moreDelta / 3;
const horizonSeries = {
  max3 : [],
  max2 : [],
  max1 : [],
  min1 : [],
  min2 : [],
  min3 : [],
};

data.forEach((item, index) => {
  let palier = Math.floor(Math.abs(item[1]) / sectionSize);
  let negative = false;
  const sign = ['max', 'min'];

  if (palier >= 3) {
    palier = 2;
  }

  palier += 1;

  if (item[1] < 0) {
    negative = true;
  }

  for (let i = 1; i <= 3; ++i) {
    for (let selectedSign of sign) {
      if (selectedSign === 'max' && negative) {
        horizonSeries[`${selectedSign}${i}`].push([item[0], 0]);
        continue;
      }

      if (selectedSign === 'min' && !negative) {
        horizonSeries[`${selectedSign}${i}`].push([item[0], 0]);
        continue;
      }

      if (i > palier) {
        horizonSeries[`${selectedSign}${i}`].push([item[0], 0]);
        continue;
      }

      const value = Math.abs(item[1]);
      const palierValue = i * sectionSize;

      if (i === palier) {
        horizonSeries[`${selectedSign}${i}`].push([item[0], value]);
      } else if (value > palierValue) {
        horizonSeries[`${selectedSign}${i}`].push([item[0], palierValue]);
      }
    }
  }
}); 

console.log(max, min, moreDelta, sectionSize, horizonSeries);

option = {
  color : ['#1B5E20', '#0D47A1', '#4CAF50', '#2196F3', '#A5D6A7', '#90CAF9' ],
  tooltip: {
    trigger: 'axis',
    position: function (pt) {
      return [pt[0], '10%'];
    }
  },
  title: {
    left: 'center',
    text: 'Large Ara Chart'
  },
  xAxis: {
    type: 'time',
  },
  yAxis : {
    // type : 'category',
    // data : ['Serie 1']
  },
  series: [
    {
      name : 'max3',
      type : 'line',
      symbol: 'none',
      areaStyle: {},
      data : horizonSeries.max3.map(item => {
        return [item[0], item[1] ? item[1] - (sectionSize * 2) : 0];
      }),
    },
    {
      name : 'min3',
      type : 'line',
      symbol: 'none',
      areaStyle: {},
      data : horizonSeries.min3.map(item => {
        return [item[0], item[1] ? item[1] - (sectionSize * 2) : 0];
      }),
    },
    {
      name : 'max2',
      type : 'line',
      symbol: 'none',
      areaStyle: {},
      data : horizonSeries.max2.map(item => {
        return [item[0], item[1] ? item[1] - (sectionSize) : 0];
      }),
    },
    {
      name : 'min2',
      type : 'line',
      symbol: 'none',
      areaStyle: {},
      data : horizonSeries.min2.map(item => {
        return [item[0], item[1] ? item[1] - (sectionSize) : 0];
      }),
    },
    {
      name : 'max1',
      type : 'line',
      symbol: 'none',
      areaStyle: {},
      data : horizonSeries.max1,
    },
    {
      name : 'min1',
      type : 'line',
      symbol: 'none',areaStyle: {},
      data : horizonSeries.min1,
    },
  ]
};

Now I want to pass it in category type chart But, when I do that, the chart does not show and the tooltip want to show me all the values of all my series in one time (2000 * 6 is very big)

相关问题