如何解决画布绘制非常慢
我想显示带有刻度的刻度尺,这很好用。最重要的是,我还想用红色指示器在刻度中显示鼠标位置。
因此,我在运行应用程序时绘制画布,然后在更改鼠标位置时重新绘制整个画布。
我是新手,不了解我的代码有什么问题。我一直在试图解决它,但是没有运气。
此函数中可能存在问题
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,这意味着canvas上下文必须构造的路径很大。
因此,要解决此问题,您必须找到一种缓解该问题的方法。
,这正在做很多不必要的工作
屏幕的高度不是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,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,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,coordinateMeasurmentr,divisableVal,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(),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>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。