繁体   English   中英

画布绘图很慢

[英]Canvas drawing is very slow

我想用工作正常的标记显示比例。 最重要的是,我还想用红色指示器在比例尺中显示鼠标位置。

因此,我在运行应用程序时绘制画布,然后在更改鼠标位置时重新绘制整个画布。

我是画布的新手,不明白我的代码有什么问题。 我一直试图解决它,但没有运气。

问题可能出在这个函数中,

 function drawBlackMarkers(y, coordinateMeasurment){
    const markHightY = scaleTextPadding.initial;
    ctxLeft.moveTo(coordinateMeasurment, y + markHightY);
    ctxLeft.lineTo(completeMarkHight, y + markHightY);
  }

我有一个很大的for 循环意味着要经过很多次迭代,在该循环中我多次调用drawBlackMarkers函数,如下所示。

function setMarkers(initialValY, rangeValY, coordinateMeasurmentr, divisableVal,
    scaleCountStartValueOfY, scaleCountRangeValueOfY) {
    let count = 0;
    // re-modifying scale staring and ending values based on zoom factor
    const scaleInceremnt = scaleIncementValue;
    for (let y = (initialValY), scaleCountY = scaleCountStartValueOfY;
      y <= (rangeValY) && scaleCountY <= scaleCountRangeValueOfY;
      y += scaleInceremnt, scaleCountY += incrementFactor) {


      switch (count) {
        case displayScale.starting:
          coordinateMeasurment = marktype.bigMark; count++;
          const scaleValY = scaleCountY - divisableVal;

          ctxLeft.strokeStyle = colors.black;

          ctxLeft.font = scaleNumberFont;
          const size = ctxLeft.measureText(scaleValY.toString());
          ctxLeft.save();
          const textX = coordinateMeasurment + ((size.width) / 2);
          const textY = y - scaleTextPadding.alignment;
          ctxLeft.translate(textX, textY);
          ctxLeft.rotate(-Math.PI / 2);
          ctxLeft.translate(-textX, -textY);
          ctxLeft.fillText(scaleValY.toString(), coordinateMeasurment, y - scaleTextPadding.complete);
          ctxLeft.restore();
          break;
        case displayScale.middle:
          coordinateMeasurment = marktype.middleMark; count++;
          break;
        case displayScale.end:
          coordinateMeasurment = marktype.smallMark; count = 0;
          break;
        default:
          coordinateMeasurment = marktype.smallMark; count++;
          break;
      }

      // to draw scale lines on canvas
  // drawBlackMarkers(y, coordinateMeasurment);      
    }
  }

请检查这个: http : //jsfiddle.net/3v5nt7fe/1/

问题是如果我注释drawBlackMarkers函数调用,鼠标坐标更新非常快,但如果我取消注释,更新位置需要很长时间。

我真的需要帮助来解决这个问题。

这不是drawBlackMarkers本身,而是这个:

for (let y = (initialValY), scaleCountY = scaleCountStartValueOfY;
  y <= (rangeValY) && scaleCountY <= scaleCountRangeValueOfY;
  y += scaleInceremnt, scaleCountY += incrementFactor) {

这种情况不断增加,发生了 640,000 次。 你可以这样写:

  // to draw scale lines on canvas
  // drawBlackMarkers(y, coordinateMeasurment);
  console.log(y);

并查看控制台结果。

所以那个 for 循环做的很少,因为它大部分都在 switch 语句后面,当它执行这个简单的drawBlackMarkers时,它会显示该循环的真实成本。 rangeValY是 640,000,这意味着画布上下文必须构建的路径是巨大的。

因此,要解决此问题,您必须找到一种方法来改善该问题。

这是做了很多不必要的工作

屏幕高度不是 64000 像素。 您想要计算视口,并且只绘制视口中的内容。

您的函数 drawBlackMarkers 不是罪魁祸首。 在此之前系统非常缓慢,它只是添加了一个要绘制的东西。 是压死骆驼的稻草。

通过减少您正在绘制的内容的长度,您可以很容易地避免浪费的 CPU 周期。

在这个版本中,我所做的只是重新启用 drawBlackMarkers,并缩小画布。

 const CANVAS_WIDTH = 2000; const CANVAS_HEIGHT = 50; const completeMarkHight = 15; const divisibleValue = 0; const scaleIncementValue = 10; const scaleTextPadding = { initial: 0, middle: 5, end: 10, complete: 15, alignment: 18 }; const displayScale = { starting: 0, middle: 5, end: 9 }; const colors = { red: '#FF0000', white: '#D5D6D7', black: '#181c21' }; const marktype = { bigMark: 0, middleMark: 5, smallMark: 10 }; const startingInitialOrigin = { x: 0, y: 0 }; const scaleNumberFont = '10px Titillium Web Regular'; const defaultZoomLevel = 100; const markingGap = {level1: 400, level2: 200, level3: 100, level4: 50, level5: 20, level6: 10 }; const zoomScaleLevel = {level0: 0, level1: 25, level2: 50, level3: 100, level4: 200, level5: 500, level6: 1000}; var $canvas = $('#canvas'); var ctxLeft = $canvas[0].getContext('2d'); var mousePositionCoordinates; var pagePositions = { x: 100, y:0 }; var remainderX; var remainderY; var scaleCountRemainderX; var scaleCountRemainderY; var zoomFactor; var zoomScale; var zoomLevel; var multiplyFactor; var incrementFactor; var markingDistance; var timetaken=0; ctxLeft.fillStyle = colors.white; function render() { clear(); ctxLeft.beginPath(); zoomScale = 1000; zoomLevel = 1000; zoomFactor = zoomLevel / defaultZoomLevel; markingDistance = markingGap.level6; multiplyFactor = markingDistance / defaultZoomLevel; incrementFactor = markingDistance / scaleIncementValue; renderVerticalRuler(startingInitialOrigin.y); } function renderVerticalRuler(posY) { const initialValY = - posY / multiplyFactor; const rangeValY = (CANVAS_WIDTH - posY) / multiplyFactor; const initialValOfYwithMultiplyFactor = -posY; const rangeValOfYwithMultiplyFactor = (CANVAS_WIDTH - posY); // to adjust scale count get remainder value based on marking gap scaleCountRemainderY = initialValOfYwithMultiplyFactor % markingDistance; const scaleCountStartValueOfY = initialValOfYwithMultiplyFactor - scaleCountRemainderY; const scaleCountRangeValueOfY = rangeValOfYwithMultiplyFactor - scaleCountRemainderY; // to get orgin(0,0) values remainderY = initialValY % 100; const translateY = (posY / multiplyFactor) - remainderY; ctxLeft.translate(origin.x, translateY); // x,y const coordinateMeasurment = 0; const t0 = performance.now(); setMarkers(initialValY, rangeValY, coordinateMeasurment, divisibleValue, scaleCountStartValueOfY, scaleCountRangeValueOfY); const t1 = performance.now() console.log("it took " + (t1 - t0) + " milliseconds."); ctxLeft.stroke(); ctxLeft.closePath(); } function setMarkers(initialValY, rangeValY, coordinateMeasurmentr, divisableVal, scaleCountStartValueOfY, scaleCountRangeValueOfY) { let count = 0; // re-modifying scale staring and ending values based on zoom factor const scaleInceremnt = scaleIncementValue; for (let y = (initialValY), scaleCountY = scaleCountStartValueOfY; y <= (rangeValY) && scaleCountY <= scaleCountRangeValueOfY; y += scaleInceremnt, scaleCountY += incrementFactor) { switch (count) { case displayScale.starting: coordinateMeasurment = marktype.bigMark; count++; const scaleValY = scaleCountY - divisableVal; ctxLeft.strokeStyle = colors.black; ctxLeft.font = scaleNumberFont; const size = ctxLeft.measureText(scaleValY.toString()); ctxLeft.save(); const textX = coordinateMeasurment + ((size.width) / 2); const textY = y - scaleTextPadding.alignment; ctxLeft.translate(textX, textY); ctxLeft.rotate(-Math.PI / 2); ctxLeft.translate(-textX, -textY); ctxLeft.fillText(scaleValY.toString(), coordinateMeasurment, y - scaleTextPadding.complete); ctxLeft.restore(); break; case displayScale.middle: coordinateMeasurment = marktype.middleMark; count++; break; case displayScale.end: coordinateMeasurment = marktype.smallMark; count = 0; break; default: coordinateMeasurment = marktype.smallMark; count++; break; } // to draw scale lines on canvas drawBlackMarkers(y, coordinateMeasurment); } } function drawBlackMarkers(y, coordinateMeasurment){ const markHightY = scaleTextPadding.initial; ctxLeft.moveTo(coordinateMeasurment, y + markHightY); ctxLeft.lineTo(completeMarkHight, y + markHightY); } function clear() { ctxLeft.resetTransform(); ctxLeft.clearRect(origin.x, origin.y, CANVAS_HEIGHT, CANVAS_WIDTH); } render(); $('.canvas-container').mousemove(function(e) { mousePositionCoordinates = {x:e.clientX, y:e.clientY}; render(); // SHOW RED INDICATOR ctxLeft.beginPath(); ctxLeft.strokeStyle = colors.red; // show mouse indicator ctxLeft.lineWidth = 2; // to display purple indicator based on zoom level const mouseX = mousePositionCoordinates.x * zoomFactor; const mouseY = mousePositionCoordinates.y * zoomFactor; const markHightY =scaleTextPadding.initial + this.remainderY; ctxLeft.moveTo(marktype.bigMark, e.clientY ); ctxLeft.lineTo(completeMarkHight, e.clientY); ctxLeft.stroke(); $('.mouselocation').text(`${mousePositionCoordinates.x},${mousePositionCoordinates.y}`); });
 body, html{ width: 100000px; height:100000px; } .canvas-container{ width:100%; height:100%; } .canvasLeft { position: absolute; border:1px solid black; background: grey; border-top: none; z-index: 1; top:0 } .mouselocation{ position: fixed; right: 0px; top: 50px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <div class="canvas-container"> <canvas id="canvas" class="canvasLeft" width="30" height="2000"></canvas> </div> <div class="mouselocation"> </div>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM