Reputation: 758
I'm currently creating a software that will be like paint, however I am stuck on getting a box to follow the mouse on the canvas. The purpose of the box is to get it to show where the mouse position is, to show what colour has been selected and to show the size of the brush. I found this piece of code online:
<html>
<head>
<script>
function m(e){
var bx = document.getElementById("box");
bx.style.left = e.pageX;
bx.style.top = e.pageY;
}
</script>
</head>
<body onmousemove="m(event)">
<div id="box" style="background-color:#990000; width:20px; height:20px; position:absolute;" />
</body>
I've tried to implement this into my program, however it doesn't seem to be showing on the canvas...I've changed the function m(e) to fnTrackMouse(event)
I can only use mainly javascript and a bit of html and css. No Jquery please. Here's a section of my program that I'm working on:
<!doctype html>
<html lang="en">
<head>
<style>
...
</style>
<script>
var oCanvas, oCanvasContext; //declare the global variables used to hold and control the canvas element
var sFillColour; //create a global variable used to hold the active/selected colour
var sCanvasColour; //create a global variable used to hold the canvas colour
var iMouseX, iMouseY; //declare the global variables used to hold the mouse's coordinates
var iBrushWidth, iBrushHeight; //declare the global variables used to hold the selected brush sizes
function fnInitialise(iCanvasWidth, iCanvasHeight) {
//this function is called via the HTML body tag and the onload event
fnDebugMessage("Running fnInitialise"); //debug message
oCanvas = document.getElementById("cw1Canvas"); //create a reference to the HTML canvas element
if (oCanvas.getContext) { //test to see if we can read the canvas' context; if true we have found the canvas
oCanvas.width=iCanvasWidth; //set the canvas width using the width argument passed to the fnInitialise function
oCanvas.height=iCanvasHeight; //set the canvas height using the width argument passed to the fnInitialise function
oCanvasContext = oCanvas.getContext("2d"); //set the context to 2D
fnDebugMessage("Canvas size, width: " + iCanvasWidth + ", height: " + iCanvasHeight); //debug message, if this message appears in
//set some default values`
sCanvasColour=getComputedStyle(oCanvas).getPropertyValue("background-color"); //this instruction automatically detects the background colour of the cavas and stores it in the global sCanvasColour variable
fnDebugMessage("Canvas background colour: " + sCanvasColour); //debug message, if this message appears in
//let set a default brush size
iBrushWidth=5;
iBrushHeight=5;
//set the canvas size to 550px x 550px
oCanvas.width=550;
oCanvas.height=550;
} else {
fnDebugMessage("fnInitialise, failed to get the canvas's context"); //debug message, we were unable to get the canvas' context
}
}
function fnTrackMouse(e) {
//this function is called "everytime" the user's mouse is moved when over the associated element (in this case the canvas)
//we have also added the ability for it to accept a parameter (called e, actually we can call it anything but as event is a reserved work "e" makes some sense
var canvasRect = oCanvas.getBoundingClientRect(); //use this function to dynamically get the size of the canvas and its position
iMouseX=(e.clientX - canvasRect.left - 3); //modify the original position of the mouse by accounting for the position on the canvas; on the x
iMouseY=(e.clientY - canvasRect.top - 3); //modify the original position of the mouse by accounting for the position on the canvas; on the y
var bx = document.getElementById("box");
bx.style.left = iMouseX;
bx.style.top = iMouseY;
fnDebugMessage("Working!"+iMouseX)
if (e.buttons==1) { //this checks to see if the user is pressing the left mouse button (1 = the left mouse button)
//the user has pressed the left button - so lets start painting
fnPaint(iMouseX, iMouseY, iBrushWidth, iBrushHeight); //call the fnPaint function and pass it the coordinates and size to paint
}
fnDebugMessage("Tracking mouse: x: " + iMouseX + ", y: "+iMouseY); //update the console to show the mouse position, dont forget, you may need to include an offset to centre the paint effect
}
</script>
</head>
<body onload="fnInitialise(100, 100);">
<!--
this div block (HTML page divider) is used to hold the entire interactive painting HTML elements
the benefit of putting multiple elements in a single container is that if you set the location of the
container each of the elements held by the container will move relative to it; move one, move all
-->
<div id="cw1MainContainer">
<!-- this div block is only used to hold the HTML canvas element -->
<div id="cw1CanvasContainer">
<canvas id="cw1Canvas" onmousemove="fnTrackMouse(event);" onkeypress="fnBrushSize(event);"></canvas>
<div id="box" style="background-color:#990000; width:20px; height:20px; position:absolute;" />
<!--
by specifing the onmouseover event the canvas will call the "fnTrackMouse" function EVERY time the
mouse moves 1 pixel over the canvas.
by passing the JavaScript "event" we are effectively also passing details about the event,
e.g. where the mouse was, what buttons were pressed etc.
-->
</div>
</div>
</body>
</html>
I've taken out most of the code that I think was irrelevant to this problem, but if it is necessary, please let me know. Any help would be appreciated. Cheers
Upvotes: 0
Views: 220
Reputation: 50749
Your issus is that you are not providing a unit for your position. You can fix this by appending the px
suffix to your coordinates of your mouse position:
bx.style.left = iMouseX +'px';
bx.style.top = iMouseY + 'px';
However, you're still going to have an issue. The issue here is that your canvas
is listening for an onmousemove
event. However, when you move the "box" div to your mouse location, the canvas's onmousemove
event will not be triggered until you have moved your mouse off of the box and back onto the canvas, thus causing a "lagging behind" effect. To fix this you can add the style pointer-events: none
to your box div
which will stop all mouse events on the box.
See example below:
canvas {
border: 1px solid black;
}
#box {
pointer-events: none;
}
<!doctype html>
<html lang="en">
<head>
<script>
var oCanvas, oCanvasContext;
var sFillColour;
var sCanvasColour;
var iMouseX, iMouseY;
var iBrushWidth, iBrushHeight;
var multiplier = 1
function fnInitialise(iCanvasWidth, iCanvasHeight) {
oCanvas = document.getElementById("cw1Canvas");
if (oCanvas.getContext) {
oCanvas.width = iCanvasWidth;
oCanvas.height = iCanvasHeight;
oCanvasContext = oCanvas.getContext("2d");
sCanvasColour = getComputedStyle(oCanvas).getPropertyValue("background-color");
iBrushWidth = 5;
iBrushHeight = 5;
} else {
}
}
function fnTrackMouse(e) {
var canvasRect = oCanvas.getBoundingClientRect();
iMouseX = (e.clientX - canvasRect.left - 3);
iMouseY = (e.clientY - canvasRect.top - 3);
var bx = document.getElementById("box");
bx.style.left = iMouseX +'px';
bx.style.top = iMouseY + 'px';
if (e.ctrlKey) {
fnSetFillColour(sCanvasColour);
}
if (e.buttons == 1) {
fnPaint(iMouseX, iMouseY, iBrushWidth, iBrushHeight);
}
}
</script>
</head>
<body onload="fnInitialise(100, 100);">
<div id="cw1MainContainer">
<div id="cw1CanvasContainer">
<canvas id="cw1Canvas" onmousemove="fnTrackMouse(event);" onkeypress="fnBrushSize(event);"></canvas>
<div id="box" style="background-color:#990000; width:20px; height:20px; position:absolute;" />
</div>
</div>
</body>
</html>
Upvotes: 1
Reputation: 12891
There's a little problem with your code.
Here you're trying to set the position of the bx element according to the mouse position:
bx.style.left = iMouseX;
bx.style.top = iMouseY;
Unfortunately this doesn't work unless you append the string px - a short form for pixels.
bx.style.left = iMouseX+"px";
bx.style.top = iMouseY+"px";
Upvotes: 1