Drawing multiple shapes using canvas like paint application - javascript

I am trying to create a paint like application using canvas. I am able to draw with free hand tool but when i try to using shapes we need to use clearrect method which i am not able to use properly. I need to draw multiple shapes on canvas with mouse but unable to do so.
Here is a link to what i am trying
http://jsfiddle.net/6vq64sdh/
HTML:
<canvas width="800px" height="600px" id="drawing"></canvas>
JS
var isDown;
var start;
var end;
var canvasEl = document.getElementById("drawing");
var draw = canvasEl.getContext("2d");
draw.lineWidth = "2";
draw.strokeStyle = "blue";
var lastWidth = 0;
var lastHeight = 0;
$("#drawing").mousedown(function(e) {
isDown = true;
start = getMousePos(canvasEl, e);
end = getMousePos(canvasEl, e);
lastWidth = 0;
lastHeight = 0;
e.preventDefault();
});
$("#drawing").mouseup(function() {
isDown = false;
});
$("#drawing").mousemove(function(e) {
if (!isDown) return;
var end = getMousePos(canvasEl, e);
var h = end.y - start.y;
var w = end.x - start.x;
draw.clearRect(start.x-5, start.y-5, lastWidth + 6, lastHeight + 6);
draw.beginPath();
draw.rect(start.x, start.y, w, h);
lastWidth = w;
lastHeight = h;
draw.stroke();
draw.closePath();
});
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: Math.floor(evt.clientX - rect.left),
y: Math.floor(evt.clientY - rect.top)
};
}
in above link able to draw multiple rectangles when i tried to drag mouse right side but unable to do when i drag it to left side. Could you please

I have just a little bit improved your code. It looks like you having some trouble when you trying to draw new rectangle over an already exists one.
I make a variable that will store the drawed rectangles. (Its like browser's brain) And the bottom of code, i created a setInterval() function that re-draw your rectangles that in the brain variable in 60fps.
var drawed_objects = []; //our brain variable
var isDown;
var start;
var end;
var canvasEl = document.getElementById("drawing");
var draw = canvasEl.getContext("2d");
draw.lineWidth = "2";
draw.strokeStyle = "blue";
var lastWidth = 0;
var lastHeight = 0;
$("#drawing").mousedown(function(e) {
isDown = true;
start = getMousePos(canvasEl, e);
end = getMousePos(canvasEl, e);
lastWidth = 0;
lastHeight = 0;
e.preventDefault();
});
$("#drawing").mouseup(function() {
drawed_objects.push({start:start,width:w,height:h});
isDown = false;
});
$("#drawing").mousemove(function(e) {
if (!isDown) return;
end = getMousePos(canvasEl, e);
h = end.y - start.y;
w = end.x - start.x;
draw.clearRect(start.x-5, start.y-5, lastWidth + 6, lastHeight + 6);
draw.beginPath();
draw.rect(start.x, start.y, w, h);
lastWidth = w;
lastHeight = h;
draw.stroke();
draw.closePath();
});
//in here we drawing old rectangles again again again..
//and all time clearing the canvas
setInterval(function(){
draw.clearRect(0,0,draw.canvas.width,draw.canvas.height);
for( let i=0; i <drawed_objects.length; i++ )
{
var obj = drawed_objects[i];
draw.beginPath();
draw.rect(obj.start.x, obj.start.y, obj.width, obj.height);
draw.stroke();
draw.closePath();
}
},1000/60);
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: Math.floor(evt.clientX - rect.left),
y: Math.floor(evt.clientY - rect.top)
};
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas width="800px" height="600px" id="drawing"></canvas>

Related

Issue when dragging text on canvas if slightly scrolled down

When I scroll slightly down on my canvas, it does not allow me to drag my text at all. Examples (These are GIFs) -
https://gyazo.com/e60d2efd924ced758c2c6441391804db
GIF explained: So you saw the drag was working when I was on top of the page but when I scrolled slightly down. It completely stopped working. I added a few console.logs around, and what I know is the click event listener for the canvas is working but it isn't detected the text when I slightly scroll down on the page.
I based my drag code from: http://jsfiddle.net/m1erickson/9xAGa/ | What you can see is if you change the canvas size width: 667 and height: 800, and when you scroll slightly down, you will have the same issue I am having.
HTML Code:
<div id="middle_container">
<div class="center_container">
<canvas id="canvas" width="667px" height="800px"></canvas>
</div>
</div>
JavaScript Code:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var BB=canvas.getBoundingClientRect();
var offsetX = BB.left;
var offsetY = BB.top;
var mx;
var my;
var texts = [];
var images = [];
var dragF = -1;
var mode = "none";
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for(const { text, x, y, width, height } of texts) {
ctx.fillText(text, x, y);
}
}
function addNewText(string_text) {
var y = texts.length * 20 + 20;
var text = {
text: string_text,
x: 20,
y: y
};
ctx.font = "32px verdana";
ctx.textBaseline = "top";
text.width = ctx.measureText(text.text).width;
text.height = 32;
texts.push(text);
draw();
}
function hitDrag(x,y,textIndex) {
var r=texts[textIndex];
return (x>r.x && x<r.x+r.width && y>r.y && y<r.y+r.height);
}
function myDrag(a,e) {
if (a == "down") {
e.preventDefault();
e.stopPropagation();
mx=parseInt(e.clientX-offsetX);
my=parseInt(e.clientY-offsetY);
for(var i=0;i<texts.length;i++){
if(hitDrag(mx,my,i)){
console.log("found");
dragF = i;
}
}
}
}
addNewText("Hello World")
$("#canvas").mousedown(function(e) {
myDrag("down", e);
});
The problem is this line of code:
var BB=canvas.getBoundingClientRect();
which is only populated once at the start of your script. The .getBoundingClientRect() method returns the position of a HTML element relative to the viewport.
Well if you scroll the window, the viewport moves - as the canvas element - but the BB object still holds the position of your canvas at startup.
The fix is rather simple - you need to use the actual position of the canvas element by calling .getBoundingClientRect() again on mouse down and on mouse move.
I've prepared a little sample based on your code and the fiddle you've linked:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var BB = canvas.getBoundingClientRect();
var offsetX = BB.left;
var offsetY = BB.top;
var mx;
var my;
var texts = [];
var images = [];
var dragF = -1;
var mode = "none";
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (const {
text,
x,
y,
width,
height
} of texts) {
ctx.fillText(text, x, y);
}
}
function addNewText(string_text) {
var y = texts.length * 20 + 20;
var text = {
text: string_text,
x: 20,
y: y
};
ctx.font = "32px verdana";
ctx.textBaseline = "top";
text.width = ctx.measureText(text.text).width;
text.height = 32;
texts.push(text);
draw();
}
function myDrag(a, e) {
if (a == "down") {
e.preventDefault();
e.stopPropagation();
let rect = canvas.getBoundingClientRect();
mx = parseInt(e.clientX - rect.left);
my = parseInt(e.clientY - rect.top);
for (var i = 0; i < texts.length; i++) {
if (hitDrag(mx, my, i)) {
// console.log("found");
dragF = i;
}
}
}
}
function hitDrag(x, y, textIndex) {
var r = texts[textIndex];
return (x > r.x && x < r.x + r.width && y > r.y && y < r.y + r.height);
}
function handleMouseMove(e) {
if (dragF < 0) {
return;
}
e.preventDefault();
let rect = canvas.getBoundingClientRect();
mouseX = parseInt(e.clientX - rect.left);
mouseY = parseInt(e.clientY - rect.top);
var dx = mouseX - mx;
var dy = mouseY - my;
mx = mouseX;
my = mouseY;
var text = texts[dragF];
text.x += dx;
text.y += dy;
draw();
}
function handleMouseUp(e) {
e.preventDefault();
dragF = -1;
}
addNewText("Hello World")
$("#canvas").mousedown(function(e) {
myDrag("down", e);
});
$("#canvas").mousemove(function(e) {
handleMouseMove(e);
});
$("#canvas").mouseup(function(e) {
handleMouseUp(e);
});
body {
background-color: ivory;
}
#canvas {
border: 1px solid red;
}
#theText {
width: 10em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="middle_container">
<div class="center_container">
<canvas id="canvas" width="667px" height="800px"></canvas>
</div>
</div>
<br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br>

Make Animated Sprite follow cursor on Mousedown with Javascript

This is my first posted question, so be gentle lol. I am trying to make a little game that will display different animated sprites on a canvas element that is laid over a user's webcam feed. Right now I am just working with one sprite to get the functionality right. I only want the sprite to appear and follow the mouse when left-click is held down. Right now the sprite appears on mousedown and animates, but disappears if I move the mouse instead of following. I only want it to disappear on mouseup. I have looked all over for the answer, but haven't been able to find one. Here is the js I have:
'use strict';
const video = document.getElementById('video');
const canvas = document.getElementById('canvas');
const errorMsgElement = document.querySelector('span#errorMsg');
canvas.width = window.innerWidth;
canvas.height =window.innerHeight;
const constraints = {
// audio: true,
video: {
// width: 1280, height: 720
width: window.innerWidth,
height: window.innerHeight
}
};
// Access webcam
async function init() {
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
handleSuccess(stream);
} catch (e) {
errorMsgElement.innerHTML = `navigator.getUserMedia error:${e.toString()}`;
}
}
// Success
function handleSuccess(stream) {
window.stream = stream;
video.srcObject = stream;
}
// Load init
init();
//Code for drawing sprite on Canvas
var image = new Image();
image.src = "Starsprite.png";
var ctx = canvas.getContext("2d");
let magic = false;
var spriteWidth = 187;
var spriteHeight = 60;
var rows = 1;
var cols = 3;
var width = spriteWidth/cols;
var height = spriteHeight/rows;
var curFrame = 0;
var frameCount = 3;
let x =0;
let y =0;
var srcX=0;
var srcY=0;
function startPosition(e){
magic =true;
x =e.clientX;
y =e.clientY;
}
function movePosition(e){
ctx.clearRect(x,y,width,height);
x =e.clientX;
y =e.clientY;
}
function endPosition(){
magic =false;
ctx.clearRect(x,y,width,height);
}
canvas.addEventListener("mousedown", startPosition);
canvas.addEventListener("mousemove",movePosition);
canvas.addEventListener("mouseup", endPosition);
canvas.addEventListener("mousedown",draw);
function updateFrame(){
curFrame = ++curFrame % frameCount;
srcX = curFrame * width;
}
function draw(){
if (!magic) return;
ctx.clearRect(x,y,width,height);
updateFrame();
ctx.drawImage(image,srcX,srcY,width,height, x,y,width,height);
console.log(x + ", " + y);
}
setInterval(draw,200);
The movePosition function does update the x & y coordinates, but the sprite doesn't show while the mouse is moving. I tried creating an event listener to run the draw function on mousemove, but it messes up the animation because it fires every time the browser updates the mouse position. Any ideas on tackling this problem?
Ok, so I have worked some more on it and animated the movement instead of trying to call the function over again. I based this on instructions for animating keystroke inputs. It works fairly well, but if I move the mouse very quickly to a new position it doesn't follow it all the way.
//Code for drawing on Canvas
var image = new Image();
image.src = "Starsprite.png";
var ctx = canvas.getContext("2d");
let magic = false;
var spriteWidth = 187;
var spriteHeight = 60;
var rows = 1;
var cols = 3;
var width = spriteWidth/cols;
var height = spriteHeight/rows;
var curFrame = 0;
var frameCount = 3;
let x =0;
let y =0;
let mousex =0;
let mousey =0;
var stillx =0;
var stilly =0;
var srcX=0;
var srcY=0;
var left =false;
var right =false;
var up = false;
var down = false;
var speed = 60;
var lift = 30;
var buffer = 100;
function startPosition(e){
magic =true;
x =e.clientX;
y =e.clientY;
}
function moveDirection(e){
stillx = x + buffer;
stilly = y + buffer;
mousex = e.clientX;
mousey = e.clientY;
if(mousex>stillx){
left = false;
right = true;
}
if(mousex<stillx){
left = true;
right = false;
}
if(mousey>stilly){
down = true;
up = false;
}
if(mousey<stilly){
down = false;
up = true;
}
}
function endPosition(){
magic =false;
ctx.clearRect(x,y,width,height);
}
canvas.addEventListener("mousedown", startPosition);
canvas.addEventListener("mousemove",moveDirection);
canvas.addEventListener("mouseup", endPosition);
canvas.addEventListener("mousedown",draw);
function moveSprite(){
if(right && x<canvas.width-width){
x+=speed;
// x+=speed;
right =false;
}
if(left && x>0){
x-=speed;
left=false;
}
if(down && y<canvas.height-height){
y+=lift;
down=false;
}
if(up && y>0){
y-=lift;
up=false;
}
}
function updateFrame(){
curFrame = ++curFrame % frameCount;
srcX = curFrame * width;
moveSprite();
}
function draw(){
if (!magic) return;
ctx.clearRect(x,y,width,height);
updateFrame();
ctx.drawImage(image,srcX,srcY,width,height, x,y,width,height);
}
setInterval(draw,200);
If anyone has a better solution please let me know!

Drawing a circle using mouse position

I am trying to draw a circle by clicking and dragging the mouse pointer. The way you would do in PowerPoint or something. The center of the circle is showing up in weird places and I can't explain it.
Here is the jsfiddle: https://jsfiddle.net/h8t3hfa2/2/
This is how I get the start and end position;
$('#c').mousedown(function(event) {
var parentOffset = $(this).offset();
circle = new Circle();
circle.start['x'] = event.pageX - parentOffset.left;
circle.start['y'] = event.pageY - parentOffset.top;
});
$('#c').mouseup(function(event) {
var parentOffset = $(this).offset();
circle.end['x'] = event.pageX - parentOffset.left;
circle.end['y'] = event.pageY - parentOffset.top;
circle.draw(canvas[0]);
});
When I console log the midpoint it looks correct but the circle shows up somewhere else. Any ideas?
It happens because you're scaling your canvas using CSS. Remember, canvas dimensions are different from canvas CSS (style) dimensions.
A quick fix is to equalize them:
canvas.get(0).width = canvas.width();
canvas.get(0).height = canvas.height();
https://jsfiddle.net/h8t3hfa2/3/
var Circle = function() {
this.start = [];
this.end = [];
}
Circle.prototype.draw = function(canvas) {
var me = this;
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var mid = me.getcenter();
var rad = me.getradius();
console.log(mid, rad);
ctx.beginPath();
console.log(mid['x'], mid['y']);
ctx.arc(mid['x'], mid['y'], rad, 0, 360);
ctx.stroke();
}
};
Circle.prototype.getcenter = function() {
var me = this;
//Check the start and end are set
var centerX = (me.start['x'] + me.end['x']) / 2;
var centerY = (me.start['y'] + me.end['y']) / 2;
return {
'x': centerX,
'y': centerY
};
};
Circle.prototype.getradius = function() {
var me = this;
var distX = Math.abs(me.start['x'] - me.end['x']);
var distY = Math.abs(me.start['y'] - me.end['y']);
return distX / 2;
};
var circle;
var canvas = $('#c');
// added only these two lines
canvas.get(0).width = canvas.width();
canvas.get(0).height = canvas.height();
$('#c').mousedown(function(event) {
var parentOffset = $(this).offset();
circle = new Circle();
circle.start['x'] = event.pageX - parentOffset.left;
circle.start['y'] = event.pageY - parentOffset.top;
});
$('#c').mouseup(function(event) {
var parentOffset = $(this).offset();
circle.end['x'] = event.pageX - parentOffset.left;
circle.end['y'] = event.pageY - parentOffset.top;
circle.draw(canvas[0]);
});
canvas {background-color: white;height: 100%;width: 100%;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id='c'></canvas>
You should probably also add an onresize event handler to reset the canvas dimensions when the window size changes because you're using a fluid layout. Be careful, though, modifying either of the canvas dimensions (even to the original size) will cause the canvas to clear.
Removing height: 100%; width: 100%; from styles fixes avoids the problem.
Off-topic, but I suggest editing getradius to use the min (or max) of distX and distY (instead of hardcoding distX) like the applications you mentioned.
Circle.prototype.getradius = function() {
var me = this;
var distX = Math.abs(me.start['x'] - me.end['x'])/2;
var distY = Math.abs(me.start['y'] - me.end['y'])/2;
return Math.min(distX, distY);
};

HTML5 canvas, make image rotate around click to select and drag circle

I have completed code that has a user click a button (to the right of the canvas), then the image is added to the canvas and is constrained to only move around the circumference of a circle. In order to move the image the user just needs to click the image and then move the mouse. To release the image the user simply needs to click where the image goes on the canvas.
Here is a fiddle showing what the current code does.
http://jsfiddle.net/smacnabb/68awv7sq/9/
Question: I am looking to be able to have the images that move around the circumference of the circle rotate while moving around the circumference of the circle.
This is what I mean:
Here is a fiddle for the code I added to try and make this happen
http://jsfiddle.net/smacnabb/68awv7sq/11/
in the handlemousemove method, it calls state.draw() every time the mouse move i'm passing mouseX, mouseY to state.draw.
state.draw() is in addstate method and this was the code I added to make the image rotate
var dx = mouseX - centerX;
var dy = mouseY - centerY;
var radianAngle = Math.atan2(dy, dx);
context.save();
context.translate(centerX, centerY);
context.rotate(radianAngle);
if (this.dragging) {
context.strokeStyle = 'black';
context.strokeRect(this.x, this.y, this.width + 2, this.height + 2)
}
context.drawImage(this.image, this.x, this.y);
context.restore();
What am I doing wrong?
You are close...Take a look at this example:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var radianAngle = 0;
var cx = 225;
var cy = 125;
var radius = 50;
// image loader
var imageURLs = [];
var imagesOK = 0;
var imgs = [];
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/cars.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/plane.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/cars1.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/plane1.png");
loadAllImages(start);
function loadAllImages(callback) {
for (var i = 0; i < imageURLs.length; i++) {
var img = new Image();
imgs.push(img);
img.onload = function() {
imagesOK++;
if (imagesOK >= imageURLs.length) {
callback();
}
};
img.onerror = function() {
alert("image load failed");
}
img.crossOrigin = "anonymous";
img.src = imageURLs[i];
}
}
var imagesY = 20;
var targets = [];
var selectedTarget = -1;
function start() {
var n = imgs.length / 2;
for (var i = 0; i < n; i++) {
var target = imgs[i + n];
ctx.drawImage(target, 15, imagesY);
targets.push({
x: 15,
y: imagesY,
width: target.width,
height: target.height,
image: imgs[i]
});
imagesY += target.height + 10;
}
}
function handleMouseDown(e) {
e.preventDefault();
x = parseInt(e.clientX - offsetX);
y = parseInt(e.clientY - offsetY);
for (var i = 0; i < targets.length; i++) {
var t = targets[i];
if (x >= t.x && x <= t.x + t.width && y >= t.y && y <= t.y + t.height) {
selectedTarget = i;
draw(x, y);
}
}
}
function handleMouseMove(e) {
if (selectedTarget < 0) {
return;
}
e.preventDefault();
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
draw(mouseX, mouseY);
}
function draw(mouseX, mouseY) {
var dx = mouseX - cx;
var dy = mouseY - cy;
var radianAngle = Math.atan2(dy, dx);
// Drawing code goes here
var img = targets[selectedTarget].image;
ctx.clearRect(100, 0, canvas.width, canvas.height);
// draw the circle
ctx.beginPath();
ctx.arc(cx, cy, radius, 0, Math.PI * 2);
ctx.closePath();
ctx.stroke();
// draw the image rotated around the circumference
ctx.save();
ctx.translate(cx, cy);
ctx.rotate(radianAngle);
ctx.drawImage(img, radius - img.width / 2, -img.height / 2);
ctx.restore();
}
$("#canvas").mousedown(function(e) {
handleMouseDown(e);
});
$("#canvas").mousemove(function(e) {
handleMouseMove(e);
});
body{ background-color: ivory; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Select an icon on left by clicking<br>
Then move mouse to have icon rotate around circle</h4>
<canvas id="canvas" width=350 height=350></canvas>

Optimize canvas drawing to make a continuous path

This is a script for filling canvas' grid squares with red color.
I'm looking for tips how to optimize my script to fill squares continuously, without chopping like here:
I tried to separate and merge some functions, but can't find a solution.
Here's the updated jsFiddle and my code:
HTML:
<canvas id="plan" width="501px" height="301px"></canvas>
JavaScript (updated):
var canvas = document.getElementById('plan');
var context = canvas.getContext('2d'),
wt = canvas.width,
ht = canvas.height;
var down = false;
var draw = function (e) {};
window.onload = grid();
var oldPos = {
mX: 0,
mY: 0
};
var dPos = {
mX: 0,
mY: 0
};
var curPos = {
mX: 0,
mY: 0
};
draw.to = function (X, Y) {
oldPos = getMousePos(canvas, e); //update position
var mposX = X,
mposY = Y;
mposX = mposX - mposX % 5;
mposY = mposY - mposY % 5;
context.fillStyle = "red";
context.fillRect(mposX + 0.5, mposY + 0.5, 5, 5);
};
draw.single = function (e) {
oldPos = getMousePos(canvas, e);
var mpos = getMousePos(canvas, e);
mpos.mX = mpos.mX - mpos.mX % 5;
mpos.mY = mpos.mY - mpos.mY % 5;
context.fillStyle = "red";
context.fillRect(mpos.mX + 0.5, mpos.mY + 0.5, 5, 5);
};
draw.move = function (e) {
if (down) {
curPos = getMousePos(canvas, e);
dPos.mX = Math.abs(curPos.mX - oldPos.mX); // distance between old & new (delta X)
dPos.mY = Math.abs(curPos.mY - oldPos.mY); // delta Y
if (dPos.mX >= 5 || dPos.mY >= 5) { // if the distance is bigger than 5px hz OR 5px vertical
lightIntermediateSquares(oldPos.mX, oldPos.mY, curPos.mX, curPos.mY); // ^ connect them
} else {
draw.single(e); // simple
}
}
};
draw.start = function (e) {
e.preventDefault();
down = true;
draw.single(e);
};
draw.stop = function (e) {
down = false;
};
function lightIntermediateSquares(startX, startY, endX, endY) {
for (var pct = 0; pct <= 1; pct += 0.03) {
var dx = endX - startX;
var dy = endY - startY;
var X = startX + dx * pct;
var Y = startY + dy * pct;
draw.to(X, Y); // is it okay?
}
}
function grid() {
context.strokeStyle = "#f0f0f0";
var h = 2.5,
p = 2.5;
context.strokeRect(0.5, 0.5, 5, 5);
for (i = 0; i < wt; i += p) {
p *= 2;
context.drawImage(canvas, p, 0);
}
for (i = 0; i < ht; i += h) {
h *= 2;
context.drawImage(canvas, 0, h);
}
}
function getMousePos(canvas, e) {
var rect = canvas.getBoundingClientRect();
return {
mX: e.clientX - rect.left - 1,
mY: e.clientY - rect.top - 1
};
}
canvas.addEventListener('mouseup', draw.stop, false);
canvas.addEventListener('mousedown', draw.start, false);
canvas.addEventListener('mousemove', draw.move, false);
canvas.addEventListener('mouseout', draw.stop, false);
Here's how to light the missing squares
Calculate a line between the previous mousemove and the current mousemove position.
Then walk that line using interpolation and color any grid squares that the line crosses.
// walk along a line from the last mousemove position
// to the current mousemove position.
// Then color any cells we pass over on our walk
for(var pct=0;pct<=1;pct+=0.06){
var dx = mouseX-lastX;
var dy = mouseY-lastY;
var X = parseInt(lastX + dx*pct);
var Y = parseInt(lastY + dy*pct);
if( !(X==lastForX && Y==lastForY) ){
draw.ColorCell(X,Y);
}
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/WvuHL/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var wt = canvas.width;
var ht = canvas.height;
var down = false;
var lastX=-20;
var lastY=-20;
var points=[];
var draw = function (e) {};
draw.started = false;
var count;
function interpolateLine(startX,startY,endX,endY){
var lastForX;
var lastForY;
//
for(var pct=0;pct<=1;pct+=0.06){
var dx = endX-startX;
var dy = endY-startY;
var X = startX + dx*pct;
var Y = startY + dy*pct;
if( !(X==lastForX && Y==lastForY) ){
draw.ColorCell(X,Y);
}
lastForX=X;
lastForY=Y;
}
}
draw.ColorCell=function(x,y){
var rw = x - 1;
var rh = y - 1;
rw = rw - rw % 5 + 0.5;
rh = rh - rh % 5 + 0.5;
context.fillStyle = "red";
context.fillRect( rw, rh, 5, 5);
};
draw.single = function (e) {
var mouseX=parseInt(e.clientX-offsetX);
var mouseY=parseInt(e.clientY-offsetY);
draw.ColorCell(mouseX,mouseY);
};
// mousemove
draw.move = function (e) {
if(!down){return;}
// get the current mouse position
var mouseX=parseInt(e.clientX-offsetX);
var mouseY=parseInt(e.clientY-offsetY);
// if we haven't moved off this XY, then don't bother processing further
if(mouseX==lastX && mouseY==lastY){return;}
// When running the for-loop below,
// many iterations will not find a new grid-cell
// so lastForX/lastForY will let us skip duplicate XY
var lastForX=lastX;
var lastForY=lastY;
// walk along a line from the last mousemove position
// to the current mousemove position.
// Then color any cells we pass over on our walk
for(var pct=0;pct<=1;pct+=0.06){
var dx = mouseX-lastX;
var dy = mouseY-lastY;
var X = parseInt(lastX + dx*pct);
var Y = parseInt(lastY + dy*pct);
if( !(X==lastForX && Y==lastForY) ){
draw.ColorCell(X,Y);
}
lastForX=X;
lastForY=Y;
}
// set this mouse position as starting position for next mousemove
lastX=mouseX;
lastY=mouseY;
};
// mousedown
draw.start = function (e) {
e.preventDefault();
lastX=parseInt(e.clientX-offsetX);
lastY=parseInt(e.clientY-offsetY);
down = true;
};
// mouseup
draw.stop = function (e) {
e.preventDefault();
down = false;
};
function grid() {
context.strokeStyle = "#f0f0f0";
var h = 2.5;
var p = 2.5;
context.strokeRect(0.5, 0.5, 5, 5);
for (i = 0; i < wt; i += p) {
p *= 2;
context.drawImage(canvas, p, 0);
}
for (i = 0; i < ht; i += h) {
h *= 2;
context.drawImage(canvas, 0, h);
}
}
canvas.addEventListener('mouseup', draw.stop, false);
canvas.addEventListener('mouseout', draw.stop, false);
canvas.addEventListener('mousedown', draw.start, false);
canvas.addEventListener('click', draw.single, false);
canvas.addEventListener('mousemove', draw.move, false);
grid();
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=501 height=301></canvas>
</body>
</html>

Categories

Resources