From 8c9953666a099e7ff707a99e7f550fa729396db3 Mon Sep 17 00:00:00 2001 From: liuyang Date: Fri, 11 Sep 2020 21:53:09 +0800 Subject: [PATCH] perf(rewrite draw canvas method): prepare for inline string suport complex rotate and wrap --- src/controllers/menuButton.js | 6 +- src/global/draw.js | 1190 +++++---------------------------- src/global/getRowlen.js | 380 +++++++---- src/store/index.js | 1 + 4 files changed, 440 insertions(+), 1137 deletions(-) diff --git a/src/controllers/menuButton.js b/src/controllers/menuButton.js index c09bc92..7b9e046 100644 --- a/src/controllers/menuButton.js +++ b/src/controllers/menuButton.js @@ -2937,9 +2937,9 @@ const menuButton = { d[r][c][attr] = foucsStatus; } - if(attr == "tr" && d[r][c].tb != null){ - d[r][c].tb = "0"; - } + // if(attr == "tr" && d[r][c].tb != null){ + // d[r][c].tb = "0"; + // } } } } diff --git a/src/global/draw.js b/src/global/draw.js index 3dc866e..d717dd6 100644 --- a/src/global/draw.js +++ b/src/global/draw.js @@ -996,6 +996,7 @@ function luckysheetDrawMain(scrollWidth, scrollHeight, drawWidth, drawHeight, of Store.measureTextCacheTimeOut = setTimeout(() => { Store.measureTextCache = {}; + Store.measureTextCellInfoCache = {}; }, 2000); } @@ -1178,7 +1179,7 @@ let nullCellRender = function(r, c, start_r, start_c, end_r, end_c,luckysheetTab } -let cellRender1 = function(r, c, start_r, start_c, end_r, end_c, value, luckysheetTableContent,af_compute, cf_compute,offsetLeft,offsetTop,dynamicArray_compute,cellOverflowMap, dataset_col_st, dataset_col_ed,scrollHeight,scrollWidth,bodrder05,isMerge){ +let cellRender = function(r, c, start_r, start_c, end_r, end_c, value, luckysheetTableContent,af_compute, cf_compute,offsetLeft,offsetTop,dynamicArray_compute,cellOverflowMap, dataset_col_st, dataset_col_ed,scrollHeight,scrollWidth,bodrder05,isMerge){ let cell = Store.flowdata[r][c]; let cellWidth = end_c - start_c - 2; @@ -1273,7 +1274,7 @@ let cellRender1 = function(r, c, start_r, start_c, end_r, end_c, value, luckyshe if(cell.tb == '1' && cellOverflow_colInObj.colIn){ //此单元格 为 溢出单元格渲染范围最后一列,绘制溢出单元格内容 if(cellOverflow_colInObj.colLast){ - cellTextRender( + cellOverflowRender( cellOverflow_colInObj.rowIndex, cellOverflow_colInObj.colIndex, cellOverflow_colInObj.stc, @@ -1504,7 +1505,9 @@ let cellRender1 = function(r, c, start_r, start_c, end_r, end_c, value, luckyshe cellWidth:cellWidth, cellHeight:cellHeight, space_width:space_width, - space_height:space_height + space_height:space_height, + r:r, + c:c }); //若单元格有条件格式图标集 @@ -1599,1042 +1602,213 @@ let cellRender1 = function(r, c, start_r, start_c, end_r, end_c, value, luckyshe } } -//非空白单元格渲染 -let cellRender = function(r, c, start_r, start_c, end_r, end_c, value, luckysheetTableContent,af_compute, cf_compute,offsetLeft,offsetTop,dynamicArray_compute,cellOverflowMap, dataset_col_st, dataset_col_ed,scrollHeight,scrollWidth,bodrder05,isMerge){ +//溢出单元格渲染 +let cellOverflowRender = function(r, c, stc, edc,luckysheetTableContent,scrollHeight,scrollWidth,offsetLeft,offsetTop,af_compute, cf_compute){ + //溢出单元格 起止行列坐标 + let start_r; + if (r == 0) { + start_r = -scrollHeight - 1; + } + else { + start_r = Store.visibledatarow[r - 1] - scrollHeight - 1; + } + + let end_r = Store.visibledatarow[r] - scrollHeight; + + let start_c; + if (stc == 0) { + start_c = -scrollWidth; + } + else { + start_c = Store.visibledatacolumn[stc - 1] - scrollWidth; + } + + let end_c = Store.visibledatacolumn[edc] - scrollWidth; + // let cell = Store.flowdata[r][c]; let cellWidth = end_c - start_c - 2; let cellHeight = end_r - start_r - 2; let space_width = 2, space_height = 2; //宽高方向 间隙 + let pos_x = start_c + offsetLeft; + let pos_y = start_r + offsetTop + 1; + let fontset = luckysheetfontformat(cell); luckysheetTableContent.font = fontset; - // luckysheetTableContent.textBaseline = 'top'; + + luckysheetTableContent.save(); + luckysheetTableContent.beginPath(); + luckysheetTableContent.rect(pos_x , pos_y, cellWidth , cellHeight ); + luckysheetTableContent.clip(); + luckysheetTableContent.scale(Store.zoomRatio,Store.zoomRatio); - //水平对齐 - let horizonAlign = menuButton.checkstatus(Store.flowdata, r, c, "ht"); - //垂直对齐 - let verticalAlign = menuButton.checkstatus(Store.flowdata, r, c, "vt"); - //文本单行 宽度和高度 - let measureText = getMeasureText(value, luckysheetTableContent); - //luckysheetTableContent.measureText(value); - let textMetrics = measureText.width; - let oneLineTextHeight = measureText.actualBoundingBoxDescent + measureText.actualBoundingBoxAscent; + let textInfo = getCellTextInfo(cell , luckysheetTableContent, { + cellWidth:cellWidth, + cellHeight:cellHeight, + space_width:space_width, + space_height:space_height, + r:r, + c:c + }); + //交替颜色 let checksAF = alternateformat.checksAF(r, c, af_compute); //条件格式 let checksCF = conditionformat.checksCF(r, c, cf_compute); - //单元格 背景颜色 - let fillStyle = menuButton.checkstatus(Store.flowdata, r, c, "bg"); - if(checksAF != null && checksAF[1] != null){ //若单元格有交替颜色 背景颜色 - fillStyle = checksAF[1]; + //单元格 文本颜色 + luckysheetTableContent.fillStyle = menuButton.checkstatus(Store.flowdata, r, c , "fc"); + + //若单元格有交替颜色 文本颜色 + if(checksAF != null && checksAF[0] != null){ + luckysheetTableContent.fillStyle = checksAF[0]; } - if(checksCF != null && checksCF["cellColor"] != null){ //若单元格有条件格式 背景颜色 - fillStyle = checksCF["cellColor"]; + //若单元格有条件格式 文本颜色 + if(checksCF != null && checksCF["textColor"] != null){ + luckysheetTableContent.fillStyle = checksCF["textColor"]; } - if(fillStyle==null){ - luckysheetTableContent.fillStyle = "#FFFFFF"; - } - else{ - luckysheetTableContent.fillStyle = fillStyle; - } + cellTextRender( + textInfo, + luckysheetTableContent, + { + pos_x:pos_x, + pos_y:pos_y, + } + ); + luckysheetTableContent.restore(); + // let fontset = luckysheetfontformat(cell); + // luckysheetTableContent.font = fontset; + // // luckysheetTableContent.textBaseline = 'top'; + + // //溢出单元格 值 + // let value = getcellvalue(r, c, null, "m"); + // if(value == null){ + // value = getcellvalue(r, c); + // } + + // //文本单行 宽度和高度 + // let measureText = getMeasureText(value, luckysheetTableContent); + // //luckysheetTableContent.measureText(value); + // let textMetrics = measureText.width; + // let oneLineTextHeight = measureText.actualBoundingBoxDescent + measureText.actualBoundingBoxAscent; + + // let pos_x = start_c + offsetLeft; + // let pos_y = start_r + offsetTop + 1; - let borderfix = menuButton.borderfix(Store.flowdata, r, c); - // console.log(value, fillStyle,borderfix); - let cellsize = [ - (start_c + offsetLeft + borderfix[0]), - (start_r + offsetTop + borderfix[1]), - (end_c - start_c + borderfix[2]-(!!isMerge?1:0)), - (end_r - start_r + borderfix[3]) - ]; - luckysheetTableContent.fillRect(cellsize[0], cellsize[1], cellsize[2], cellsize[3]); + // luckysheetTableContent.save(); + // luckysheetTableContent.beginPath(); + // luckysheetTableContent.rect(pos_x, pos_y, cellWidth, cellHeight); + // luckysheetTableContent.clip(); + // luckysheetTableContent.scale(Store.zoomRatio,Store.zoomRatio); + + // //溢出单元格 水平对齐 + // let horizonAlign = menuButton.checkstatus(Store.flowdata, r, c, "ht"); + // let horizonAlignPos = (pos_x + space_width) ; //默认为1,左对齐 + // if(horizonAlign == "0"){ //居中对齐 + // horizonAlignPos = (pos_x + cellWidth / 2) - (textMetrics / 2); + // } + // else if(horizonAlign == "2"){ //右对齐 + // horizonAlignPos = (pos_x + cellWidth - space_width) - textMetrics; + // } + + // let verticalCellHeight = cellHeight>oneLineTextHeight?cellHeight:oneLineTextHeight; + // //溢出单元格 垂直对齐 + // let verticalAlign = menuButton.checkstatus(Store.flowdata, r, c, "vt"); + // let verticalAlignPos = (pos_y + verticalCellHeight - space_height) - oneLineTextHeight; //默认为2,下对齐 + // let verticalAlignPos_text = (pos_y + verticalCellHeight - space_height) ; //文本垂直方向基准线 + // luckysheetTableContent.textBaseline = "bottom"; + // if(verticalAlign == "0"){ //居中对齐 + // verticalAlignPos = (pos_y + verticalCellHeight / 2) - (oneLineTextHeight / 2); + + // verticalAlignPos_text = (pos_y + verticalCellHeight / 2) ; + // luckysheetTableContent.textBaseline = "middle"; + // } + // else if(verticalAlign == "1"){ //上对齐 + // verticalAlignPos = (pos_y + space_height) ; + + // verticalAlignPos_text = (pos_y + space_height) ; + // luckysheetTableContent.textBaseline = "top"; + // } - // luckysheetTableContent.fillRect( - // (start_c + offsetLeft - 1) , - // (start_r + offsetTop) , - // (end_c - start_c) , - // (end_r - start_r) - // ) + // verticalAlignPos = verticalAlignPos/Store.zoomRatio; + // horizonAlignPos = horizonAlignPos/Store.zoomRatio; + // verticalAlignPos_text = verticalAlignPos_text/Store.zoomRatio; - //若单元格有批注(单元格右上角红色小三角标示) - if(cell.ps != null){ - let ps_w = 8*Store.zoomRatio, ps_h = 8*Store.zoomRatio; //红色小三角宽高 + // //交替颜色 + // let checksAF = alternateformat.checksAF(r, c, af_compute); + // //条件格式 + // let checksCF = conditionformat.checksCF(r, c, cf_compute); - luckysheetTableContent.beginPath(); - luckysheetTableContent.moveTo( - (end_c + offsetLeft - ps_w), - (start_r + offsetTop) - ); - luckysheetTableContent.lineTo( - (end_c + offsetLeft), - (start_r + offsetTop) - ); - luckysheetTableContent.lineTo( - (end_c + offsetLeft), - (start_r + offsetTop + ps_h) - ); - luckysheetTableContent.fillStyle = "#FC6666"; - luckysheetTableContent.fill(); - luckysheetTableContent.closePath(); - } + // //单元格 文本颜色 + // luckysheetTableContent.fillStyle = menuButton.checkstatus(Store.flowdata, r, c , "fc"); + + // //若单元格有交替颜色 文本颜色 + // if(checksAF != null && checksAF[0] != null){ + // luckysheetTableContent.fillStyle = checksAF[0]; + // } + // //若单元格有条件格式 文本颜色 + // if(checksCF != null && checksCF["textColor"] != null){ + // luckysheetTableContent.fillStyle = checksCF["textColor"]; + // } + + // luckysheetTableContent.fillText(value == null ? "" : value, horizonAlignPos, verticalAlignPos_text); + + // luckysheetTableContent.restore(); + + //单元格是否有删除线 + // let cl = menuButton.checkstatus(Store.flowdata, r, c , "cl"); + // if(cl == "1" && !isRealNull(value)){ + // luckysheetTableContent.beginPath(); + // luckysheetTableContent.strokeStyle = "#000"; + // luckysheetTableContent.moveTo( + // horizonAlignPos, + // verticalAlignPos + oneLineTextHeight / 2/Store.zoomRatio + // ); + // luckysheetTableContent.lineTo( + // horizonAlignPos + textMetrics/Store.zoomRatio, + // verticalAlignPos + oneLineTextHeight / 2/Store.zoomRatio + // ); + // luckysheetTableContent.stroke(); + // luckysheetTableContent.closePath(); + // } +} - //若单元格强制为字符串,则显示绿色小三角 - if(cell.qp==1 && isRealNum(cell.v)){ - let ps_w = 6*Store.zoomRatio, ps_h = 6*Store.zoomRatio; //红色小三角宽高 +//获取表格渲染范围 溢出单元格 +function getCellOverflowMap(canvas, col_st, col_ed, row_st, row_end){ + let map = {}; - luckysheetTableContent.beginPath(); - luckysheetTableContent.moveTo( - (start_c + offsetLeft + ps_w-1), - (start_r + offsetTop) - ); - luckysheetTableContent.lineTo( - (start_c + offsetLeft-1), - (start_r + offsetTop) - ); - luckysheetTableContent.lineTo( - (start_c + offsetLeft-1), - (start_r + offsetTop + ps_h) - ); - luckysheetTableContent.fillStyle = "#487f1e"; - luckysheetTableContent.fill(); - luckysheetTableContent.closePath(); - } + let data = Store.flowdata; - //溢出单元格 - let cellOverflow_bd_r_render = true; //溢出单元格右边框是否需要绘制 - let cellOverflow_colInObj = cellOverflow_colIn(cellOverflowMap, r, c, dataset_col_st, dataset_col_ed); + for(let r = row_st; r <= row_end; r++){ + for(let c = 0; c < data[r].length; c++){ + let cell = data[r][c]; - if(cell.tb == '1' && cellOverflow_colInObj.colIn){ - //此单元格 为 溢出单元格渲染范围最后一列,绘制溢出单元格内容 - if(cellOverflow_colInObj.colLast){ - cellOverflowRender( - cellOverflow_colInObj.rowIndex, - cellOverflow_colInObj.colIndex, - cellOverflow_colInObj.stc, - cellOverflow_colInObj.edc, - luckysheetTableContent, - scrollHeight, - scrollWidth,offsetLeft,offsetTop,af_compute, cf_compute - ); - } - else{ - cellOverflow_bd_r_render = false; - } - } - //非溢出单元格 - else{ - //若单元格有条件格式数据条 - if(checksCF != null && checksCF["dataBar"] != null){ - let x = (start_c + offsetLeft + space_width); - let y = (start_r + offsetTop + space_height); - let w = (cellWidth - space_width * 2); - let h = (cellHeight - space_height * 2); + if (Store.config["colhidden"] != null && Store.config["colhidden"][c] != null) { + continue + } - let valueType = checksCF["dataBar"]["valueType"]; - let valueLen = checksCF["dataBar"]["valueLen"]; - let format = checksCF["dataBar"]["format"]; + if(cell != null && !isRealNull(cell.v) && cell.mc == null && cell.tb == '1'){ + // let fontset = luckysheetfontformat(cell); + // canvas.font = fontset; - if(valueType == 'minus'){ - //负数 - let minusLen = checksCF["dataBar"]["minusLen"]; - - if(format.length > 1){ - //渐变 - let my_gradient = luckysheetTableContent.createLinearGradient( - x + w * minusLen * (1 - valueLen), - y, - x + w * minusLen, - y - ); - my_gradient.addColorStop(0, "#ffffff"); - my_gradient.addColorStop(1, "#ff0000"); + //水平对齐 + let horizonAlign = menuButton.checkstatus(data, r, c, "ht"); - luckysheetTableContent.fillStyle = my_gradient; - } - else{ - //单色 - luckysheetTableContent.fillStyle = "#ff0000"; - } + //文本宽度 + // let value = getcellvalue(r, c, null, "m"); + // if(value == null){ + // value = getcellvalue(r, c); + // } - luckysheetTableContent.fillRect( - x + w * minusLen * (1 - valueLen), - y, - w * minusLen * valueLen, - h - ); - - luckysheetTableContent.beginPath(); - luckysheetTableContent.moveTo( - x + w * minusLen * (1 - valueLen), - y - ); - luckysheetTableContent.lineTo( - x + w * minusLen * (1 - valueLen), - y + h - ); - luckysheetTableContent.lineTo( - x + w * minusLen, - y + h - ); - luckysheetTableContent.lineTo( - x + w * minusLen, - y - ); - luckysheetTableContent.lineTo( - x + w * minusLen * (1 - valueLen), - y - ); - luckysheetTableContent.lineWidth = 1; - luckysheetTableContent.strokeStyle = "#ff0000"; - luckysheetTableContent.stroke(); - luckysheetTableContent.closePath(); - } - else if(valueType == 'plus'){ - //正数 - let plusLen = checksCF["dataBar"]["plusLen"]; - - if(plusLen == 1){ - if(format.length > 1){ - //渐变 - let my_gradient = luckysheetTableContent.createLinearGradient( - x, - y, - x + w * valueLen, - y - ); - my_gradient.addColorStop(0, format[0]); - my_gradient.addColorStop(1, format[1]); - - luckysheetTableContent.fillStyle = my_gradient; - } - else{ - //单色 - luckysheetTableContent.fillStyle = format[0]; - } - - luckysheetTableContent.fillRect( - x, - y, - w * valueLen, - h - ); - - luckysheetTableContent.beginPath(); - luckysheetTableContent.moveTo( - x, - y - ); - luckysheetTableContent.lineTo( - x, - y + h - ); - luckysheetTableContent.lineTo( - x + w * valueLen, - y + h - ); - luckysheetTableContent.lineTo( - x + w * valueLen, - y - ); - luckysheetTableContent.lineTo( - x, - y - ); - luckysheetTableContent.lineWidth = 1; - luckysheetTableContent.strokeStyle = format[0]; - luckysheetTableContent.stroke(); - luckysheetTableContent.closePath(); - } - else{ - let minusLen = checksCF["dataBar"]["minusLen"]; - - if(format.length > 1){ - //渐变 - let my_gradient = luckysheetTableContent.createLinearGradient( - x + w * minusLen, - y, - x + w * minusLen + w * plusLen * valueLen, - y - ); - my_gradient.addColorStop(0, format[0]); - my_gradient.addColorStop(1, format[1]); - - luckysheetTableContent.fillStyle = my_gradient; - } - else{ - //单色 - luckysheetTableContent.fillStyle = format[0]; - } - - luckysheetTableContent.fillRect( - x + w * minusLen, - y, - w * plusLen * valueLen, - h - ); - - luckysheetTableContent.beginPath(); - luckysheetTableContent.moveTo( - x + w * minusLen, - y - ); - luckysheetTableContent.lineTo( - x + w * minusLen, - y + h - ); - luckysheetTableContent.lineTo( - x + w * minusLen + w * plusLen * valueLen, - y + h - ); - luckysheetTableContent.lineTo( - x + w * minusLen + w * plusLen * valueLen, - y - ); - luckysheetTableContent.lineTo( - x + w * minusLen, - y - ); - luckysheetTableContent.lineWidth = 1; - luckysheetTableContent.strokeStyle = format[0]; - luckysheetTableContent.stroke(); - luckysheetTableContent.closePath(); - } - } - } - - let pos_x = start_c + offsetLeft; - let pos_y = start_r + offsetTop + 1; - - luckysheetTableContent.save(); - luckysheetTableContent.beginPath(); - luckysheetTableContent.rect(pos_x , pos_y, cellWidth , cellHeight ); - luckysheetTableContent.clip(); - luckysheetTableContent.scale(Store.zoomRatio,Store.zoomRatio); - - let horizonAlignPos = (pos_x + space_width) ; //默认为1,左对齐 - if(horizonAlign == "0"){ //居中对齐 - horizonAlignPos = (pos_x + cellWidth / 2) - (textMetrics / 2); - } - else if(horizonAlign == "2"){ //右对齐 - horizonAlignPos = (pos_x + cellWidth - space_width) - textMetrics; - } - - let verticalCellHeight = cellHeight>oneLineTextHeight?cellHeight:oneLineTextHeight; - - let verticalAlignPos = (pos_y + verticalCellHeight - space_height) - oneLineTextHeight; //默认为2,下对齐 - let verticalAlignPos_text = (pos_y + verticalCellHeight - space_height) ; //文本垂直方向基准线 - luckysheetTableContent.textBaseline = "bottom"; - if(verticalAlign == "0"){ //居中对齐 - verticalAlignPos = (pos_y + verticalCellHeight / 2) - (oneLineTextHeight / 2); - - verticalAlignPos_text = (pos_y + verticalCellHeight / 2) ; - luckysheetTableContent.textBaseline = "middle"; - } - else if(verticalAlign == "1"){ //上对齐 - verticalAlignPos = (pos_y + space_height) ; - - verticalAlignPos_text = (pos_y + space_height) ; - luckysheetTableContent.textBaseline = "top"; - } - - verticalAlignPos = verticalAlignPos/Store.zoomRatio; - horizonAlignPos = horizonAlignPos/Store.zoomRatio; - verticalAlignPos_text = verticalAlignPos_text/Store.zoomRatio; - // pos_x = pos_x/Store.zoomRatio; - // pos_y = pos_y/Store.zoomRatio; - // space_width = space_width/Store.zoomRatio; - // cellHeight = cellHeight/Store.zoomRatio; - // oneLineTextHeight = oneLineTextHeight/Store.zoomRatio; - - //若单元格有条件格式图标集 - if(checksCF != null && checksCF["icons"] != null){ - let l = checksCF["icons"]["left"]; - let t = checksCF["icons"]["top"]; - - luckysheetTableContent.drawImage( - luckysheet_CFiconsImg, - l * 42, - t * 32, - 32, - 32, - pos_x/Store.zoomRatio , - verticalAlignPos, - oneLineTextHeight/Store.zoomRatio, - oneLineTextHeight/Store.zoomRatio - ); - - if(horizonAlign != "0" && horizonAlign != "2"){ //左对齐时 文本渲染空出一个图标的距离 - horizonAlignPos = horizonAlignPos + oneLineTextHeight/Store.zoomRatio; - } - } - - //单元格 文本颜色 - luckysheetTableContent.fillStyle = menuButton.checkstatus(Store.flowdata, r, c , "fc"); - - //若单元格有交替颜色 文本颜色 - if(checksAF != null && checksAF[0] != null){ - luckysheetTableContent.fillStyle = checksAF[0]; - } - //若单元格有条件格式 文本颜色 - if(checksCF != null && checksCF["textColor"] != null){ - luckysheetTableContent.fillStyle = checksCF["textColor"]; - } - - //单元格是否有删除线 - let cl = menuButton.checkstatus(Store.flowdata, r, c , "cl"); - - if(cell.tb == '2'){ - //自动换行 - // luckysheetTableContent.textBaseline = 'top'; //textBaseline以top计算 - //Text rotation,0: 0、1: 45 、2: -45、3 Vertical text、4: 90 、5: -90, - if(cell.ct!=null && cell.ct.t=="inlineStr" && cell.ct.sharedStrings!=null && cell.ct.sharedStrings.length>0){ - let strArr = [],lineMaxHeight=[]; - let sharedStrings = cell.ct.sharedStrings; - for(let i=0;i 1){ - vArr = value.split(""); - } - else{ - vArr.push(value); - } - - let textW_all = 0; //拆分后宽高度合计 - let textH_all = 0; - - for(let i = 0; i < vArr.length; i++){ - let textW = getMeasureText(vArr[i], luckysheetTableContent).width; - //luckysheetTableContent.measureText(vArr[i]).width; - let textH = oneLineTextHeight; - - // textW /= Store.zoomRatio; - // textH /= Store.zoomRatio; - - textW_all += textW/Store.zoomRatio; - textH_all += textH/Store.zoomRatio; - - let hAP = (pos_x + space_width) ; - if(horizonAlign == "0"){ - hAP = (pos_x + cellWidth / 2) - (textW / 2); - } - else if(horizonAlign == "2"){ - hAP = (pos_x + cellWidth - space_width) - textW; - } - - let vAP = (pos_y + cellHeight - space_height) - textH * vArr.length; - if(verticalAlign == "0"){ - vAP = (pos_y + cellHeight / 2) - (textH / 2) * vArr.length; - } - else if(verticalAlign == "1"){ - vAP = (pos_y + space_height) ; - } - - hAP = hAP / Store.zoomRatio; - vAP = vAP / Store.zoomRatio; - - luckysheetTableContent.fillText(vArr[i], hAP, (vAP + i * textH/Store.zoomRatio)); - } - - if(cl == "1" && !isRealNull(value)){ - let textW = textW_all / vArr.length; - let textH = textH_all; - - let hAP = (pos_x + space_width) ; - if(horizonAlign == "0"){ - hAP = (pos_x + cellWidth / 2) - (textW / 2); - } - else if(horizonAlign == "2"){ - hAP = (pos_x + cellWidth - space_width) - textW; - } - - let vAP = (pos_y + cellHeight - space_height) - textH; - if(verticalAlign == "0"){ - vAP = (pos_y + cellHeight / 2) - (textH / 2); - } - else if(verticalAlign == "1"){ - vAP = (pos_y + space_height) ; - } - - hAP = hAP / Store.zoomRatio; - vAP = vAP / Store.zoomRatio; - - luckysheetTableContent.beginPath(); - luckysheetTableContent.strokeStyle = "#000"; - luckysheetTableContent.moveTo( - hAP + textW / 2, - vAP - ); - luckysheetTableContent.lineTo( - hAP + textW / 2, - vAP + textH - ); - luckysheetTableContent.closePath(); - luckysheetTableContent.stroke(); - } - } - } - else if(cell.tr == "4" || cell.tr == "5"){ - let textW = oneLineTextHeight; - let textH = textMetrics; - - let hAP = (pos_x + space_width) ; - if(horizonAlign == "0"){ - hAP = (pos_x + cellWidth / 2) - (textW / 2); - } - else if(horizonAlign == "2"){ - hAP = (pos_x + cellWidth - space_width) - textW; - } - - let vAP = (pos_y + cellHeight - space_height) - textH; - if(verticalAlign == "0"){ - vAP = (pos_y + cellHeight / 2) - (textH / 2); - } - else if(verticalAlign == "1"){ - vAP = (pos_y + space_height) ; - } - - hAP = hAP / Store.zoomRatio; - vAP = vAP / Store.zoomRatio; - - //向下90(90 旋转) - if(tr == "4"){ - luckysheetTableContent.save(); - luckysheetTableContent.translate(hAP, vAP); - luckysheetTableContent.rotate(90 * Math.PI / 180); - luckysheetTableContent.translate(-hAP, -vAP); - luckysheetTableContent.fillText(value == null ? "" : value, hAP, vAP - textW/ Store.zoomRatio); - luckysheetTableContent.restore(); - } - - //向上90(-90 旋转) - if(tr == "5"){ - luckysheetTableContent.save(); - luckysheetTableContent.translate(hAP + textH/ Store.zoomRatio, vAP); - luckysheetTableContent.rotate(-90 * Math.PI / 180); - luckysheetTableContent.translate(-(hAP + textH/ Store.zoomRatio), -vAP); - luckysheetTableContent.fillText(value == null ? "" : value, hAP, vAP - textH/ Store.zoomRatio); - luckysheetTableContent.restore(); - } - - if(cl == "1" && !isRealNull(value)){ - luckysheetTableContent.beginPath(); - luckysheetTableContent.strokeStyle = "#000"; - luckysheetTableContent.moveTo(hAP + textW/ Store.zoomRatio / 2, vAP); - luckysheetTableContent.lineTo(hAP + textW/ Store.zoomRatio / 2, vAP + textH/ Store.zoomRatio); - luckysheetTableContent.closePath(); - luckysheetTableContent.stroke(); - } - } - } - else{ - //单元格有下钻属性,文本颜色变成超链接的颜色 - if(cell.dd != null){ - luckysheetTableContent.fillStyle = "#0000ff"; - - luckysheetTableContent.beginPath(); - luckysheetTableContent.strokeStyle = "#0000ff"; - luckysheetTableContent.moveTo( - horizonAlignPos, - verticalAlignPos + oneLineTextHeight - ); - luckysheetTableContent.lineTo( - horizonAlignPos + textMetrics, - verticalAlignPos + oneLineTextHeight - ); - luckysheetTableContent.stroke(); - luckysheetTableContent.closePath(); - } - - luckysheetTableContent.fillText(value == null ? "" : value, horizonAlignPos, verticalAlignPos_text); - - if(cl == "1" && !isRealNull(value)){ - luckysheetTableContent.beginPath(); - luckysheetTableContent.strokeStyle = "#000"; - luckysheetTableContent.moveTo( - horizonAlignPos, - verticalAlignPos + oneLineTextHeight / 2 / Store.zoomRatio - ); - luckysheetTableContent.lineTo( - horizonAlignPos + textMetrics/ Store.zoomRatio, - verticalAlignPos + oneLineTextHeight / 2 / Store.zoomRatio - ); - luckysheetTableContent.stroke(); - luckysheetTableContent.closePath(); - } - } - - luckysheetTableContent.restore(); - } - - if(cellOverflow_bd_r_render){ - //右边框 - if(!Store.luckysheetcurrentisPivotTable && !fillStyle && Store.showGridLines){ - luckysheetTableContent.beginPath(); - luckysheetTableContent.moveTo( - (end_c + offsetLeft - 2 + bodrder05), - (start_r + offsetTop) - ); - luckysheetTableContent.lineTo( - (end_c + offsetLeft - 2 + bodrder05), - (end_r + offsetTop) - ); - luckysheetTableContent.lineWidth = 1; - luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle; - luckysheetTableContent.stroke(); - luckysheetTableContent.closePath(); - } - } - - //下边框 - if(!Store.luckysheetcurrentisPivotTable && !fillStyle && Store.showGridLines){ - luckysheetTableContent.beginPath(); - luckysheetTableContent.moveTo( - (start_c + offsetLeft - 1), - (end_r + offsetTop - 2 + bodrder05) - ); - luckysheetTableContent.lineTo( - (end_c + offsetLeft - 1), - (end_r + offsetTop - 2 + bodrder05) - ); - luckysheetTableContent.lineWidth = 1; - luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle; - luckysheetTableContent.stroke(); - luckysheetTableContent.closePath(); - } -} - -//溢出单元格渲染 -let cellOverflowRender = function(r, c, stc, edc,luckysheetTableContent,scrollHeight,scrollWidth,offsetLeft,offsetTop,af_compute, cf_compute){ - //溢出单元格 起止行列坐标 - let start_r; - if (r == 0) { - start_r = -scrollHeight - 1; - } - else { - start_r = Store.visibledatarow[r - 1] - scrollHeight - 1; - } - - let end_r = Store.visibledatarow[r] - scrollHeight; - - let start_c; - if (stc == 0) { - start_c = -scrollWidth; - } - else { - start_c = Store.visibledatacolumn[stc - 1] - scrollWidth; - } - - let end_c = Store.visibledatacolumn[edc] - scrollWidth; - - // - let cell = Store.flowdata[r][c]; - let cellWidth = end_c - start_c - 2; - let cellHeight = end_r - start_r - 2; - let space_width = 2, space_height = 2; //宽高方向 间隙 - - let fontset = luckysheetfontformat(cell); - luckysheetTableContent.font = fontset; - // luckysheetTableContent.textBaseline = 'top'; - - //溢出单元格 值 - let value = getcellvalue(r, c, null, "m"); - if(value == null){ - value = getcellvalue(r, c); - } - - //文本单行 宽度和高度 - let measureText = getMeasureText(value, luckysheetTableContent); - //luckysheetTableContent.measureText(value); - let textMetrics = measureText.width; - let oneLineTextHeight = measureText.actualBoundingBoxDescent + measureText.actualBoundingBoxAscent; - - let pos_x = start_c + offsetLeft; - let pos_y = start_r + offsetTop + 1; - - luckysheetTableContent.save(); - luckysheetTableContent.beginPath(); - luckysheetTableContent.rect(pos_x, pos_y, cellWidth, cellHeight); - luckysheetTableContent.clip(); - luckysheetTableContent.scale(Store.zoomRatio,Store.zoomRatio); - - //溢出单元格 水平对齐 - let horizonAlign = menuButton.checkstatus(Store.flowdata, r, c, "ht"); - let horizonAlignPos = (pos_x + space_width) ; //默认为1,左对齐 - if(horizonAlign == "0"){ //居中对齐 - horizonAlignPos = (pos_x + cellWidth / 2) - (textMetrics / 2); - } - else if(horizonAlign == "2"){ //右对齐 - horizonAlignPos = (pos_x + cellWidth - space_width) - textMetrics; - } - - let verticalCellHeight = cellHeight>oneLineTextHeight?cellHeight:oneLineTextHeight; - //溢出单元格 垂直对齐 - let verticalAlign = menuButton.checkstatus(Store.flowdata, r, c, "vt"); - let verticalAlignPos = (pos_y + verticalCellHeight - space_height) - oneLineTextHeight; //默认为2,下对齐 - let verticalAlignPos_text = (pos_y + verticalCellHeight - space_height) ; //文本垂直方向基准线 - luckysheetTableContent.textBaseline = "bottom"; - if(verticalAlign == "0"){ //居中对齐 - verticalAlignPos = (pos_y + verticalCellHeight / 2) - (oneLineTextHeight / 2); - - verticalAlignPos_text = (pos_y + verticalCellHeight / 2) ; - luckysheetTableContent.textBaseline = "middle"; - } - else if(verticalAlign == "1"){ //上对齐 - verticalAlignPos = (pos_y + space_height) ; - - verticalAlignPos_text = (pos_y + space_height) ; - luckysheetTableContent.textBaseline = "top"; - } - - verticalAlignPos = verticalAlignPos/Store.zoomRatio; - horizonAlignPos = horizonAlignPos/Store.zoomRatio; - verticalAlignPos_text = verticalAlignPos_text/Store.zoomRatio; - - //交替颜色 - let checksAF = alternateformat.checksAF(r, c, af_compute); - //条件格式 - let checksCF = conditionformat.checksCF(r, c, cf_compute); - - //单元格 文本颜色 - luckysheetTableContent.fillStyle = menuButton.checkstatus(Store.flowdata, r, c , "fc"); - - //若单元格有交替颜色 文本颜色 - if(checksAF != null && checksAF[0] != null){ - luckysheetTableContent.fillStyle = checksAF[0]; - } - //若单元格有条件格式 文本颜色 - if(checksCF != null && checksCF["textColor"] != null){ - luckysheetTableContent.fillStyle = checksCF["textColor"]; - } - - luckysheetTableContent.fillText(value == null ? "" : value, horizonAlignPos, verticalAlignPos_text); - - luckysheetTableContent.restore(); - - //单元格是否有删除线 - let cl = menuButton.checkstatus(Store.flowdata, r, c , "cl"); - if(cl == "1" && !isRealNull(value)){ - luckysheetTableContent.beginPath(); - luckysheetTableContent.strokeStyle = "#000"; - luckysheetTableContent.moveTo( - horizonAlignPos, - verticalAlignPos + oneLineTextHeight / 2/Store.zoomRatio - ); - luckysheetTableContent.lineTo( - horizonAlignPos + textMetrics/Store.zoomRatio, - verticalAlignPos + oneLineTextHeight / 2/Store.zoomRatio - ); - luckysheetTableContent.stroke(); - luckysheetTableContent.closePath(); - } -} - -//获取表格渲染范围 溢出单元格 -function getCellOverflowMap(canvas, col_st, col_ed, row_st, row_end){ - let map = {}; - - let data = Store.flowdata; - - for(let r = row_st; r <= row_end; r++){ - for(let c = 0; c < data[r].length; c++){ - let cell = data[r][c]; - - if (Store.config["colhidden"] != null && Store.config["colhidden"][c] != null) { - continue - } - - if(cell != null && !isRealNull(cell.v) && cell.mc == null && cell.tb == '1'){ - let fontset = luckysheetfontformat(cell); - canvas.font = fontset; - - //水平对齐 - let horizonAlign = menuButton.checkstatus(data, r, c, "ht"); - - //文本宽度 - let value = getcellvalue(r, c, null, "m"); - if(value == null){ - value = getcellvalue(r, c); - } - let textMetrics = getMeasureText(value, canvas).width; + let textMetrics = getCellTextInfo(cell, canvas,{ + r:r, + c:c, + }).textWidthAll; //canvas.measureText(value).width; let start_c = c - 1 < 0 ? 0 : Store.visibledatacolumn[c - 1]; @@ -2839,7 +2013,7 @@ function cellTextRender(textInfo, ctx, option){ if(values==null){ return; } - console.log(textInfo, pos_x, pos_y, values[0].width, values[0].left, values[0].style); + console.log(textInfo, pos_x, pos_y, values[0].width, values[0].left, ctx); if(textInfo.rotate!=0 && textInfo.type!="verticalWrap"){ ctx.save(); diff --git a/src/global/getRowlen.js b/src/global/getRowlen.js index 66197e1..fb26a0c 100644 --- a/src/global/getRowlen.js +++ b/src/global/getRowlen.js @@ -35,57 +35,65 @@ function rowlenByRange(d, r1, r2, cfg) { } if(cell != null && cell.v != null){ - let fontset = luckysheetfontformat(cell); - canvas.font = fontset; - - let value = getcellvalue(r, c, d).toString(); //单元格文本 - let measureText = getMeasureText(value, canvas); - - let textMetrics = measureText.width; //文本宽度 - let oneLineTextHeight = measureText.actualBoundingBoxDescent + measureText.actualBoundingBoxAscent; - let spaceHeight = Math.ceil(oneLineTextHeight/3); - let computeRowlen; //计算行高 - let word_space_height = oneLineTextHeight/3; - if(cell.tb == "2"){ - //自动换行 - let cellWidth = colLocationByIndex(c)[1] - colLocationByIndex(c)[0] - 4; //单元格宽度 - - if(textMetrics > cellWidth){ - let strArr = []; //文本截断数组 - strArr = getCellTextSplitArr(value, strArr, cellWidth, canvas); - - computeRowlen = (oneLineTextHeight+word_space_height) * strArr.length + spaceHeight; - } - else{ - computeRowlen = oneLineTextHeight + spaceHeight; - } - } - else if(cell.tr != null){ - //单元格有旋转标示 - let tr = cell.tr; - - if(tr == "0"){ - //无旋转 - computeRowlen = oneLineTextHeight + spaceHeight; - } - else if(tr == "1" || tr == "2"){ - //向下倾斜(45 旋转)----向上倾斜(-45 旋转) - computeRowlen = 0.707 * (textMetrics + oneLineTextHeight) + spaceHeight; - } - else if(tr == "3"){ - //竖排文字 - computeRowlen = value.length * oneLineTextHeight + spaceHeight; - } - else if(tr == "4" || tr == "5"){ - //向下90(90 旋转)----向上90(-90 旋转) - computeRowlen = textMetrics + spaceHeight; - } - computeRowlen = Math.round(computeRowlen); - } - else{ - computeRowlen = oneLineTextHeight + spaceHeight; - } + let textInfo = getCellTextInfo(cell, canvas,{ + r:r, + c:c, + }); + + let computeRowlen = textInfo.textHeightAll; + + // let fontset = luckysheetfontformat(cell); + // canvas.font = fontset; + + // let value = getcellvalue(r, c, d).toString(); //单元格文本 + // let measureText = getMeasureText(value, canvas); + + // let textMetrics = measureText.width; //文本宽度 + // let oneLineTextHeight = measureText.actualBoundingBoxDescent + measureText.actualBoundingBoxAscent; + // let spaceHeight = Math.ceil(oneLineTextHeight/3); + // let computeRowlen; //计算行高 + // let word_space_height = oneLineTextHeight/3; + // if(cell.tb == "2"){ + // //自动换行 + // let cellWidth = colLocationByIndex(c)[1] - colLocationByIndex(c)[0] - 4; //单元格宽度 + + // if(textMetrics > cellWidth){ + // let strArr = []; //文本截断数组 + // strArr = getCellTextSplitArr(value, strArr, cellWidth, canvas); + + // computeRowlen = (oneLineTextHeight+word_space_height) * strArr.length + spaceHeight; + // } + // else{ + // computeRowlen = oneLineTextHeight + spaceHeight; + // } + // } + // else if(cell.tr != null){ + // //单元格有旋转标示 + // let tr = cell.tr; + + // if(tr == "0"){ + // //无旋转 + // computeRowlen = oneLineTextHeight + spaceHeight; + // } + // else if(tr == "1" || tr == "2"){ + // //向下倾斜(45 旋转)----向上倾斜(-45 旋转) + // computeRowlen = 0.707 * (textMetrics + oneLineTextHeight) + spaceHeight; + // } + // else if(tr == "3"){ + // //竖排文字 + // computeRowlen = value.length * oneLineTextHeight + spaceHeight; + // } + // else if(tr == "4" || tr == "5"){ + // //向下90(90 旋转)----向上90(-90 旋转) + // computeRowlen = textMetrics + spaceHeight; + // } + + // computeRowlen = Math.round(computeRowlen); + // } + // else{ + // computeRowlen = oneLineTextHeight + spaceHeight; + // } //比较计算高度和当前高度取最大高度 if(computeRowlen > currentRowLen){ @@ -95,7 +103,7 @@ function rowlenByRange(d, r1, r2, cfg) { } currentRowLen = currentRowLen/Store.zoomRatio; - + console.log(currentRowLen); if(currentRowLen != Store.defaultrowlen){ cfg_clone["rowlen"][r] = currentRowLen; } @@ -179,8 +187,18 @@ function getMeasureText(value, ctx, fontset){ commonWord = "田"; } let oneLineTextHeight = menuButton.getTextSize(commonWord, ctx.font)[1]*0.8; - cache.actualBoundingBoxDescent = oneLineTextHeight/2; - cache.actualBoundingBoxAscent = oneLineTextHeight/2; + if(ctx.textBaseline=="top"){ + cache.actualBoundingBoxDescent = oneLineTextHeight; + cache.actualBoundingBoxAscent = 0; + } + else if(ctx.textBaseline=="middle"){ + cache.actualBoundingBoxDescent = oneLineTextHeight/2; + cache.actualBoundingBoxAscent = oneLineTextHeight/2; + } + else{ + cache.actualBoundingBoxDescent = 0; + cache.actualBoundingBoxAscent = oneLineTextHeight; + } //console.log(value, oneLineTextHeight, measureText.actualBoundingBoxDescent+measureText.actualBoundingBoxAscent,ctx.font); } @@ -206,11 +224,29 @@ function isSupportBoundingBox(ctx){ // let measureTextCache = {}, measureTextCacheTimeOut = null; // option {cellWidth,cellHeight,space_width,space_height} function getCellTextInfo(cell , ctx, option){ - // let cell = Store.flowdata[r][c]; let cellWidth = option.cellWidth; let cellHeight = option.cellHeight; + let isMode = "", isModeSplit = ""; + if(cellWidth==null){ + isMode = "onlyWidth"; + isModeSplit = "_"; + } + let textInfo = Store.measureTextCellInfoCache[option.r + "_" + option.c + isModeSplit + isMode]; + if(textInfo != null){ + return textInfo; + } + + // let cell = Store.flowdata[r][c]; let space_width = option.space_width, space_height = option.space_height; //宽高方向 间隙 + if(space_width==null){ + space_width = 2; + } + + if(space_height==null){ + space_height = 2; + } + //水平对齐 let horizonAlign = menuButton.checkstatusByCell(cell, "ht"); //垂直对齐 @@ -352,6 +388,14 @@ function getCellTextInfo(cell , ctx, option){ textW_all += colMaxW; textH_all = Math.max(textH_all, columnHeight); } + + textContent.type = "verticalWrap"; + textContent.textWidthAll = textW_all; + textContent.textHeightAll = textH_all; + + if(isMode=="onlyWidth"){ + return textContent; + } let cumColumnWidth = 0; for(let i = 0; i < textH_all_ColumnHeight.length; i++){ @@ -390,10 +434,6 @@ function getCellTextInfo(cell , ctx, option){ cumColumnWidth+=columnWidth; } - - textContent.type = "verticalWrap"; - textContent.textWidthAll = textW_all; - textContent.textHeightAll = textH_all; } else{ let supportBoundBox = isSupportBoundingBox(ctx); @@ -416,8 +456,8 @@ function getCellTextInfo(cell , ctx, option){ textContent.rotate = rt; rt = Math.abs(rt); - let anchor = 0, preHeight = 0, preWidth=0, preStr, preTextHeight, preTextWidth; - for(let i = 1; i <= value.length; i++){ + let anchor = 0, preHeight = 0, preWidth=0, preStr, preTextHeight, preTextWidth, i=0; + while(i <= value.length){ let str = value.substring(anchor, i); let measureText = getMeasureText(str, ctx); let textWidth = measureText.width; @@ -429,12 +469,10 @@ function getCellTextInfo(cell , ctx, option){ // textW_all += textW; - if(text_all_split[splitIndex]==null){ - text_all_split[splitIndex]= []; - } - if(rt!=0){//rotate - if((height+space_height)>cellHeight){ + console.log("all",anchor, i , str); + if((height+space_height)>cellHeight && text_all_split[splitIndex]!=null){ + console.log("cut",anchor, i , str); anchor = i-1; text_all_split[splitIndex].push({ @@ -454,7 +492,10 @@ function getCellTextInfo(cell , ctx, option){ splitIndex +=1; } else if(i== value.length){ - + console.log("last",anchor, i , str); + if(text_all_split[splitIndex]==null){ + text_all_split[splitIndex]= []; + } text_all_split[splitIndex].push({ content:str, style:fontset, @@ -468,10 +509,17 @@ function getCellTextInfo(cell , ctx, option){ asc:measureText.actualBoundingBoxAscent, desc:measureText.actualBoundingBoxDescent }); + break; + } + else{ + if(text_all_split[splitIndex]==null){ + text_all_split[splitIndex]= []; + } + i++; } } else{//plain - if((width+space_width)>cellWidth){ + if((width+space_width)>cellWidth && text_all_split[splitIndex]!=null){ anchor = i-1; @@ -490,7 +538,9 @@ function getCellTextInfo(cell , ctx, option){ splitIndex +=1; } else if(i== value.length){ - + if(text_all_split[splitIndex]==null){ + text_all_split[splitIndex]= []; + } text_all_split[splitIndex].push({ content:str, style:fontset, @@ -502,6 +552,14 @@ function getCellTextInfo(cell , ctx, option){ asc:measureText.actualBoundingBoxAscent, desc:measureText.actualBoundingBoxDescent }); + + break; + } + else{ + if(text_all_split[splitIndex]==null){ + text_all_split[splitIndex]= []; + } + i++; } } @@ -514,20 +572,19 @@ function getCellTextInfo(cell , ctx, option){ } let split_all_size = []; - console.log(splitIndex, text_all_split); + // console.log(splitIndex, text_all_split); let splitLen = Object.keys(text_all_split).length; for(let i = 0; i < splitLen; i++){ let splitLists = text_all_split[i]; if(splitLists==null){ continue; } - let sWidth = 0, sHeight=0, textHeight=0; + let sWidth = 0, sHeight=0; for(let s=0;s