G2
G2
G6
F2
L7
墨者学院
关于 G2
图表示例
API 文档
使用教程
English
折线图
基础折线图
双折线图
多折线图
其他折线图
条形图
分组条形图
堆叠条形图
基础条形图
柱状图
基础柱状图
分组柱状图
堆叠柱状图
直方图
饼图
环图
玫瑰图
基础饼图
嵌套饼图
点图
散点图
面积图
基础面积图
堆叠面积图
区间面积图
箱形图
箱型图
烛形图
烛形图
热力图
热力图
仪表盘
仪表盘
漏斗图
漏斗图
地图
地图
雷达图
雷达图
分面
分面
关系图
关系图
其他图表
其他
迷你图
组件使用
组件
其他
Kagi Chart
Kagi Chart
源码
复制成功
复制失败
全屏
复制
运行
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,height=device-height"> <title>Kagi Chart</title> <style>::-webkit-scrollbar{display:none;}html,body{overflow:hidden;height:100%;margin:0;}</style> </head> <body> <div id="mountNode"></div> <script>/*Fixing iframe window.innerHeight 0 issue in Safari*/document.body.clientHeight;</script> <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g2-3.5.1/dist/g2.min.js"></script> <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.data-set-0.10.1/dist/data-set.min.js"></script> <script src="https://gw.alipayobjects.com/os/antv/assets/lib/jquery-3.2.1.min.js"></script> <script> $.getJSON('https://gw.alipayobjects.com/os/antvdemo/assets/data/kagi.json', function(data) { // 获取卡吉图数据点 var kagiData = getKagiData(data, 'date', 'value'); var chart = new G2.Chart({ container: 'mountNode', forceFit: true, height: window.innerHeight }); chart.source(kagiData, { date: { type: 'cat', tickCount: 10, range: [0, 1] } }); chart.tooltip({ crosshairs: { type: 'line' } }); chart.path({ generatePoints: true }).position('date*value').color('type', function(val) { if (val === 'pos') { return '#f04864'; } return '#2fc25b'; }).size('type', function(val) { if (val === 'pos') { return 2; } return 1; }); chart.render(); }); /** * 获取卡吉图数据点 * @param {Array} points 原始数据点 * @param {String} x x维度字段名 * @param {String} y y维度字段名 * @return {Array} data 卡吉图数据点 **/ function getKagiData(points, x, y) { // 初始最小值 var min = points[0][y]; // 初始最大值 var max = points[0][y]; // 初始绘制起点 var start = points[0]; // 阳线和阴线判断标志 var isPos = points[1][y] >= points[0][y] ? true : false; // 初始绘制方向,1为向上,-1为向下 var direction = isPos ? 1 : -1; // 阈值,默认为最大值的4% var maxValue = getMax(points, y); var threshold = maxValue * 0.04; // 阴线数组 var negPath = []; // 阳线数组 var posPath = []; var tmp1 = {}; tmp1[x] = start[x]; tmp1[y] = start[y]; pushPoint(tmp1, isPos, posPath, negPath, x, y); if (points.length > 1) { for (var i = 0; i <= points.length - 1; i++) { // 浮动超过阈值时执行算法 if (Math.abs(start[y] - points[i][y]) > threshold) { if (direction > 0) { if (points[i][y] >= start[y]) { isPos = getVerticalPoints(start, points[i], max, direction, negPath, posPath, isPos, x, y); start[y] = points[i][y]; } else { var tmp2 = {}; tmp2[x] = points[i][x]; tmp2[y] = start[y]; pushPoint(tmp2, isPos, posPath, negPath, x, y); start[x] = points[i][x]; direction = -1; // 转向 isPos = getVerticalPoints(start, points[i], min, direction, negPath, posPath, isPos, x, y); max = start[y]; // 更新当前最高点 start = points[i]; // 更新当前绘制起点 } } else { if (points[i][y] < start[y]) { isPos = getVerticalPoints(start, points[i], min, direction, negPath, posPath, isPos, x, y); start[y] = points[i][y]; } else { var tmp3 = {}; tmp3[x] = points[i][x]; tmp3[y] = start[y]; pushPoint(tmp3, isPos, posPath, negPath, x, y); start[x] = points[i][x]; direction = 1; isPos = getVerticalPoints(start, points[i], max, direction, negPath, posPath, isPos, x, y); min = start[y]; // 更新当前最低点 start = points[i]; } } } } } return posPath.concat(negPath); } /** * 获取卡吉图垂直线数据点 * @param {Array} start 起点坐标 * @param {Array} end 终点坐标 * @param {Number} changePoint 转折点y坐标 * @param {Number} direction 绘制方向 * @param {Array} negPath 阴线数组 * @param {Array} posPath 阳线数组 * @param {Boolean} isPos 是否阳线标志位 * @param {String} x x维度字段名 * @param {String} y y维度字段名 * @return {Boolean} isPos 是否阳线标志位 **/ function getVerticalPoints(start, end, changePoint, direction, negPath, posPath, isPos, x, y) { // 阳线和阴线相互转换的判断条件 var condition = direction > 0 ? end[y] > changePoint && start[y] < changePoint && !isPos : end[y] < changePoint && start[y] > changePoint && isPos; var tmp1 = {}; tmp1[x] = start[x]; tmp1[y] = changePoint; var tmp2 = {}; tmp2[x] = start[x]; tmp2[y] = end[y]; if (condition) { pushPoint(tmp1, isPos, posPath, negPath, x, y, true); isPos = isPos ? false : true; pushPoint(tmp2, isPos, posPath, negPath, x, y); } else { pushPoint(tmp2, isPos, posPath, negPath, x, y); } return isPos; } /** * 将卡吉图数据分别放入阳线数组和阴线数组 * @param {Object} point 当前数据点 * @param {Boolean} isPos 是否阳线标志位 * @param {Array} negPath 阴线数组 * @param {Array} posPath 阳线数组 * @param {String} x x维度字段名 * @param {String} y y维度字段名 * @param {Boolean} isChangePoint 是否转折点 **/ function pushPoint(point, isPos, posPath, negPath, x, y) { var isChangePoint = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false; var tmpPoint = {}; tmpPoint[x] = point[x]; tmpPoint[y] = isChangePoint ? point[y] : null; // 转折点阳线和阴线都有数据,非转折点阳线或阴线的数据点为空 if (isPos) { point.type = 'pos'; posPath.push(point); tmpPoint.type = 'neg'; negPath.push(tmpPoint); } else { point.type = 'neg'; negPath.push(point); tmpPoint.type = 'pos'; posPath.push(tmpPoint); } } function getMax(points, y) { var max = points[points.length - 1][y]; if (points.length > 0) { for (var i = points.length - 1; i >= 0; i--) { max = points[i][y] > max ? points[i][y] : max; } } return max; } </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,height=device-height"> <title>Kagi Chart</title> <style>::-webkit-scrollbar{display:none;}html,body{overflow:hidden;height:100%;margin:0;}</style> </head> <body style="background: #1f1f1f;"> <div id="mountNode"></div> <script>/*Fixing iframe window.innerHeight 0 issue in Safari*/document.body.clientHeight;</script> <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g2-3.5.1/dist/g2.min.js"></script> <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.data-set-0.10.1/dist/data-set.min.js"></script> <script src="https://gw.alipayobjects.com/os/antv/assets/lib/jquery-3.2.1.min.js"></script> <script>G2.Global.setTheme('dark');</script> <script> $.getJSON('https://gw.alipayobjects.com/os/antvdemo/assets/data/kagi.json', function(data) { // 获取卡吉图数据点 var kagiData = getKagiData(data, 'date', 'value'); var chart = new G2.Chart({ container: 'mountNode', forceFit: true, height: window.innerHeight }); chart.source(kagiData, { date: { type: 'cat', tickCount: 10, range: [0, 1] } }); chart.tooltip({ crosshairs: { type: 'line' } }); chart.path({ generatePoints: true }).position('date*value').color('type', function(val) { if (val === 'pos') { return '#f04864'; } return '#2fc25b'; }).size('type', function(val) { if (val === 'pos') { return 2; } return 1; }); chart.render(); }); /** * 获取卡吉图数据点 * @param {Array} points 原始数据点 * @param {String} x x维度字段名 * @param {String} y y维度字段名 * @return {Array} data 卡吉图数据点 **/ function getKagiData(points, x, y) { // 初始最小值 var min = points[0][y]; // 初始最大值 var max = points[0][y]; // 初始绘制起点 var start = points[0]; // 阳线和阴线判断标志 var isPos = points[1][y] >= points[0][y] ? true : false; // 初始绘制方向,1为向上,-1为向下 var direction = isPos ? 1 : -1; // 阈值,默认为最大值的4% var maxValue = getMax(points, y); var threshold = maxValue * 0.04; // 阴线数组 var negPath = []; // 阳线数组 var posPath = []; var tmp1 = {}; tmp1[x] = start[x]; tmp1[y] = start[y]; pushPoint(tmp1, isPos, posPath, negPath, x, y); if (points.length > 1) { for (var i = 0; i <= points.length - 1; i++) { // 浮动超过阈值时执行算法 if (Math.abs(start[y] - points[i][y]) > threshold) { if (direction > 0) { if (points[i][y] >= start[y]) { isPos = getVerticalPoints(start, points[i], max, direction, negPath, posPath, isPos, x, y); start[y] = points[i][y]; } else { var tmp2 = {}; tmp2[x] = points[i][x]; tmp2[y] = start[y]; pushPoint(tmp2, isPos, posPath, negPath, x, y); start[x] = points[i][x]; direction = -1; // 转向 isPos = getVerticalPoints(start, points[i], min, direction, negPath, posPath, isPos, x, y); max = start[y]; // 更新当前最高点 start = points[i]; // 更新当前绘制起点 } } else { if (points[i][y] < start[y]) { isPos = getVerticalPoints(start, points[i], min, direction, negPath, posPath, isPos, x, y); start[y] = points[i][y]; } else { var tmp3 = {}; tmp3[x] = points[i][x]; tmp3[y] = start[y]; pushPoint(tmp3, isPos, posPath, negPath, x, y); start[x] = points[i][x]; direction = 1; isPos = getVerticalPoints(start, points[i], max, direction, negPath, posPath, isPos, x, y); min = start[y]; // 更新当前最低点 start = points[i]; } } } } } return posPath.concat(negPath); } /** * 获取卡吉图垂直线数据点 * @param {Array} start 起点坐标 * @param {Array} end 终点坐标 * @param {Number} changePoint 转折点y坐标 * @param {Number} direction 绘制方向 * @param {Array} negPath 阴线数组 * @param {Array} posPath 阳线数组 * @param {Boolean} isPos 是否阳线标志位 * @param {String} x x维度字段名 * @param {String} y y维度字段名 * @return {Boolean} isPos 是否阳线标志位 **/ function getVerticalPoints(start, end, changePoint, direction, negPath, posPath, isPos, x, y) { // 阳线和阴线相互转换的判断条件 var condition = direction > 0 ? end[y] > changePoint && start[y] < changePoint && !isPos : end[y] < changePoint && start[y] > changePoint && isPos; var tmp1 = {}; tmp1[x] = start[x]; tmp1[y] = changePoint; var tmp2 = {}; tmp2[x] = start[x]; tmp2[y] = end[y]; if (condition) { pushPoint(tmp1, isPos, posPath, negPath, x, y, true); isPos = isPos ? false : true; pushPoint(tmp2, isPos, posPath, negPath, x, y); } else { pushPoint(tmp2, isPos, posPath, negPath, x, y); } return isPos; } /** * 将卡吉图数据分别放入阳线数组和阴线数组 * @param {Object} point 当前数据点 * @param {Boolean} isPos 是否阳线标志位 * @param {Array} negPath 阴线数组 * @param {Array} posPath 阳线数组 * @param {String} x x维度字段名 * @param {String} y y维度字段名 * @param {Boolean} isChangePoint 是否转折点 **/ function pushPoint(point, isPos, posPath, negPath, x, y) { var isChangePoint = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false; var tmpPoint = {}; tmpPoint[x] = point[x]; tmpPoint[y] = isChangePoint ? point[y] : null; // 转折点阳线和阴线都有数据,非转折点阳线或阴线的数据点为空 if (isPos) { point.type = 'pos'; posPath.push(point); tmpPoint.type = 'neg'; negPath.push(tmpPoint); } else { point.type = 'neg'; negPath.push(point); tmpPoint.type = 'pos'; posPath.push(tmpPoint); } } function getMax(points, y) { var max = points[points.length - 1][y]; if (points.length > 0) { for (var i = points.length - 1; i >= 0; i--) { max = points[i][y] > max ? points[i][y] : max; } } return max; } </script> </body> </html>
图表简介
Kagi Chart
了解更多
图表用法
卡吉图大约发明于 19 世纪 70 年代日本股票市场开始交易的时候。在美国,史蒂文·尼森出版《烛形图之外》后,卡吉图分析法随之流行。由于能够清晰、有效的显示价格走势的路径,卡吉图是投资者用于对股票做出更好决策的图表之一。
关联图表
折线图
相关链接
BizCharts
Viser