Skip to main content
Code Review

Return to Answer

Commonmark migration
Source Link

#Limiting updates

Limiting updates

##Some style a code points.

Some style a code points.

##Design

Design

##Example

Example

#Limiting updates

##Some style a code points.

##Design

##Example

Limiting updates

Some style a code points.

Design

Example

update grammar, punctuation
Source Link

You are correct about mouse event rates, I have seen mouse event 2ms appartapart. However touch events seamseem to be in sync with the display 60FPS, I have never seen a touch event fire at rates higher than this (but that is a hardware attribute as far as I know).

  • window is the default object you don't need to use it. window.removeEventListener is the same as removeEventListener and converslyconversely your function throttleRedraw is the same as window.throttleRedraw

  • It is not good to have statement block without delimiting parenthesis as it can easily be missed when making modifications. if (ondraw) ondraw(now); is better as if (ondraw) { ondraw(now) } the ; is optional as the line has ended in a }

  • You don't have to have a separate event handler for each event type. Many of the event properties are repeated and you end up duplicating code. Create a single handler that handles all the events of similar type.

  • The DOM does it all, but the DOM does it badly, adding and removing event handlers is just adding more work to the DOM and can be more efficiently handled by your JavaScript. Set handlers once and ignore events not needed

  • Too many comments. Comment only code that is not self evident,evident; any other comments are just noise and make the code harder to read.

The pointer is created and listens to all relevant events and sets its properties x, y, down... and so on. The pointer also correct the coorscoords to be relative to the target top left.

Note that it listens to document events and filters out events not triggered by the active element. (THE snippet has modified behavior and does not allow event outside the snippet window. The event handler has the target test commented out to improve it a little, but it is not an accurate representation of how it works on aan independent page).

You are correct about mouse event rates, I have seen mouse event 2ms appart. However touch events seam to be in sync with the display 60FPS, I have never seen a touch event fire at rates higher than this (but that is a hardware attribute as far as I know)

  • window is the default object you don't need to use it. window.removeEventListener is the same as removeEventListener and conversly your function throttleRedraw is the same as window.throttleRedraw

  • It is not good to have statement block without delimiting parenthesis as it can easily be missed when making modifications. if (ondraw) ondraw(now); is better as if (ondraw) { ondraw(now) } the ; is optional as the line has ended in a }

  • You don't have to have a separate event handler for each event type. Many of the event properties are repeated and you end up duplicating code. Create a single handler that handles all the events of similar type.

  • The DOM does it all, but the DOM does it badly, adding and removing event handlers is just adding more work to the DOM and can be more efficiently handled by your JavaScript. Set handlers once and ignore events not needed

  • Too many comments. Comment only code that is not self evident, any other comments are just noise and make the code harder to read.

The pointer is created and listens to all relevant events and sets its properties x, y, down... and so on. The pointer also correct the coors to be relative to the target top left.

Note that it listens to document events and filters out events not triggered by the active element. (THE snippet has modified behavior and does not allow event outside the snippet window. The event handler has the target test commented out to improve it a little, but it is not an accurate representation of how it works on a independent page).

You are correct about mouse event rates, I have seen mouse event 2ms apart. However touch events seem to be in sync with the display 60FPS, I have never seen a touch event fire at rates higher than this (but that is a hardware attribute as far as I know).

  • window is the default object you don't need to use it. window.removeEventListener is the same as removeEventListener and conversely your function throttleRedraw is the same as window.throttleRedraw

  • It is not good to have statement block without delimiting parenthesis as it can easily be missed when making modifications. if (ondraw) ondraw(now); is better as if (ondraw) { ondraw(now) } the ; is optional as the line has ended in a }

  • You don't have to have a separate event handler for each event type. Many of the event properties are repeated and you end up duplicating code. Create a single handler that handles all the events of similar type.

  • The DOM does it all, but the DOM does it badly, adding and removing event handlers is just adding more work to the DOM and can be more efficiently handled by your JavaScript. Set handlers once and ignore events not needed

  • Too many comments. Comment only code that is not self evident; any other comments are just noise and make the code harder to read.

The pointer is created and listens to all relevant events and sets its properties x, y, down... and so on. The pointer also correct the coords to be relative to the target top left.

Note that it listens to document events and filters out events not triggered by the active element. (THE snippet has modified behavior and does not allow event outside the snippet window. The event handler has the target test commented out to improve it a little, but it is not an accurate representation of how it works on an independent page).

edited body
Source Link
Blindman67
  • 22.8k
  • 2
  • 16
  • 40

Mouse events on a element have the annoying habit of only hearing events while the mouse is over the element. This means that if you have the mouse down and drag outside the element you will not hear the up event and end up with the mouse state stuck down.

To prevent this very annoying problem you can listen to events from the document. It will capture the mouse and keep the event.target to the element that got mouse down no matter where the mouse moves (even outside the browser tab)

function createPointer(target) {
 var currentTarget;
 var bounds;
 const types = {
 mouse: 1, touch: 2, move: 1, up: 2, end: 2, cancel: 2, start: 0, down: 0,
 names : "touchcancel,touchend,touchmove,touchstart,mousemove,mousedown,mouseup".split(","),
 }
 const pointer = {
 delta: {x : 0, y : 0},
 pos: {x : 0, y : 0, coord(x,y) { this.x = x; this.y = y }},
 last: {x : 0, y : 0, set from(src) { this.x = src.x; this.y = src.y }},
 down : false,
 active : false,
 changed : false,
 set position(coord) {
 pointer.last.from = pointer.pos;
 pointer.pos.coord(coord.clientX- bounds.left + scrollX, coord.clientY - bounds.top + scrollY);
 pointer.delta.x = pointer.pos.x - pointer.last.x;
 pointer.delta.y = pointer.pos.y - pointer.last.y;
 },
 set target(element){
 if(!element){
 types.names.forEach(event => document.removeEventListener(event, events) );
 currentTarget = undefined;
 pointer.active = false;
 }else {
 if (!currentTarget) { types.names.forEach(event => document.addEventListener(event, events) ) }
 currentTarget = element;
 bounds = element.getBoundingClientRect()
 pointer.active = true;
 }
 pointer.down = false;
 pointer.changed = true;
 }
 }
 const events = event => {
 // if (event.target === currentTarget) {
 const type = types[event.type.substring(5)];
 pointer.position = types[event.type.substring(0,5)] === types.touch ? event.touches[0] : event;
 if (type === types.down) { pointer.down = true }
 else if (type === types.up) { pointer.down = false }
 pointer.changed = true;
 event.preventDefault();
 // }
 }
 pointer.target = target;
 return pointer;
}
const rendering = (()=> {
 requestAnimationFrame(mainLoop);
 const canvas = document.querySelector('canvas');
 const ctx = canvas.getContext('2d');
 const pointer = createPointer(canvas);
 var update = false;
 
 function as(src) { this.x = src.x; this.y = src.y }
 const drag = {
 active : false,
 start : {x : 0, y : 0, as},
 end : {x : 0, y : 0, as},
 draw() {
 ctx.fillStyle = "red";
 ctx.fillRect(
 Math.min(drag.start.x, drag.end.x), Math.min(drag.start.y, drag.end.y),
 Math.abs(drag.start.x - drag.end.x), Math.abs(drag.start.y - drag.end.y),
 )
 }
 }
 
 function checkPointer() {
 if (pointer.changed) {
 if (pointer.down) {
 if (!drag.active) {
 drag.start.as(pointer.pos);
 drag.active = true;
 }
 drag.end.as(pointer.pos);
 update = true;
 } else if (drag.active) {
 drag.end.as(pointer.pos);
 drag.active = false;
 update = true;
 }
 pointer.changed = false;
 }
 }
 
 function mainLoop(time) {
 checkPointer();
 if (update) {
 ctx.clearRect(0,0,canvas.width,canvas.height);
 drag.draw();
 update = false;
 }
 requestAnimationFrame(mainLoop);
 }
})();
<canvas width="400" height="400" style="border: 2px solid #888"></canvas>

Mouse events on a element have the annoying habit of only hearing events while the mouse is over the element. This means that if you have the mouse down and drag outside the element you will not hear the up event and end up with the mouse state stuck down.

To prevent this very annoying problem you can listen to events from the document. It will capture the mouse and keep the event.target to the element that got mouse down no matter where the mouse moves (even outside the browser tab)

function createPointer(target) {
 var currentTarget;
 var bounds;
 const types = {
 mouse: 1, touch: 2, move: 1, up: 2, end: 2, cancel: 2, start: 0, down: 0,
 names : "touchcancel,touchend,touchmove,touchstart,mousemove,mousedown,mouseup".split(","),
 }
 const pointer = {
 delta: {x : 0, y : 0},
 pos: {x : 0, y : 0, coord(x,y) { this.x = x; this.y = y }},
 last: {x : 0, y : 0, set from(src) { this.x = src.x; this.y = src.y }},
 down : false,
 active : false,
 changed : false,
 set position(coord) {
 pointer.last.from = pointer.pos;
 pointer.pos.coord(coord.clientX- bounds.left + scrollX, coord.clientY - bounds.top + scrollY);
 pointer.delta.x = pointer.pos.x - pointer.last.x;
 pointer.delta.y = pointer.pos.y - pointer.last.y;
 },
 set target(element){
 if(!element){
 types.names.forEach(event => document.removeEventListener(event, events) );
 currentTarget = undefined;
 pointer.active = false;
 }else {
 if (!currentTarget) { types.names.forEach(event => document.addEventListener(event, events) ) }
 currentTarget = element;
 bounds = element.getBoundingClientRect()
 pointer.active = true;
 }
 pointer.down = false;
 pointer.changed = true;
 }
 }
 const events = event => {
 // if (event.target === currentTarget) {
 const type = types[event.type.substring(5)];
 pointer.position = types[event.type.substring(0,5)] === types.touch ? event.touches[0] : event;
 if (type === types.down) { pointer.down = true }
 else if (type === types.up) { pointer.down = false }
 pointer.changed = true;
 event.preventDefault();
 // }
 }
 pointer.target = target;
 return pointer;
}
const rendering = (()=> {
 requestAnimationFrame(mainLoop);
 const canvas = document.querySelector('canvas');
 const ctx = canvas.getContext('2d');
 const pointer = createPointer(canvas);
 var update = false;
 
 function as(src) { this.x = src.x; this.y = src.y }
 const drag = {
 active : false,
 start : {x : 0, y : 0, as},
 end : {x : 0, y : 0, as},
 draw() {
 ctx.fillStyle = "red";
 ctx.fillRect(
 Math.min(drag.start.x, drag.end.x), Math.min(drag.start.y, drag.end.y),
 Math.abs(drag.start.x - drag.end.x), Math.abs(drag.start.y - drag.end.y),
 )
 }
 }
 
 function checkPointer() {
 if (pointer.changed) {
 if (pointer.down) {
 if (!drag.active) {
 drag.start.as(pointer.pos);
 drag.active = true;
 }
 drag.end.as(pointer.pos);
 update = true;
 } else if (drag.active) {
 drag.end.as(pointer.pos);
 drag.active = false;
 update = true;
 }
 pointer.changed = false;
 }
 }
 
 function mainLoop(time) {
 checkPointer();
 if (update) {
 ctx.clearRect(0,0,canvas.width,canvas.height);
 drag.draw();
 update = false;
 }
 requestAnimationFrame(mainLoop);
 }
})();
<canvas width="400" height="400" style="border: 2px solid #888"></canvas>
function createPointer(target) {
 var currentTarget;
 var bounds;
 const types = {
 mouse: 1, touch: 2, move: 1, up: 2, end: 2, cancel: 2, start: 0, down: 0,
 names : "touchcancel,touchend,touchmove,touchstart,mousemove,mousedown,mouseup".split(","),
 }
 const pointer = {
 delta: {x : 0, y : 0},
 pos: {x : 0, y : 0, coord(x,y) { this.x = x; this.y = y }},
 last: {x : 0, y : 0, set from(src) { this.x = src.x; this.y = src.y }},
 down : false,
 active : false,
 changed : false,
 set position(coord) {
 pointer.last.from = pointer.pos;
 pointer.pos.coord(coord.clientX- bounds.left + scrollX, coord.clientY - bounds.top + scrollY);
 pointer.delta.x = pointer.pos.x - pointer.last.x;
 pointer.delta.y = pointer.pos.y - pointer.last.y;
 },
 set target(element){
 if(!element){
 types.names.forEach(event => removeEventListener(event, events) );
 currentTarget = undefined;
 pointer.active = false;
 }else {
 if (!currentTarget) { types.names.forEach(event => addEventListener(event, events) ) }
 currentTarget = element;
 bounds = element.getBoundingClientRect()
 pointer.active = true;
 }
 pointer.down = false;
 pointer.changed = true;
 }
 }
 const events = event => {
 // if (event.target === currentTarget) {
 const type = types[event.type.substring(5)];
 pointer.position = types[event.type.substring(0,5)] === types.touch ? event.touches[0] : event;
 if (type === types.down) { pointer.down = true }
 else if (type === types.up) { pointer.down = false }
 pointer.changed = true;
 event.preventDefault();
 // }
 }
 pointer.target = target;
 return pointer;
}
const rendering = (()=> {
 requestAnimationFrame(mainLoop);
 const canvas = document.querySelector('canvas');
 const ctx = canvas.getContext('2d');
 const pointer = createPointer(canvas);
 var update = false;
 
 function as(src) { this.x = src.x; this.y = src.y }
 const drag = {
 active : false,
 start : {x : 0, y : 0, as},
 end : {x : 0, y : 0, as},
 draw() {
 ctx.fillStyle = "red";
 ctx.fillRect(
 Math.min(drag.start.x, drag.end.x), Math.min(drag.start.y, drag.end.y),
 Math.abs(drag.start.x - drag.end.x), Math.abs(drag.start.y - drag.end.y),
 )
 }
 }
 
 function checkPointer() {
 if (pointer.changed) {
 if (pointer.down) {
 if (!drag.active) {
 drag.start.as(pointer.pos);
 drag.active = true;
 }
 drag.end.as(pointer.pos);
 update = true;
 } else if (drag.active) {
 drag.end.as(pointer.pos);
 drag.active = false;
 update = true;
 }
 pointer.changed = false;
 }
 }
 
 function mainLoop(time) {
 checkPointer();
 if (update) {
 ctx.clearRect(0,0,canvas.width,canvas.height);
 drag.draw();
 update = false;
 }
 requestAnimationFrame(mainLoop);
 }
})();
<canvas width="400" height="400" style="border: 2px solid #888"></canvas>
edited body
Source Link
Blindman67
  • 22.8k
  • 2
  • 16
  • 40
Loading
Source Link
Blindman67
  • 22.8k
  • 2
  • 16
  • 40
Loading
default

AltStyle によって変換されたページ (->オリジナル) /