depthLine method
dynamic
depthLine(
- dynamic x,
- dynamic y,
- dynamic w,
- dynamic h,
Implementation
depthLine(x, y, w, h) {
var drawData = {};
var linePath = [];
var txtPath = [];
var txtPath2 = [];
var reactPath = [];
int i = 0;
int hGap = 0;
dynamic txt = "";
//===================================y轴
double calYW = syw;
double callh = h - sxh;
hGap = (callh / style['depthStyle']['property']['hCopies']).round();
txt = '';
txtPath.add([
symaxStr,
x + w - syw,
y,
{'color': style['depthStyle']['property']['axisFontC']}
]);
i = hGap;
for (; i < callh - hGap / 2; i += hGap) {
txt = Tools.yToPrice(
callh, i, symin, sscale, klineState.widget.propertys['amountDigits']);
txtPath.add([
txt,
x + w - calYW,
y + i,
{'color': style['depthStyle']['property']['axisFontC']}
]);
}
txtPath.add([
syminStr,
x + w - syw,
y + callh - syts['height'],
{'color': style['depthStyle']['property']['axisFontC']}
]);
//======================================================
//============================时间轴
num leftR = 0;
num rightR = 0;
num transactionPrice = 0;
num min = 0;
num max = 0;
//有成交价,并且有买盘,并且有卖盘,并且成交价大于买一价,小于卖一价,则用成交价当作中间价
if (chartData.depthData.containsKey('transactionPrice') && chartData.depthDataBuyL>0 && chartData.depthDataSellL>0 &&
chartData.depthData['transactionPrice'] >=
chartData.depthData['bids'][chartData.depthDataBuyL - 1]['price'] &&
chartData.depthData['transactionPrice'] <=
chartData.depthData['asks'][0]['price']) {
//如果有最新成交价
leftR = (chartData.depthData['transactionPrice'] -
chartData.depthData['bids'][0]['price'])
.abs();
rightR = (chartData.depthData['asks'][chartData.depthDataSellL - 1]
['price'] -
chartData.depthData['transactionPrice'])
.abs();
if (leftR > rightR) {
max =
chartData.depthData['asks'][chartData.depthDataSellL - 1]['price'];
min = chartData.depthData['transactionPrice'] - rightR;
} else {
max = chartData.depthData['transactionPrice'] + leftR;
min = chartData.depthData['bids'][0]['price'];
}
transactionPrice = chartData.depthData['transactionPrice'];
} else {
//用买一卖一价
num leftLastP =0; //最大买价
num leftOneP = 0; //最小买价
num rightLastP = 0;//最大卖价
num rightOneP = 0;//最小卖家
if(chartData.depthDataBuyL>0){
leftLastP = chartData.depthData['bids'][chartData.depthDataBuyL - 1]['price'];
leftOneP = chartData.depthData['bids'][0]['price'];
}
leftR = (leftLastP - leftOneP).abs();//买价差
if(chartData.depthDataSellL>0){
rightLastP = chartData.depthData['asks'][chartData.depthDataSellL - 1]['price'];
rightOneP = chartData.depthData['asks'][0]['price'];
}
rightR = (rightLastP - rightOneP).abs();//卖家差
if(leftR>0 && rightR >0){
if (leftR > rightR) {
max = rightLastP;
min = rightOneP - rightR;
} else {
max = leftLastP + leftR;
min = leftOneP;
}
transactionPrice = (max + min) / 2;//中心价
}else if(leftR>0){
max = leftLastP;// + leftR;
min = leftOneP;
transactionPrice = max;//中心价
}else if(rightR >0){
max = rightLastP;
min = rightOneP;// - rightR;
transactionPrice = min;//中心价
}
}
linePath.add({
'stroke': {
'color': style['depthStyle']['property']['axisFontC'],
'strokeWidth': style['depthStyle']['property']['axisLineW'],
},
'linePath': [
[
"moveTo",
[x, y + h - sxh]
],
[
"lineTo",
[x + w - calYW, y + h - sxh]
]
],
});
double xscale = (max - min) / (w - syw);
double ponew = sxts['width'];
List pList = [];
double pw = w - syw;
if(ponew*5<pw){//5个价格刻度
pList = [0,(pw/2-ponew*1.5)/2+ponew,pw/2,pw/2+ponew/2+(pw/2-ponew*1.5)/2,pw];
}else if(ponew*3<pw){//3个价格刻度
pList = [0,pw/2,pw];
}else{//2个价格刻度
pList = [0,pw];
}
Map pStyle = {};
for (i = 0; i < pList.length; i++) {
if(i == 0){
txt = Tools.toFixed(min, klineState.widget.propertys['priceDigits']);
}else if(i == pList.length-1){
txt = Tools.toFixed(
max, klineState.widget.propertys['priceDigits']);
pStyle = {'color': style['depthStyle']['property']['axisFontC'],'xlayout':'right'};
}else{
txt = Tools.toFixed(
pList[i] * xscale + min, klineState.widget.propertys['priceDigits']);
pStyle = {'color': style['depthStyle']['property']['axisFontC'],'xlayout':'center'};
}
txtPath.add([
txt,
x + pList[i],
y + h - sxh,
pStyle
]);
}
//============================================
//=====================中间竖线================
var transactionPricex = ((transactionPrice - min) / xscale);
linePath.add({
'stroke': {
'color': style['depthStyle']['property']['centerLineC'],
'strokeWidth': style['depthStyle']['property']['centerLineW'],
'dottedLine': style['depthStyle']['property']['centerLineDotted'],
},
'linePath': [
[
"moveTo",
[x + transactionPricex, y]
],
[
"lineTo",
[x + transactionPricex, y + h - sxh]
]
],
});
//==============================================
num first = 0, firstx = 0, prey = 0;
num mx = -1;
if(klineState.widget.isWeb){
if(klineState.isInWeb){
mx = klineState.currentPosition.dx;
}
}else{
if(klineState.tapStatus != TapStatus.up){
mx = klineState.currentPosition.dx;
}
}
num mxx = mx - x;
num mp = mxx * xscale + min; //第一个鼠标位价格
num mp2 = 0; //第二个鼠标位价格
Map? mobj; //第一个鼠标位数据
Map? mobj2; //第二个鼠标位数据
num my1 = 0; //第一个鼠标位y轴
num my2 = 0; //第二个鼠标位y轴
//=================================左区域 买盘
num buyX = 0;
num buyY = 0;
int leftl = 0;
num cwc = 0;
num mx2 = mx + (cwc - mxx) * 2; //第二根竖线坐标
if(chartData.depthDataBuyL>0){
leftl = chartData.depthDataBuyL;
cwc = (chartData.depthData['bids'][leftl - 1]['price'] - min) / xscale; //买盘宽度
mx2 = mx + (cwc - mxx) * 2;
//第二根竖线坐标。mx是第一根竖线坐标, mxx是第一根距离左边x的距离。 cwc是左边整体宽度。
//cwc-mxx就是第一根竖线右侧到买盘边缘距离, X2计算出对应第二根距离 +mx 算出卖盘坐标
}
mp2 = (mx2 - x) * xscale + min;
var sddata = chartData.depthData['bids'];
var leftlineData = []; //绘制到最底
var leftfillLineData = [];
for (i = 0; i < leftl; i++) {
var cbso = sddata[i];
var cbson = i < leftl - 1 ? sddata[i + 1] : sddata[leftl - 1];
buyX = 0;
if (cbso['price'] == min) {
buyX = 0;
} else {
buyX = (cbso['price'] - min) / xscale;
}
buyY = Tools.priceToY(callh, cbso['vol'], symin, sscale);
if (i == 0) {
//从最左边开始画 x+0,y+buyY ---》 x+buyX,y+buyY 每一个点都是一根横线
first = buyY;
prey = buyY;
firstx = buyX;
leftfillLineData.add([
"moveTo",
[x + buyX, y + buyY]
]);
leftlineData.add([
"moveTo",
[x + buyX, y + buyY]
]);
} else {
leftfillLineData.add([
"lineTo",
[x + buyX, y + prey]
]);
leftfillLineData.add([
"lineTo",
[x + buyX, y + buyY]
]);
leftlineData.add([
"lineTo",
[x + buyX, y + prey]
]);
leftlineData.add([
"lineTo",
[x + buyX, y + buyY]
]);
prey = buyY;
}
if (cbso['price'] <= mp && cbson['price'] >= mp) {
mobj = cbso;
my1 = y + buyY;
}
if (cbso['price'] <= mp2 && cbson['price'] >= mp2) {
mobj2 = cbso;
my2 = y + buyY;
}
}
leftlineData.add([
"lineTo",
[x + buyX, y + h - sxh]
]); //绘制到最底
leftfillLineData.add([
"lineTo",
[x + buyX, y + callh]
]);
leftfillLineData.add([
"lineTo",
[x + firstx, y + callh]
]);
leftfillLineData.add([
"lineTo",
[x + firstx, y + first]
]);
linePath.add({
'stroke': {
'color': style[ColorType['downColor']],
},
'linePath': leftlineData,
});
linePath.add({
'stroke': {
'color': style[ColorType['lightDownColor']],
'style': PaintingStyle.fill,
'close': true,
},
'linePath': leftfillLineData,
});
//====================================右区域 卖盘
var rightfillLineData = [];
var rightlineData = [];
var rightl = chartData.depthDataSellL;
sddata = chartData.depthData['asks'];
num rightfirst = 0;
bool isBreak = false;
num sellX = 0;
num sellY = 0;
for (i = 0; i < rightl; i++) {
var cbso = sddata[i];
var cbson = i < rightl - 1 ? sddata[i + 1] : sddata[rightl - 1];
sellX = 0;
if (cbso['price'] == max) {
sellX = w - syw;
} else {
sellX = (cbso['price'] - min) / xscale;
if (sellX > w - syw) {
sellX = w - syw;
isBreak = true;
}
}
sellY = Tools.priceToY(callh, cbso['vol'], symin, sscale);
if (i == 0) {
//从最底开始画 x+sellX,y+h-sxh ---》 x+sellX,y+sellY 一个点是一条竖线
first = sellY;
rightfirst = sellX;
prey = sellY;
rightfillLineData.add([
"moveTo",
[x + sellX, y + sellY]
]);
rightlineData.add([
"moveTo",
[x + sellX, y + h - sxh]
]);
rightlineData.add([
"lineTo",
[x + sellX, y + sellY]
]);
} else {
rightfillLineData.add([
"lineTo",
[x + sellX, y + prey]
]);
rightfillLineData.add([
"lineTo",
[x + sellX, y + sellY]
]);
rightlineData.add([
"lineTo",
[x + sellX, y + prey]
]);
rightlineData.add([
"lineTo",
[x + sellX, y + sellY]
]);
prey = sellY;
}
if (cbso['price'] <= mp && cbson['price'] >= mp) {
mobj = cbso;
my1 = y + sellY;
}
if (cbso['price'] <= mp2 && cbson['price'] >= mp2) {
mobj2 = cbso;
my2 = y + sellY;
}
if (isBreak) {
break;
}
}
rightlineData.add([
"lineTo",
[x + w - syw, y + sellY]
]); //绘制到最右边 其实最后的x+sellX 已经是最后了 x+sellX = x+w-syw
rightfillLineData.add([
"lineTo",
[x + sellX, y + callh]
]);
rightfillLineData.add([
"lineTo",
[x + rightfirst, y + callh]
]);
rightfillLineData.add([
"lineTo",
[x + rightfirst, y + first]
]);
linePath.add({
'stroke': {
'color': style[ColorType['upColor']],
},
'linePath': rightlineData,
});
linePath.add({
'stroke': {
'color': style[ColorType['lightUpColor']],
'style': PaintingStyle.fill,
'close': true,
},
'linePath': rightfillLineData,
});
//十字线 + 十字线刻度提示 + 数据提示
//kdw 横向刻度背景宽度 kdwx 横向刻度背景x坐标
//kdh 竖向刻度背景高度 kdwy 竖向刻度背景y坐标
//cwc 画布的一半宽度
var crossLeftPoint1 = [];
var crossRightPoint1 = [];
// 绘制左侧圆圈颜色
linePath.add({
'stroke': {
'color': mx <= mx2?style[ColorType['lightDownColor']]:style[ColorType['lightUpColor']],
'style': PaintingStyle.fill,
},
'linePath': crossLeftPoint1,
});
// 绘制右侧圆圈颜色
linePath.add({
'stroke': {
'color': mx <= mx2?style[ColorType['lightUpColor']]:style[ColorType['lightDownColor']],
'style': PaintingStyle.fill,
},
'linePath': crossRightPoint1,
});
num kdw = 100, kdwx = 0, padding = 10;
if (mx > x &&
mx < x + w - syw &&
mobj != null &&
(klineState.widget.isWeb || klineState.tapStatus != TapStatus.up)) {
//绘制竖十字线
kdwx = mx - x - kdw / 2; //计算x轴刻度文本背景色块x坐标(鼠标坐标-绘图起始x,然后在偏移色块一半的宽度)
kdwx = mx - x < kdw / 2 ? 0 : kdwx; //如果左边不够地方了,靠左展示,不在居中
kdwx = mx - x > w - syw - kdw / 2
? w - syw - kdw
: kdwx; //如果右边不够地方了,靠右展示,不在居中
crossLeftPoint1.add([
"drawCircle",
[mx, my1, style['depthStyle']['property']['crossPointR']]
]);
linePath.add({
'stroke': {
'color': style['depthStyle']['property']['crossLineC'],
'strokeWidth': style['depthStyle']['property']['crossLineW'],
'dottedLine': style['depthStyle']['property']['crossLineDotted'],
},
'linePath': [
[
"moveTo",
[mx, y]
],
[
"lineTo",
[mx, y + h - sxh]
]
],
});
String txt1 = klineState.widget.propertys['i18n']['depthTipPrice']
.replaceAll('{v1}', Tools.toFixed(mobj['price'], klineState.widget.propertys['priceDigits']));
String txt2 = klineState.widget.propertys['i18n']['depthTipAmount']
.replaceAll('{v1}', Tools.toFixed(mobj['vol'], klineState.widget.propertys['amountDigits']));
var txt1Size = Tools.getStrW(txt1, style['depthStyle']['font']);
var txt2Size = Tools.getStrW(txt2, style['depthStyle']['font']);
num tipw = Tools.max(txt1Size['width'], txt2Size['width']) + padding * 2;
num tiph = txt1Size['height'] * 2 + padding * 3; //上下10间距,文字行20
num tipx = (cwc - mx - 10 > tipw ? mx + 10 : mx - tipw - 10);
//当鼠标左侧宽度不够的时候,固定右侧展示
if (mx < tipw + 10) {
tipx = mx + 10;
}
num tipy = (klineState.klineBox['height']! - my1 - 10 > tiph ? my1 + 10 : my1 - tiph - 10);
// //边
reactPath.add({
'stroke': {
'color': style['depthStyle']['property']['crossTipBorderC'],
'strokeWidth': style['depthStyle']['property']['crossTipBorderW'],
'style': PaintingStyle.stroke,
},
'linePath': [
[
"drawRect",
[
tipx,
tipy,
tipw,
tiph,
style['depthStyle']['property']['crossTipRound']
]
]
],
});
//背景
reactPath.add({
'stroke': {
'color': style['depthStyle']['property']['crossTipFillC'],
'style': PaintingStyle.fill,
},
'linePath': [
[
"drawRect",
[
tipx,
tipy,
tipw,
tiph,
style['depthStyle']['property']['crossTipRound']
]
]
],
});
//文字1
txtPath2.add([
txt1,
tipx + padding,
tipy + padding,
{'color': style['depthStyle']['property']['crossTipFontC']}
]);
//文字2
txtPath2.add([
txt2,
tipx + padding,
tipy + padding + txt1Size['height'] + padding,
{'color': style['depthStyle']['property']['crossTipFontC']}
]);
if (mx2 > x && mx2 < x + w - syw && mobj2 != null) {
//绘制第二根对称竖十字线
crossRightPoint1.add([
"drawCircle",
[mx2, my2, style['depthStyle']['property']['crossPointR']]
]); //绘制x轴刻度色块
//绘制x轴刻度色块
linePath.add({
'stroke': {
'color': style['depthStyle']['property']['crossLineC'],
'strokeWidth': style['depthStyle']['property']['crossLineW'],
'dottedLine': style['depthStyle']['property']['crossLineDotted'],
},
'linePath': [
[
"moveTo",
[mx2, y]
],
[
"lineTo",
[mx2, y + h - sxh]
]
],
});
txt1 = klineState.widget.propertys['i18n']['depthTipPrice']
.replaceAll('{v1}', Tools.toFixed(mobj2['price'], klineState.widget.propertys['priceDigits']));
txt2 = klineState.widget.propertys['i18n']['depthTipAmount']
.replaceAll('{v1}', Tools.toFixed(mobj2['vol'], klineState.widget.propertys['amountDigits']));
txt1Size = Tools.getStrW(txt1, style['depthStyle']['font']);
txt2Size = Tools.getStrW(txt2, style['depthStyle']['font']);
tipw = Tools.max(txt1Size['width'], txt2Size['width']) + padding * 2;
tiph = txt1Size['height'] * 2 + padding * 3;
tipx = (mx2 - cwc - 10 <= tipw ? mx2 + 10 : mx2 - tipw - 10);
//当鼠标右侧宽度不够时,固定左边展示
if (klineState.klineBox['width']! - mx2 < tipw + 10) {
tipx = mx2 - tipw - 10;
}
tipy = (klineState.klineBox['height']! - my2 - 10 > tiph ? my2 + 10 : my2 - tiph - 10);
//边
reactPath.add({
'stroke': {
'color': style['depthStyle']['property']['crossTipBorderC'],
'strokeWidth': style['depthStyle']['property']['crossTipBorderW'],
'style': PaintingStyle.stroke,
},
'linePath': [
[
"drawRect",
[
tipx,
tipy,
tipw,
tiph,
style['depthStyle']['property']['crossTipRound']
]
]
],
});
//背景
reactPath.add({
'stroke': {
'color': style['depthStyle']['property']['crossTipFillC'],
'style': PaintingStyle.fill,
},
'linePath': [
[
"drawRect",
[
tipx,
tipy,
tipw,
tiph,
style['depthStyle']['property']['crossTipRound']
]
]
],
});
//文字1
txtPath2.add([
txt1,
tipx + padding,
tipy + padding,
{'color': style['depthStyle']['property']['crossTipFontC']}
]);
//文字2
txtPath2.add([
txt2,
tipx + padding,
tipy + padding + txt1Size['height'] + padding,
{'color': style['depthStyle']['property']['crossTipFontC']}
]);
} else {
//不绘制
// print('============不绘制右侧提示 $mx2');
}
} else {
//不绘制
// print('============不绘制左侧提示 $mx');
}
drawData = {
'linePath': linePath,
'txtPath': txtPath,
'reactPath': reactPath,
'txtPath2': txtPath2,
};
// print('深度路径: $reactPath');
return drawData;
}