I've been working on a project for fun where I want to have a couple of different eyes bouncing around a screen. I want the pupil of the eye to follow the user's mouse as it moves around the page. In order to accomplish this, I planned to add an eventlistener for mousemove and update state every time the position is updated.
However, I have found that the state update triggers a re-run of my useEffect for drawing the canvas. This causes the appearance that the ball moves faster when the user is moving their mouse. I was wondering if anyone has any advice on how to avoid this or how to better organize my code to get around this issue?
You can use the "Console" tab in the sandbox to see log statements that occur during unintended updates.
const draw = (ctx: CanvasRenderingContext2D, mousePos: {x: number, y: number}) => {
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
bubbles.forEach((bubble, index) => {
bubble.intersectWall();
bubble.move();
bubble.draw(mousePos);
});
};
const handleMouseMove = (e: MouseEvent) => {
setMousePos({ x: e.screenX, y: e.screenY });
};
// Initialize bubbles on page load
useEffect(() => {
const canvas = canvasRef.current as HTMLCanvasElement;
const context = canvas.getContext("2d") as CanvasRenderingContext2D;
window.addEventListener("mousemove", handleMouseMove);
const initBubbles = [];
for (let i = 0; i < 1; i++) {
initBubbles.push(
new Bubble(
randomNumber(0 + BUBBLE_RADIUS, window.innerWidth - BUBBLE_RADIUS),
randomNumber(0 + BUBBLE_RADIUS, window.innerHeight - BUBBLE_RADIUS),
randomNumber(-1, 4),
randomNumber(-4, 4),
context
)
);
}
setBubbles(initBubbles);
return () => {
window.removeEventListener("mousemove", handleMouseMove);
};
}, []);
useEffect(() => {
const canvas = canvasRef.current as HTMLCanvasElement;
const context = canvas.getContext("2d") as CanvasRenderingContext2D;
let animationFrameId: number;
const render = () => {
draw(context, mousePos);
animationFrameId = window.requestAnimationFrame(render);
};
render();
return () => {
window.cancelAnimationFrame(animationFrameId);
};
}, [draw]);
Codepen example: https://codepen.io/pietrofan12/pen/wvEBPPx
Thank you in advance and sorry for bad english
I'm trying to update my pdf preview when I resize my window.
For now my canvas's size is changing, but the pdf preview is keeping the same size.
How can't find a way to do this.
var myState = {
pdf: null,
currentPage: 1,
zoom: 1
}
function domLoad() {
myState.pdf.getPage(myState.currentPage).then((page) => {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var viewport = page.getViewport(myState.zoom);
var heightRatio = 842 / 595;
canvas.width = ((((595/941.39)*100)*window.innerWidth)/100);
canvas.height = ((((595/941.39)*100)*window.innerWidth)/100) * heightRatio;
page.render({
canvasContext: ctx,
viewport: viewport
});
updateCanvas(canvas);
});
}
document.addEventListener('DOMContentLoaded', function(event) {
pdfjsLib.getDocument('https://www.ecam.fr/wp-content/uploads/sites/3/2016/06/Exemple-fichier-PDF-1.pdf').then((pdf) => {
myState.pdf = pdf;
render();
});
function render() {
domLoad();
}
})
addEventListener("resize", (event) => {
domLoad();
});
function updateCanvas(canvas) {
var canvasParent = document.getElementById("pdf_container");
var previousCanvas = canvasParent.querySelector('canvas');
if(previousCanvas !== null) {
canvasParent.removeChild(previousCanvas);
}
canvasParent.appendChild(canvas);
}
body { width: 100%; height: 100%; }
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.0.943/pdf.min.js"></script>
</head>
<body>
<a id="pdf_container" class="pdf_container" href="https://www.ecam.fr/wp-content/uploads/sites/3/2016/06/Exemple-fichier-PDF-1.pdf">
</a>
</div>
</body>
I tried to remove the canvas when I'm resizing the window, and add it back with another size for now.
The canvas's size is changing but the pdf preview inside won't fit it.
Reading : This solution
I managed to fix this, the viewport was the answer. The problem was the name of getViewport (it can also be a setter) :
var viewport = page.getViewport(canvas.width / page.getViewport(myState.zoom).width);
var myState = {
pdf: null,
currentPage: 1,
zoom: 1
}
function domLoad() {
myState.pdf.getPage(myState.currentPage).then((page) => {
var canvas = document.createElement('canvas');
canvas.id = 'pdf_renderer';
var ctx = canvas.getContext('2d');
console.log(page);
var heightRatio = 842 / 595;
canvas.width = ((((595/941.39)*100)*window.innerWidth)/100);
canvas.height = ((((595/941.39)*100)*window.innerWidth)/100) * heightRatio;
var viewport = page.getViewport(canvas.width / page.getViewport(myState.zoom).width);
page.render({
canvasContext: ctx,
viewport: viewport
});
updateCanvas(canvas);
});
}
document.addEventListener('DOMContentLoaded', function(event) {
pdfjsLib.getDocument('../documents/cv.pdf').then((pdf) => {
myState.pdf = pdf;
render();
});
function render() {
domLoad();
}
})
addEventListener("resize", (event) => {
domLoad();
});
function updateCanvas(canvas) {
var canvasParent = document.getElementById("pdf_container");
var previousCanvas = canvasParent.querySelector('canvas');
if(previousCanvas !== null) {
canvasParent.removeChild(previousCanvas);
}
canvasParent.appendChild(canvas);
}
I am implementing a 'loupe' ie. a "magnifying glass" that follows the mouse pointer. A portion of a vis-network graph is shown enlarged within the loupe (so that you can see a detail without zooming into the whole network). I do this by creating an off-screen vis-network with the same nodes and edges and the same viewpoint as the visible network, but at three times the scale. I then use a canvas drawImage to copy a portion of the canvas of this larger network into a div that floats above the visible network, and which is centred on the mouse pointer. This all works very well, except that I have a problem lining up the magnified image with the portion of the visible map that is being enlarged.
In my first attempt, the part of the map shown enlarged was a long way away from the location of the mouse pointer on the visible map. But a process of tedious experimentation, I managed to work out that I needed a multiplier (which I have called the magicNumber in the code below) to get it approximately right, i.e. so that the loupe shows an magnified view of the bit of the network under the pointer. I expect that this magic number is actually some constant in vis-network, but I can't think what it would be - and the correct value is probably not exactly the 1.92 that I obtained by experiment.
My question therefore is: what should this number be, and what does it mean?
There is a MVE here https://codepen.io/micrology/pen/eYBbKVX
Here is an extract from my code - first the CSS for the loupe and then the JavaScript:
.magnifier {
display: none;
position: absolute;
border: 1px black solid;
box-shadow: 5px 5px 10px #1e1e1e;
border-radius: 50%;
z-index: 5000;
}
const magSize = 300; // diameter of loupe
const magnification = 3; // magnification
let main = elem('main'); // div holding the visible network
let mainRect = main.getBoundingClientRect();
let magnifier = document.createElement('canvas'); // the 'magnifying glass'
magnifier.width = magSize;
magnifier.height = magSize;
magnifier.className = 'magnifier';
let magnifierCtx = magnifier.getContext('2d');
magnifierCtx.fillStyle = 'white';
main.appendChild(magnifier);
let bigNetPane = null;
let bigNetwork = null;
let bigNetCanvas = null;
const magicNumber = 1.92; / the mysterious magic number
// the loupe pops up when the user holds down the SHIFT key and moves the mouse
window.addEventListener('keydown', (e) => {
if (e.shiftKey) createMagnifier();
});
window.addEventListener('mousemove', (e) => {
if (e.shiftKey) showMagnifier(e);
});
window.addEventListener('keyup', (e) => {
if (e.key == 'Shift') closeMagnifier();
});
function createMagnifier() {
if (bigNetPane) {
bigNetwork.destroy();
bigNetPane.remove();
}
// the triple sized version of the netowrk is generated inside the bigNetPane div, which is off screen
bigNetPane = document.createElement('div');
bigNetPane.id = 'big-net-pane';
bigNetPane.style.position = 'absolute';
bigNetPane.style.top = '-9999px';
bigNetPane.style.left = '-9999px';
bigNetPane.style.width = `${netPane.offsetWidth * magnification}px`;
bigNetPane.style.height = `${netPane.offsetHeight * magnification}px`;
main.appendChild(bigNetPane);
bigNetwork = new Network(bigNetPane, data, options);
bigNetCanvas = bigNetPane.firstElementChild.firstElementChild;
bigNetwork.moveTo({
position: network.getViewPosition(),
scale: magnification * network.getScale(),
});
main.style.cursor = 'none';
magnifier.style.display = 'none';
}
function showMagnifier(e) {
e.preventDefault();
if (bigNetCanvas == null) createMagnifier(e);
magnifierCtx.fillRect(0, 0, magSize, magSize);
// this is where the magicNumber is required to line up the enlarged image with where the pointer is
magnifierCtx.drawImage(
bigNetCanvas,
(e.x - mainRect.x) * magicNumber * magnification,
(e.y - mainRect.y) * magicNumber * magnification,
magSize,
magSize,
0,
0,
magSize,
magSize
);
magnifier.style.top = e.clientY - mainRect.y - magSize / 2 + 'px';
magnifier.style.left = e.clientX - mainRect.x - magSize / 2 + 'px';
magnifier.style.display = 'block';
}
function closeMagnifier() {
if (bigNetPane) {
bigNetwork.destroy();
bigNetPane.remove();
}
main.style.cursor = 'default';
magnifier.style.display = 'none';
}
I have now got it to work. The CodePen demo has been edited so it now works as desired. The corrected code snippet (to compare with the code in the question) is:
const magSize = 300; // diameter of loupe
const magnification = 3; // magnification
const halfMagSize = magSize / 2.0;
let main = elem("mynetwork");
let mainRect = main.getBoundingClientRect();
let magnifier = document.createElement("canvas");
magnifier.width = magSize;
magnifier.height = magSize;
magnifier.className = "magnifier";
let magnifierCtx = magnifier.getContext("2d");
magnifierCtx.fillStyle = "white";
main.appendChild(magnifier);
let bigNetPane = null;
let bigNetwork = null;
let bigNetCanvas = null;
let netPaneCanvas = container.firstElementChild.firstElementChild;
window.addEventListener("keydown", (e) => {
if (e.shiftKey) createMagnifier();
});
window.addEventListener("mousemove", (e) => {
if (e.shiftKey) showMagnifier(e);
});
window.addEventListener("keyup", (e) => {
if (e.key == "Shift") closeMagnifier();
});
function showMagnifier(e) {
e.preventDefault();
if (bigNetCanvas == null) createMagnifier(e);
magnifierCtx.fillRect(0, 0, magSize, magSize);
magnifierCtx.drawImage(
bigNetCanvas,
((e.clientX - mainRect.x) * bigNetCanvas.width) /
netPaneCanvas.clientWidth -
halfMagSize,
((e.clientY - mainRect.y) * bigNetCanvas.height) /
netPaneCanvas.clientHeight -
halfMagSize,
magSize,
magSize,
0,
0,
magSize,
magSize
);
magnifier.style.top = e.clientY - halfMagSize + "px";
magnifier.style.left = e.clientX - halfMagSize + "px";
magnifier.style.display = "block";
}
function createMagnifier() {
if (bigNetPane) {
bigNetwork.destroy();
bigNetPane.remove();
}
network.storePositions();
bigNetPane = document.createElement("div");
bigNetPane.id = "big-net-pane";
bigNetPane.style.position = "absolute";
bigNetPane.style.top = "-9999px";
bigNetPane.style.left = "-9999px";
bigNetPane.style.width = `${main.offsetWidth * magnification}px`;
bigNetPane.style.height = `${main.offsetHeight * magnification}px`;
main.appendChild(bigNetPane);
bigNetwork = new vis.Network(bigNetPane, data, {
physics: { enabled: false }
});
bigNetCanvas = bigNetPane.firstElementChild.firstElementChild;
bigNetwork.moveTo({
position: network.getViewPosition(),
scale: network.getScale() * magnification,
animation: false
});
main.style.cursor = "none";
magnifier.style.display = "none";
}
function closeMagnifier() {
if (bigNetPane) {
bigNetwork.destroy();
bigNetPane.remove();
}
main.style.cursor = "default";
magnifier.style.display = "none";
}
so ive been testing out HTML canvas. im trying to get a sprite to change on keyboard input.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id='Game' width='200' height='200' style='border: 2px solid #000000;'></canvas>
<script>
window.onload = function(){
var Game = document.getElementById('Game');
var context = Game.getContext('2d')
var room = new Image();
var lx = 0;
var ly = 0;
var li = 0;
var lo = 0;
var lwidth = 100;
var lheight = 100;
room.onload = function(){
context.drawImage(room,lx,ly,lwidth,lheight,li,lo,200,200);
}
room.src = 'https://i.ibb.co/D7fL7yN/Room.png';
var sprite = new Image();
var cx = 0;
var cy = 125;
var sy = 0;
var sx = 0;
var swidth = 35;
var sheight = 34;
sprite.onload = function(){
context.drawImage(sprite,sx,sy,swidth,sheight,cx,cy,50,50);
}
sprite.src = 'https://i.ibb.co/7VhjqPr/John-Sheet.png';
}
</script>
</body>
</html>
ive been searching on how to change the SX with Keyboard input so my character changes sprites. can you help me? a code example would be best!
Tracking keyboard state.
You can create an object that hold the state of the keyboard, specifically the keys you are interested in reacting to. Use the "keydown" and "keyup" KeyboardEvent to update the keyboard state as the events fire. Use the KeyboardEvent property code to workout which key is changing. DO NOT use keyCode as that has depreciated and is Non Standard
You also want to prevent the default behaviour of keys. Eg prevent arrow keys scrolling the page. This is done by calling the event preventDefault function
const keys = {
ArrowRight: false,
ArrowLeft: false,
ArrowUp: false,
ArrowDown: false,
}
addEventListener("keydown", keyEvent);
addEventListener("keyup", keyEvent);
function keyEvent(event) {
if (keys[event.code] !== undefined) {
keys[event.code] = event.type === "keydown";
event.preventDefault();
}
}
Then in the game you need only check the keyboard state
if (keys.ArrowRight) { moveRight() }
if (keys.ArrowLeft) { moveLeft() }
// and so on
In the demo below the keys are binded to game actions, meaning that what and how many keys are used are independent of the action. The are also set via configuration, so that key binding can be changed without changing game code. You can also bind other inputs as in example
Animation
To animate you should use the timer function requestAnimationFrame as it is specifically designed to give the best animation results. It will call your rendering function, you can consider the rendering function like a loop, that is call every time you step forward in animation time.
Putting it together
The demo below use the above (modified) methods to get keyboard input and render the scene via animation frame requests.
It also uses some techniques (simple versions of) that help make your game a better product.
Encapsulates the player as an object
Maintains game state by holding the current rendering function in currentRenderState
Has configuration config so all important values are in one place, and could be loaded (from JSON file) to easily change the game without changing code.
Has configurable keyboard binding, Note more than one key can be bound to a game action. In example movement is via WASD or arrow keys.
All text is configurable (making it language independent)
Passes the 2D context to all rendering code.
Separates the game from the rendering. This makes it easier to port the game to low end or high end devices or even move it to a server where ctx is replaced with coms and the game can be broadcast . The game does not change only how it is rendered
var currentRenderState = getFocus; // current game state
const config = {
player: {
start: {x: 100, y:100},
speed: 2,
imageURL: "https://i.stack.imgur.com/C7qq2.png?s=64&g=1",
},
keys: { // link key code to game action
up: ["ArrowUp", "KeyW"],
down: ["ArrowDown", "KeyS"],
left: ["ArrowLeft", "KeyA"],
right: ["ArrowRight", "KeyD"],
},
touchableTime: 140, // in ms. Set to 0 or remove to deactivate
text: {
focus: "Click canvas to get focus",
loading: "Just a moment still loading media!",
instruct: "Use arrow keys or WASD to move",
}
};
requestAnimationFrame(mainLoop); // request first frame
const ctx = gameCanvas.getContext("2d");
const w = gameCanvas.width, h = gameCanvas.height;
const player = {
image: (()=> {
const img = new Image;
img.src = config.player.imageURL;
img.addEventListener("load", () => player.size = img.width, {once: true});
return img;
})(),
x: config.player.start.x,
y: config.player.start.y,
size: 0,
speed: config.player.speed,
direction: 0,
update() {
var oldX = this.x, oldY = this.y;
if (actions.left) { this.x -= this.speed }
if (actions.right) { this.x += this.speed }
if (actions.up) { this.y -= this.speed }
if (actions.down) { this.y += this.speed }
if (this.x < 0) { this.x = 0 }
else if (this.x > w - this.size) { this.x = w - this.size }
if (this.y < 0) { this.y = 0 }
else if (this.y > h - this.size) { this.y = h - this.size }
const mx = this.x - oldX, my = this.y - oldY;
if (mx !== 0 || my !== 0) { this.direction = Math.atan2(my, mx) }
},
draw(ctx) {
if (ctx) {
ctx.setTransform(1, 0, 0, 1, this.x + this.size / 2, this.y + this.size / 2);
ctx.rotate(this.direction + Math.PI / 2); // rotate 90 deg as image points up
ctx.drawImage(this.image,-this.size / 2, -this.size / 2, this.size, this.size);
}
}
}
function drawText(ctx, text, size, color) {
if (ctx) {
ctx.fillStyle = color;
ctx.font = size + "px Arial";
ctx.textAlign = "center";
ctx.fillText(text, w / 2, h * (1/4));
}
}
function getFocus(ctx) {
drawText(ctx, config.text.focus, 24, "black");
}
function drawScene(ctx) {
if (!player.size === 0) {
drawText(ctx, config.text.loading, 16, "blue")
actions.hasInput = false; // ensure instruction are up when ready
} else {
if (!actions.hasInput) { drawText(ctx, config.text.instruct, 16, "blue") }
player.update();
player.draw(ctx);
}
}
function mainLoop() {
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, w, h);
currentRenderState(ctx);
requestAnimationFrame(mainLoop); // request next frame
}
// keys holds action name for each named key. eg for up action ArrowUp: "up", KeyW: "up",
const keys = Object.entries(config.keys)
.reduce((keys, [action,codes]) =>
codes.reduce((keys, code) => (keys[code] = action, keys), keys), {});
// actions are set true when key down. NOTE first up key for action cancels action
const actions = Object.keys(config.keys)
.reduce((actions,action) => (actions[action] = false, actions),{});
addEventListener("keydown", keyEvent);
addEventListener("keyup", keyEvent);
function keyEvent(event) {
if (keys[event.code] !== undefined) {
actions[keys[event.code]] = event.type === "keydown";
event.preventDefault();
actions.hasInput = true;
}
}
if (config.touchableTime) {
const actionTimers = {};
touchable.addEventListener("click", (e) => {
if (e.target.dataset.action) {
actions[e.target.dataset.action] = true;
clearTimeout(actionTimers[e.target.dataset.action]);
actionTimers[e.target.dataset.action] = setTimeout(() => actions[e.target.dataset.action] = false, config.touchableTime);
actions.hasInput=true;
if (currentRenderState !== drawScene) {
window.focus();
currentRenderState = drawScene;
}
}
});
} else {
touchable.classList.add("hide");
}
gameCanvas.addEventListener("click", () => currentRenderState = drawScene, {once: true});
canvas {border: 1px solid black}
#game {
width:402px;
height:182px;
font-size: 24px;
user-select: none;
}
.left {
position: absolute;
top: 160px;
left: 10px;
cursor: pointer;
}
.right {
position: absolute;
top: 160px;
left: 355px;
cursor: pointer;
}
#touchable span:hover {color: red}
.hide { display: none }
<div id="game">
<canvas id="gameCanvas" width="400" height="180"></canvas>
<div id="touchable">
<div class="left">
<span data-action="up">▲</span>
<span data-action="down">▼</span>
</div>
<div class="right">
<span data-action="left">◄</span>
<span data-action="right">►</span>
</div>
</div>
</div>
Click to snippet frame area for focusing keyboard events
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id='Game' width='200' height='200' style='border: 2px solid #000000;'></canvas>
<script>
window.onload = function(){
// Keyboard collect
const keys = [];
document.onkeydown = e => {
var code = e.which;
if(keys.indexOf(code) < 0){
keys.push(code);
}
};
document.onkeyup = e => keys.splice(keys.indexOf(e.which),1);
// constants
const Game = document.getElementById('Game');
const context = Game.getContext('2d')
const room = new Image();
const lx = 0;
const ly = 0;
const li = 0;
const lo = 0;
const lwidth = 100;
const lheight = 100;
room.onload = function(){
context.drawImage(room,lx,ly,lwidth,lheight,li,lo,200,200);
}
room.src = 'https://i.ibb.co/D7fL7yN/Room.png';
const sprite = new Image();
const swidth = 35;
const sheight = 34;
const sy = 0;
sprite.onload = function(){
context.drawImage(sprite,0,sy,swidth,sheight,0,cy,50,50);
}
sprite.src = 'https://i.ibb.co/7VhjqPr/John-Sheet.png';
// variables
let cx = 0;
let cy = 125;
let sx = 0;
// new variables
const frames_per_step = 20;
let moving = false; // moving flag
let step = 0; // frame counter (for steps)
// main loop function
function tick() {
// keyboard process
if (keys.length) {
keys.forEach(item => {
switch(item){
case 68:case 39://D and right arrow
cx += 1; // move right
// change sprite
if (step++ < frames_per_step / 2) {
sx = 35; // leg up
} else {
sx = 70; // leg down
if(step > frames_per_step) step = 0;
}
moving = true;
break;
case 65:case 37://A and left arrow
cx -= 1; // move left
// change sprite
if (step++ < frames_per_step / 2) {
sx = 105;
} else {
sx = 140;
if(step > frames_per_step) step = 0;
}
moving = true;
break;
// no sprite mechanics here, just move
case 87:case 38://W adn arrow up
cy -= 1;
break;
case 83:case 40://S adn arrow down
cy += 1;
break;
}
});
// render
context.drawImage(room,lx,ly,lwidth,lheight,li,lo,200,200);
context.drawImage(sprite,sx,sy,swidth,sheight,cx,cy,50,50);
} else if(moving) { // return sprite to stay position
sx = 0;
context.drawImage(room,lx,ly,lwidth,lheight,li,lo,200,200);
context.drawImage(sprite,sx,sy,swidth,sheight,cx,cy,50,50);
moving = false;
} // else do nothing
requestAnimationFrame(tick);
}
tick();
}
</script>
</body>
</html>
I am trying to move a div with the help of mousemove event.
Here is the code for the same.
https://codepen.io/anurag92/pen/VEoQOZ
class ImageMarker extends React.Component {
constructor(props) {
super(props);
this.mouseDown = this.mouseDown.bind(this);
this.mouseUp = this.mouseUp.bind(this);
this.mouseMove = this.mouseMove.bind(this);
this.paint = this.paint.bind(this);
}
mouseDown(e) {
const position = {
left: this.marker.offsetLeft,
top: this.marker.offsetTop
};
this.hitOffset = {
x: e.pageX - position.left,
y: e.pageY - position.top,
diameter: this.diameter(),
markerRadius: 10
};
this.marker.addEventListener('mousemove', this.mouseMove);
this.marker.addEventListener('mouseup', this.mouseUp);
this.marker.addEventListener('mouseleave', this.mouseUp);
e.preventDefault();
}
mouseMove(e) {
this.position = {
x: e.pageX - this.hitOffset.x,
y: e.pageY - this.hitOffset.y
};
this.position.x = Math.round(this.position.x);
this.position.y = Math.round(this.position.y);
this.position.x = Math.min(700 - 1, Math.max(0, this.position.x));
this.position.y = Math.min(700 - 1, Math.max(0, this.position.y));
this.paint();
}
mouseUp(e) {
this.marker.removeEventListener('mousemove', this.mouseMove);
this.marker.removeEventListener('mouseup', this.mouseUp);
this.marker.removeEventListener('mouseleave', this.mouseUp);
}
diameter() {
return 1;
}
paint() {
if (JSON.stringify(this.paintedPosition) !== JSON.stringify(this.position)) {
this.paintedPosition = Object.assign({}, this.position);
}
if (this.position) {
this.marker.style.left = `${100 * this.position.x / 700}%`;
this.marker.style.top = `${100 * this.position.y / 700}%`;
}
return this;
}
render() {
this.position = this.position || {
x: 5,
y: 5
};
this.offset = 0;
return <div className='outer'
ref = {ref => {
this.canvasRef = ref;
}}
>
<div className = 'marker'
onMouseDown = {event => this.mouseDown(event)}
ref = {ref => {
this.marker = ref;
}} >
</div>
</div>;
}
}
// export default ImageMarker;
ReactDOM.render(<ImageMarker />,
document.getElementById('root')
);
When i move my cursor slowly its working fine, but on fast movement mouseleave gets triggered and as a result div is not able to keep up with the cursor.
Can someone please tell me a potential fix for this.
You could resolve that by attaching the mouseMove (and mouseUp)to the whole document This way they will be fired no matter if the mouse gets out of the element you want to drag.
Just remember to detach the event during componentWillUnmount to avoid leaks.
Further more if you want you site to work on mobile you need to attach touch, pointer or drag events. See the code of the kendo-draggable abstraction for a reference. We are using it in our react components. Bind to the element on ComponentDidMount and detach on ComponentWillUnmount