Skip to content

Commit 1e34ec2

Browse files
committed
pre-rendering optimizations
1 parent 3216f23 commit 1e34ec2

File tree

1 file changed

+65
-37
lines changed

1 file changed

+65
-37
lines changed

script.js

+65-37
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ var color_choices = [
1616
var radiansPer45Degrees = Math.PI / 4;
1717

1818
var canvas = document.getElementById('canvas');
19-
var ctx = canvas.getContext('2d');
19+
var mainCtx = canvas.getContext('2d');
20+
var offScreenCanvas = document.createElement('canvas');
21+
var offScreenCtx = offScreenCanvas.getContext('2d');
22+
offScreenCanvas.width = canvas.width;
23+
offScreenCanvas.height = canvas.height;
2024

2125
var img = new Image();
2226
var rgb_color = "#FF00FF";
@@ -38,14 +42,19 @@ var showNormalized = false;
3842
var modeMessage = document.querySelector('#mode');
3943
// var coords = document.querySelector('#coords');
4044

45+
function blitCachedCanvas() {
46+
mainCtx.clearRect(0, 0, canvas.width, canvas.height);
47+
mainCtx.drawImage(offScreenCanvas, 0, 0);
48+
}
49+
4150
function clipboard(selector) {
4251
var copyText = document.querySelector(selector).innerText;
4352
navigator.clipboard.writeText(copyText);
4453
}
4554

4655
function clearDrawings() {
47-
ctx.clearRect(0, 0, canvas.width, canvas.height);
48-
ctx.drawImage(img, 0, 0);
56+
offScreenCtx.clearRect(0, 0, offScreenCanvas.width, offScreenCanvas.height);
57+
blitCachedCanvas();
4958
}
5059

5160
function isClockwise(vertices) {
@@ -80,9 +89,8 @@ function onPathClose() {
8089
masterPoints.push(points);
8190
points = [];
8291
masterColors.push(rgb_color);
83-
clearDrawings();
84-
drawAllPolygons();
85-
92+
drawAllPolygons(offScreenCtx);
93+
blitCachedCanvas();
8694
rgb_color = color_choices[(masterColors.length) % (color_choices.length)];
8795
}
8896

@@ -94,15 +102,18 @@ img.onload = function() {
94102
canvas.style.height = img.height * scaleFactor + 'px';
95103
canvas.width = img.width;
96104
canvas.height = img.height;
97-
ctx.drawImage(img, 0, 0);
105+
offScreenCanvas.width = img.width;
106+
offScreenCanvas.height = img.height;
107+
offScreenCtx.drawImage(img, 0, 0);
108+
blitCachedCanvas();
98109
};
99110

100-
function makeLine(x1, y1, x2, y2) {
111+
function makeLine(ctx, x1, y1, x2, y2) {
101112
ctx.moveTo(x1, y1);
102113
ctx.lineTo(x2, y2);
103114
}
104115

105-
function drawNode(x, y, stroke = null) {
116+
function drawNode(ctx, x, y, stroke = null) {
106117
if (stroke) {
107118
ctx.strokeStyle = stroke;
108119
}
@@ -121,20 +132,22 @@ function getScaledCoords(e) {
121132
return [x / scaleFactor, y / scaleFactor];
122133
}
123134

124-
function drawAllPolygons () {
135+
function drawAllPolygons(ctx) {
136+
ctx.clearRect(0, 0, canvas.width, canvas.height);
137+
ctx.drawImage(img, 0, 0);
125138
// draw polygons as subpaths and fill all at once
126139
// we do this to avoid overlapping polygons becoming opaque
127140
ctx.beginPath();
128141
ctx.fillStyle = fill_color;
129142
for (var i = 0; i < masterPoints.length; i++) {
130143
var newpoints = masterPoints[i];
131144
for (var j = 1; j < newpoints.length; j++) {
132-
makeLine(newpoints[j - 1][0], newpoints[j - 1][1], newpoints[j][0], newpoints[j][1]);
145+
makeLine(ctx, newpoints[j - 1][0], newpoints[j - 1][1], newpoints[j][0], newpoints[j][1]);
133146
ctx.moveTo(newpoints[0][0], newpoints[0][1]);
134147
for (var j = 1; j < newpoints.length; j++) {
135148
ctx.lineTo(newpoints[j][0], newpoints[j][1]);
136149
}
137-
makeLine(newpoints[newpoints.length - 1][0], newpoints[newpoints.length - 1][1], newpoints[0][0], newpoints[0][1]);
150+
makeLine(ctx, newpoints[newpoints.length - 1][0], newpoints[newpoints.length - 1][1], newpoints[0][0], newpoints[0][1]);
138151
}
139152
}
140153
ctx.fill();
@@ -147,7 +160,7 @@ function drawAllPolygons () {
147160

148161
ctx.beginPath();
149162
for (var j = 1; j < newpoints.length; j++) {
150-
makeLine(newpoints[j - 1][0], newpoints[j - 1][1], newpoints[j][0], newpoints[j][1]);
163+
makeLine(ctx, newpoints[j - 1][0], newpoints[j - 1][1], newpoints[j][0], newpoints[j][1]);
151164
ctx.moveTo(newpoints[0][0], newpoints[0][1]);
152165
for (var j = 1; j < newpoints.length; j++) {
153166
ctx.lineTo(newpoints[j][0], newpoints[j][1]);
@@ -158,12 +171,12 @@ function drawAllPolygons () {
158171

159172
// draw arc around each point
160173
for (var j = 0; j < newpoints.length; j++) {
161-
drawNode(newpoints[j][0], newpoints[j][1]);
174+
drawNode(ctx, newpoints[j][0], newpoints[j][1]);
162175
}
163176
}
164177
}
165178

166-
function getParentPoints () {
179+
function getParentPoints() {
167180
var parentPoints = [];
168181
for (var i = 0; i < masterPoints.length; i++) {
169182
parentPoints.push(masterPoints[i]);
@@ -240,31 +253,35 @@ canvas.addEventListener('mousemove', function(e) {
240253
xcoord.innerHTML = x;
241254
ycoord.innerHTML = y;
242255

256+
var ctx = mainCtx;
257+
ctx.lineWidth = 5;
258+
ctx.lineJoin = 'bevel';
259+
ctx.fillStyle = 'white';
260+
243261
if (canvas.style.cursor == 'crosshair') {
244-
clearDrawings();
245-
drawAllPolygons();
262+
blitCachedCanvas();
246263

247264
for (var i = 0; i < points.length - 1; i++) {
248265
ctx.strokeStyle = rgb_color;
249266
ctx.beginPath();
250267
ctx.lineJoin = 'bevel';
251-
makeLine(points[i][0], points[i][1], points[i + 1][0], points[i + 1][1]);
268+
makeLine(ctx, points[i][0], points[i][1], points[i + 1][0], points[i + 1][1]);
252269
ctx.closePath();
253270
ctx.stroke();
254271

255-
drawNode(points[i][0], points[i][1]);
272+
drawNode(ctx, points[i][0], points[i][1]);
256273
}
257274

258275

259276
if ((points.length > 0 && drawMode == "polygon") || (points.length > 0 && points.length < 2 && drawMode == "line")) {
260277
ctx.beginPath();
261278
ctx.lineJoin = 'bevel';
262279
ctx.strokeStyle = rgb_color;
263-
makeLine(points[points.length - 1][0], points[points.length - 1][1], x, y);
280+
makeLine(ctx, points[points.length - 1][0], points[points.length - 1][1], x, y);
264281
ctx.closePath();
265282
ctx.stroke();
266283

267-
drawNode(points[i][0], points[i][1]);
284+
drawNode(ctx, points[i][0], points[i][1]);
268285
}
269286
}
270287
});
@@ -297,8 +314,11 @@ canvas.addEventListener('drop', function(e) {
297314
canvas.style.height = img.height * scaleFactor + 'px';
298315
canvas.width = img.width;
299316
canvas.height = img.height;
317+
offScreenCanvas.width = img.width;
318+
offScreenCanvas.height = img.height;
300319
canvas.style.borderRadius = '10px';
301-
ctx.drawImage(img, 0, 0);
320+
offScreenCtx.drawImage(img, 0, 0);
321+
blitCachedCanvas();
302322
};
303323
// show coords
304324
// document.getElementById('coords').style.display = 'inline-block';
@@ -382,7 +402,7 @@ canvas.addEventListener('click', function(e) {
382402

383403
points.push([x, y]);
384404

385-
drawNode(x, y, rgb_color);
405+
drawNode(mainCtx, x, y, rgb_color);
386406

387407
if(drawMode == "line" && points.length == 2) {
388408
onPathClose();
@@ -432,8 +452,7 @@ document.addEventListener('keydown', function(e) {
432452
}
433453
})
434454

435-
function update() {
436-
drawAllPolygons();
455+
function rewritePoints() {
437456
var parentPoints = getParentPoints();
438457
writePoints(parentPoints);
439458
}
@@ -443,26 +462,32 @@ function highlightButtonInteraction (buttonId) {
443462
setTimeout(() => document.querySelector(buttonId).classList.remove('active'), 100);
444463
}
445464

446-
function undo () {
465+
function undo() {
447466
highlightButtonInteraction('#undo');
448467

449468
if (points.length > 0) {
450469
points.pop();
451-
clearDrawings();
452-
update();
470+
blitCachedCanvas();
471+
rewritePoints();
453472

454473
if(points.length === 0){
455474
return;
456475
}
457476

477+
var ctx = mainCtx;
458478
ctx.strokeStyle = rgb_color;
459-
var i = 0;
460-
for (; i < points.length - 1; i++) {
461-
makeLine(points[i][0], points[i][1], points[i + 1][0], points[i + 1][1]);
462-
ctx.stroke();
463-
drawNode(points[i][0], points[i][1]);
479+
ctx.fillStyle = 'white';
480+
if (points.length === 1) {
481+
drawNode(ctx, points[0][0], points[0][1]);
482+
}
483+
else {
484+
drawNode(ctx, points[0][0], points[0][1]);
485+
for (var i = 0; i < points.length - 1; i++) {
486+
makeLine(ctx, points[i][0], points[i][1], points[i + 1][0], points[i + 1][1]);
487+
ctx.stroke();
488+
drawNode(ctx, points[i + 1][0], points[i + 1][1]);
489+
}
464490
}
465-
drawNode(points[i][0], points[i][1]);
466491
}
467492
}
468493

@@ -473,8 +498,8 @@ document.querySelector('#undo').addEventListener('click', function(e) {
473498
function discardCurrentPolygon () {
474499
highlightButtonInteraction('#discard-current');
475500
points = [];
476-
clearDrawings();
477-
update();
501+
blitCachedCanvas();
502+
rewritePoints();
478503
}
479504

480505
document.querySelector('#discard-current').addEventListener('click', function(e) {
@@ -483,7 +508,10 @@ document.querySelector('#discard-current').addEventListener('click', function(e)
483508

484509
function clearAll() {
485510
highlightButtonInteraction('#clear')
486-
clearDrawings();
511+
mainCtx.clearRect(0, 0, canvas.width, canvas.height);
512+
offScreenCtx.clearRect(0, 0, offScreenCanvas.width, offScreenCanvas.height);
513+
mainCtx.drawImage(img, 0, 0);
514+
offScreenCtx.drawImage(img, 0, 0);
487515
points = [];
488516
masterPoints = [];
489517
masterColors = [];

0 commit comments

Comments
 (0)