Vẽ canvas rất chậm
Tôi muốn hiển thị tỷ lệ với các dấu hiệu đang hoạt động tốt. Trên hết, tôi cũng muốn hiển thị vị trí chuột trong thang đo với chỉ báo màu đỏ.
Vì vậy, tôi vẽ canvas khi chạy ứng dụng và sau đó tôi vẽ lại toàn bộ canvas khi vị trí chuột bị thay đổi.
Tôi mới sử dụng canvas và không hiểu mã của mình có gì sai. Tôi đã cố gắng giải quyết nó nhưng không may mắn.
Vấn đề có thể là trong chức năng này,
function drawBlackMarkers(y, coordinateMeasurment){
const markHightY = scaleTextPadding.initial;
ctxLeft.moveTo(coordinateMeasurment, y + markHightY);
ctxLeft.lineTo(completeMarkHight, y + markHightY);
}
Tôi đang gặp một vòng lặp for lớn có nghĩa là có rất nhiều lần lặp phải trải qua và trong vòng lặp đó, tôi gọi hàm drawBlackMarkers nhiều lần như hình dưới đây.
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);
}
}
Làm ơn kiểm tra cái này : http://jsfiddle.net/3v5nt7fe/1/
Vấn đề là nếu tôi nhận xét cuộc gọi hàm drawBlackMarkers , cập nhật phối hợp chuột rất nhanh nhưng nếu tôi bỏ ghi chú, thì phải mất quá nhiều thời gian để cập nhật vị trí.
Tôi thực sự cần giúp đỡ để giải quyết vấn đề này.
Trả lời
Nó không phải là drawBlackMarkerschính nó, nó là thế này:
for (let y = (initialValY), scaleCountY = scaleCountStartValueOfY;
y <= (rangeValY) && scaleCountY <= scaleCountRangeValueOfY;
y += scaleInceremnt, scaleCountY += incrementFactor) {
Điều này không ngừng tăng lên và xảy ra 640.000 lần. Bạn có thể cho biết đó là trường hợp bằng cách viết:
// to draw scale lines on canvas
// drawBlackMarkers(y, coordinateMeasurment);
console.log(y);
và xem kết quả bảng điều khiển.
Vì vậy, vòng lặp for đó thực hiện rất ít, bởi vì hầu hết nó nằm sau một câu lệnh switch, và khi nó thực hiện điều này đơn giản drawBlackMarkersbên ngoài nó cho thấy chi phí thực của vòng lặp đó. rangeValYlà 640.000, có nghĩa là đường dẫn mà ngữ cảnh canvas phải tạo là rất lớn.
Vì vậy, để khắc phục điều này, bạn phải tìm cách cải thiện vấn đề đó.
Điều này đang làm rất nhiều công việc không cần thiết
Màn hình không có chiều cao 64000 pixel. Bạn muốn tính toán khung nhìn và chỉ vẽ những gì có trong khung nhìn.
Hàm drawBlackMarkers của bạn không phải là thủ phạm. Hệ thống trước đó rất chậm, nó chỉ đơn giản là thêm một thứ nữa cần được vẽ. Chính rơm đã làm gãy lưng lạc đà.
Bằng cách giảm độ dài của những gì bạn đang vẽ, bạn có thể rất dễ dàng tránh được các chu kỳ CPU bị lãng phí.
Trong phiên bản này, tất cả những gì tôi đã làm là bật lại drawBlackMarkers và thu nhỏ canvas.
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>