depthLine method

dynamic depthLine(
  1. dynamic x,
  2. dynamic y,
  3. dynamic w,
  4. 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;
}