paint-by-numbers

Relaxing paint-by-numbers game  https://p.ce9e.org/paint-by-numbers/
git clone https://git.ce9e.org/paint-by-numbers.git

commit
cea83841076d014fa7326c9da72dde9b307e036c
parent
59f88bffdb05e19ee651d79f28808143a5ba5992
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2023-02-13 05:40
refactor: view module

Diffstat

M paint.js 85 ++++++++++++++++++++-----------------------------------------
A utils.js 35 +++++++++++++++++++++++++++++++++++
A view.js 37 +++++++++++++++++++++++++++++++++++++

3 files changed, 99 insertions, 58 deletions


diff --git a/paint.js b/paint.js

@@ -1,19 +1,18 @@
    1     1 import { Frame, PXSIZE } from './frame.js';
   -1     2 import { View } from './view.js';
   -1     3 import * as utils from './utils.js';
    2     4 
    3     5 var input = document.querySelector('input');
    4     6 var palette = document.querySelector('.palette');
    5     7 
    6     8 var canvas = document.querySelector('canvas');
    7    -1 var ctx = canvas.getContext('2d');
    8     9 
    9    10 var frame = new Frame();
   -1    11 var view = new View(canvas, frame);
   10    12 
   11    13 var data;
   12    14 var pencil = 0;
   13    15 
   14    -1 var zoom = 1;
   15    -1 var dx = 0;
   16    -1 var dy = 0;
   17    16 var speed_x = 0;
   18    17 var speed_y = 0;
   19    18 
@@ -42,19 +41,6 @@ var makeContrast = function(a) {
   42    41     return l > 0.18 ? '#000' : '#fff';
   43    42 };
   44    43 
   45    -1 var onAnimation = function(fn) {
   46    -1     var called = false;
   47    -1     return (...args) => {
   48    -1         if (!called) {
   49    -1             called = true;
   50    -1             window.requestAnimationFrame(() => {
   51    -1                 fn(...args);
   52    -1                 called = false;
   53    -1             });
   54    -1         }
   55    -1     };
   56    -1 };
   57    -1 
   58    44 var file2img = function(file) {
   59    45     return new Promise((resolve, reject) => {
   60    46         var img = new Image();
@@ -132,64 +118,47 @@ input.addEventListener('change', () => {
  132   118             });
  133   119         }
  134   120         setPencil(0);
  135    -1         resizeCanvas();
   -1   121         view.refreshSize();
  136   122 
  137    -1         zoom = canvas.height / frame.canvas.height * 0.8;
  138    -1         dx = (canvas.width - frame.canvas.width * zoom) / 2;
  139    -1         dy = (canvas.height - frame.canvas.height * zoom) / 2;
   -1   123         view.zoom = view.canvas.height / frame.canvas.height * 0.8;
   -1   124         view.dx = (view.canvas.width - frame.canvas.width * view.zoom) / 2;
   -1   125         view.dy = (view.canvas.height - frame.canvas.height * view.zoom) / 2;
  140   126 
  141   127         speed_x = 0;
  142   128         speed_y = 0;
  143   129 
  144    -1         render();
   -1   130         view.render();
  145   131     });
  146   132 });
  147   133 
  148    -1 var resizeCanvas = function() {
  149    -1     var rect = canvas.getBoundingClientRect();
  150    -1 
  151    -1     dx += (rect.width - canvas.width) / 2;
  152    -1     dy += (rect.height - canvas.height) / 2;
  153    -1 
  154    -1     canvas.width = rect.width;
  155    -1     canvas.height = rect.height;
  156    -1 
  157    -1     render();
  158    -1 };
  159    -1 
  160    -1 var render = onAnimation(function() {
  161    -1     ctx.clearRect(0, 0, canvas.width, canvas.height);
  162    -1     ctx.drawImage(frame.canvas, dx, dy, frame.canvas.width * zoom, frame.canvas.height * zoom);
  163    -1 });
  164    -1 
  165    -1 var applySpeed = onAnimation(function() {
  166    -1     dx += speed_x;
  167    -1     dy += speed_y;
  168    -1     render();
   -1   134 var applySpeed = utils.throttle(function() {
   -1   135     view.dx += speed_x;
   -1   136     view.dy += speed_y;
   -1   137     view.render();
  169   138     speed_x *= 0.85;
  170   139     speed_y *= 0.85;
  171   140     if (Math.abs(speed_x) > 0.1 || Math.abs(speed_y) > 0.1) {
  172   141         setTimeout(applySpeed);
  173   142     }
  174    -1 });
   -1   143 }, 'animation');
  175   144 
  176    -1 window.addEventListener('resize', resizeCanvas);
  177    -1 resizeCanvas();
   -1   145 window.addEventListener('resize', () => view.refreshSize());
   -1   146 view.refreshSize();
  178   147 
  179   148 window.addEventListener('wheel', event => {
  180   149     var rect = canvas.getBoundingClientRect();
  181   150     var cx = event.clientX - rect.x;
  182   151     var cy = event.clientY - rect.y;
  183   152 
  184    -1     var ocx = (cx - dx) / zoom;
  185    -1     var ocy = (cy - dy) / zoom;
   -1   153     var ocx = (cx - view.dx) / view.zoom;
   -1   154     var ocy = (cy - view.dy) / view.zoom;
  186   155 
  187    -1     zoom *= Math.pow(2, -event.deltaY / 100 / 100);
   -1   156     view.zoom *= Math.pow(2, -event.deltaY / 100 / 100);
  188   157 
  189    -1     dx = cx - ocx * zoom;
  190    -1     dy = cy - ocy * zoom;
   -1   158     view.dx = cx - ocx * view.zoom;
   -1   159     view.dy = cy - ocy * view.zoom;
  191   160 
  192    -1     render();
   -1   161     view.render();
  193   162 });
  194   163 
  195   164 var setPencil = function(color) {
@@ -220,7 +189,7 @@ window.addEventListener('keydown', event => {
  220   189     } else if (event.key === 'e') {
  221   190         setPencil(pencil + 1);
  222   191     }
  223    -1     render();
   -1   192     view.render();
  224   193 });
  225   194 
  226   195 var drawLine = function(x1, y1, x2, y2, color) {
@@ -250,14 +219,14 @@ var drawLine = function(x1, y1, x2, y2, color) {
  250   219 
  251   220 var last_click = null;
  252   221 
  253    -1 var onClick = onAnimation(function(event) {
   -1   222 var onClick = utils.throttle(function(event) {
  254   223     if (event.buttons & 1) {
  255   224         var rect = canvas.getBoundingClientRect();
  256   225         var cx = event.clientX - rect.x;
  257   226         var cy = event.clientY - rect.y;
  258   227 
  259    -1         var ocx = (cx - dx) / zoom / PXSIZE;
  260    -1         var ocy = (cy - dy) / zoom / PXSIZE;
   -1   228         var ocx = (cx - view.dx) / view.zoom / PXSIZE;
   -1   229         var ocy = (cy - view.dy) / view.zoom / PXSIZE;
  261   230 
  262   231         if (last_click) {
  263   232             drawLine(last_click.x, last_click.y, ocx, ocy, pencil);
@@ -266,11 +235,11 @@ var onClick = onAnimation(function(event) {
  266   235         }
  267   236         last_click = {x: ocx, y: ocy};
  268   237 
  269    -1         render();
   -1   238         view.render();
  270   239     } else {
  271   240         last_click = null;
  272   241     }
  273    -1 });
   -1   242 }, 'animation');
  274   243 
  275   244 canvas.addEventListener('mousemove', onClick);
  276   245 canvas.addEventListener('mousedown', onClick);

diff --git a/utils.js b/utils.js

@@ -0,0 +1,35 @@
   -1     1 var _setTimeout = function(fn, timeout) {
   -1     2     if (timeout === 'animation') {
   -1     3         requestAnimationFrame(fn);
   -1     4     } else {
   -1     5         setTimeout(fn, timeout);
   -1     6     }
   -1     7 };
   -1     8 
   -1     9 export var throttle = function(fn, timeout) {
   -1    10     var blocked = false;
   -1    11     var called = false;
   -1    12     var nextArgs = [];
   -1    13 
   -1    14     var wrapper = function(...args) {
   -1    15         if (blocked) {
   -1    16             called = true;
   -1    17             nextArgs = args;
   -1    18         } else {
   -1    19             blocked = true;
   -1    20             called = false;
   -1    21             nextArgs = [];
   -1    22 
   -1    23             fn.apply(this, args);
   -1    24 
   -1    25             _setTimeout(() => {
   -1    26                 blocked = false;
   -1    27                 if (called) {
   -1    28                     wrapper.apply(this, nextArgs);
   -1    29                 }
   -1    30             }, timeout);
   -1    31         }
   -1    32     };
   -1    33 
   -1    34     return wrapper;
   -1    35 };

diff --git a/view.js b/view.js

@@ -0,0 +1,37 @@
   -1     1 import * as utils from './utils.js';
   -1     2 
   -1     3 export class View {
   -1     4     constructor(canvas, frame) {
   -1     5         this.canvas = canvas;
   -1     6         this.frame = frame;
   -1     7         this.ctx = canvas.getContext('2d');
   -1     8         this.zoom = 1;
   -1     9         this.dx = 0;
   -1    10         this.dy = 0;
   -1    11     }
   -1    12 
   -1    13     refreshSize() {
   -1    14         var rect = this.canvas.getBoundingClientRect();
   -1    15 
   -1    16         this.dx += (rect.width - this.canvas.width) / 2;
   -1    17         this.dy += (rect.height - this.canvas.height) / 2;
   -1    18 
   -1    19         this.canvas.width = rect.width;
   -1    20         this.canvas.height = rect.height;
   -1    21 
   -1    22         this.render();
   -1    23     }
   -1    24 
   -1    25     render() {
   -1    26         this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
   -1    27         this.ctx.drawImage(
   -1    28             this.frame.canvas,
   -1    29             this.dx,
   -1    30             this.dy,
   -1    31             this.frame.canvas.width * this.zoom,
   -1    32             this.frame.canvas.height * this.zoom,
   -1    33         );
   -1    34     }
   -1    35 }
   -1    36 
   -1    37 View.prototype.render = utils.throttle(View.prototype.render, 'animation');