# 引言

最近接到一个任务是通过 KLineChart✔️8.6.1 实现在一幅图上画两个合约的蜡烛图。研究 api 发现并没有通过配置实现的方法,于是联系作者沟通得知需要自己画图实现。于是有了本篇文章。
KLineChart.jpg

# 添加模版

let shortName = this.constant.periodTypeEnum.getNameByCode(this.klineType) + '    合约2:' + this.currentInstrumentId
this.chart.addTechnicalIndicatorTemplate({
  name: 'custom_candle_solid',
  shortName: shortName,
  precision: 2,
  bar: {
	upColor: '#EF5350',
	downColor: '#26A69A',
	noChangeColor: '#888889'
  },
  plots: [
	{ key: 'open', title: '开: ' },
	{ key: 'close', title: '收: ' },
	{ key: 'high', title: '高: ' },
	{ key: 'low', title: '低: ' }
  ],
  calcTechnicalIndicator: (dataList, { params, plots }) => {
	return dataList.map((kLineData, i) => {
	  return {
		instrumentId: kLineData.instrumentId,
		timestamp: getDateTime(new Date(kLineData.timestamp)),
		open: kLineData.open,
		close: kLineData.close,
		high: kLineData.high,
		low: kLineData.low
	  }
	})
  },
  render: ({ ctx, dataSource, viewport, styles, xAxis, yAxis }) => {
	// X 轴起始像素
	let x = xAxis.convertToPixel(0)
	dataSource.technicalIndicatorDataList.forEach(function (kLineData, i) {
	  let open = kLineData.open
	  let close = kLineData.close
	  let high = kLineData.high
	  let low = kLineData.low
	  // 给蜡烛柱设置颜色
	  if (close > open) { // 涨
		ctx.strokeStyle = '#EF5350'
		ctx.fillStyle = '#EF5350'
	  } else if (close < open) { // 跌
		ctx.strokeStyle = '#26A69A'
		ctx.fillStyle = '#26A69A'
	  } else { // 未变动
		ctx.strokeStyle = '#888889'
		ctx.fillStyle = '#888889'
	  }
	  // 获取开盘价 Y 轴像素
	  let openY = yAxis.convertToPixel(open)
	  // 获取收盘价 Y 轴像素
	  let closeY = yAxis.convertToPixel(close)
	  // 开、收、高、低的 Y 轴像素
	  let priceY = [openY, closeY, yAxis.convertToPixel(high), yAxis.convertToPixel(low)]
	  // 从低到高排序
	  priceY.sort(function (a, b) {
		return a - b
	  })
	  // 画蜡烛柱上部
	  ctx.fillRect(x - 0.5, priceY[0], 1, priceY[1] - priceY[0])
	  // 画蜡烛柱下部
	  ctx.fillRect(x - 0.5, priceY[2], 1, priceY[3] - priceY[2])
	  // 蜡烛柱高度
	  var barHeight = Math.max(1, priceY[2] - priceY[1])
	  // 画蜡烛柱中部 (viewport.barSpace 蜡烛柱的宽度,随放大缩小操作而变化)
	  ctx.fillRect(x - (viewport.barSpace / 2), priceY[1], viewport.barSpace, barHeight)
	  // 下一蜡烛柱 X 轴的起始位置(viewport.dataSpace 蜡烛柱的宽度加蜡烛柱之间的间隔,随放大缩小操作而变化)
	  x += viewport.dataSpace
	})
  }
})

# 创建指标

this.chart.createTechnicalIndicator('custom_candle_solid', true, { id: 'paneId10', dragEnabled: true, height: this.height })