KLineChart icon indicating copy to clipboard operation
KLineChart copied to clipboard

Month and day based vertical/time grid

Open mationai opened this issue 3 years ago • 0 comments

It would be very nice if vertical/time grid is separated by month for daily data and by date for intraday data.

It's not difficult, here's the code I have in my lighter weight candlestick lib to do so by month (Feel free to use it).

chart.drawTimeGrid = () => {
  const { ctx, data, geometry, width, barWd, style } = chart
  const topPad = geometry.boxPrice.padding
  const btmPad = geometry.boxVolume.padding
  const barCnts = gen.barCountsByMonth(data, width)
  const lineWd = ctx.lineWidth

  for (let cnt of barCnts) {
    const x = (
      cnt===0 ? .5 :
      cnt===width ? width - .5 : 
      topPad.left + (cnt + 0.5) * barWd
    )
    if (x > width) {
      ctx.lineWidth = lineWd
      return
    }
    const isBorder = x===.5 || x===width - .5
    ctx.lineWidth = isBorder ? 1 : .5
    ctx.strokeStyle = style[isBorder ? 'colorBorder' : 'colorGrid']
    ctx.beginPath()
    ctx.moveTo(x, topPad.top - 2.5)
    ctx.lineTo(x, topPad.ht + btmPad.ht)
    ctx.stroke()
  }
  ctx.lineWidth = lineWd
}

const gen = {}
gen.barCountsByMonth = (data=[], width, borders=true) => {
  const res = borders ? [0] : []
  if (!data.length)
    return res
  let mo = getMonth(data[0])
  let cnt = 1
  let _mo
  for (let o of data.slice(2)) {
    cnt += 1
    _mo = getMonth(o)
    if (mo !== _mo) {
      mo = _mo
      res.push(cnt)
    }
  }
  if (borders)
    res.push(width)
  return res
}

const getMonth = (o={}) => {
  const date = o.date || o.timestamp || o.date || o.time || o.datetime || o.ts
  return (
    typeof(date)==='string' && o.date[4]==='-' ?  o.date.slice(5, 7)
    : new Date(date).getMonth()
  )
}

mationai avatar Jan 31 '22 03:01 mationai