Skip to content

Commit

Permalink
Fixed latency issue and server-client comm bug. Now all colors are se…
Browse files Browse the repository at this point in the history
…nt and received accurately. Also added brush sizes and changed clear button color to fit theme.
  • Loading branch information
dinosoeren committed May 11, 2015
1 parent dfc8bc5 commit 5704930
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 49 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# App Design Final Project: Multi-User Drawing
By Casey Hofford and Soeren Walls

This node.js app allows multiple people to draw on the same canvas in their browser simultaneously.
This node.js app allows multiple people to draw on the same canvas in their browser simultaneously.

![Screenshot](/screenshot.png?raw=true "Screenshot")
8 changes: 4 additions & 4 deletions clear.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
64 changes: 59 additions & 5 deletions index.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ h2 {
text-align: center;
}

#color_swatch {
#color_swatch, #brush_size {
z-index: 2;
position: absolute;
display: inline-block;
Expand All @@ -32,18 +32,54 @@ h2 {
padding: 10px 20px;
}

#color_swatch .selector {
#color_swatch .selector, #brush_size .brush {
display: block;
width: 40px;
height: 40px;
border: 2px solid #444;
border: 2px solid rgba(44, 44, 44, 0.5);
border-radius: 3px;
clear: both;
float: none;
margin: 10px 0;
margin: 10px auto;
background-color: #fff;
opacity: 0.7;
transition-duration: 0.3s;
cursor: pointer;
color: rgba(44, 44, 44, 0.5);
}

#color_swatch .selector:hover, #brush_size .brush:hover {
border: 2px solid rgba(44, 44, 44, 1);
color: rgba(44, 44, 44, 1);
}
#color_swatch .selector:active, #brush_size .brush:active {
box-shadow: inset 0 0 5px #333;
}

#brush_size {
left: auto;
right: 0;
}

#brush_size .brush {
border-radius: 40px;
text-align: center;
display: table;
}
#brush_size .brush.selected {
background-color: rgba(44, 44, 44, 0.5);
color: #fff;
}
#brush_size .brush span {
display: table-cell;
vertical-align: middle;
}
#brush_size .brush[data-size="4"] {
width: 16px;
height: 16px;
}
#brush_size .brush[data-size="8"] {
width: 28px;
height: 28px;
}

#canvas_overlay, #table {
Expand Down Expand Up @@ -89,4 +125,22 @@ h2 {
margin: 10px;
padding: 10px;
cursor: pointer;
white-space: nowrap;
}

#clear #backcircle {
transition: 0.3s;
fill: #000;
stroke-color: #000;
}
#clear:hover #backcircle {
fill: #333;
stroke: #333;
}

#clear h2 {
transition: 0.3s;
}
#clear:hover h2 {
color: #333;
}
24 changes: 15 additions & 9 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,22 @@ <h2>by Casey Hofford and Soeren Walls</h2>
<div class="selector" style="background-color: white;"></div>
<div class="selector" style="background-color: black;"></div>
</div>
<div id="brush_size">
<div class="brush" data-size="4"><span>4</span></div>
<div class="brush selected" data-size="8"><span>8</span></div>
<div class="brush" data-size="16"><span>16</span></div>
</div>
<div id="canvas_overlay">
<!-- Where the click events happen. -->
</div>
<table id="table">
<tbody id="tbody">
</tbody>
</table>
<div id="clear">
<div id="clear" alt="Clear Canvas" title="Clear Canvas">
<h2>Clear</h2>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<!-- Clear button SVG created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
Expand All @@ -38,7 +44,7 @@ <h2>by Casey Hofford and Soeren Walls</h2>
version="1.1"
width="48"
height="48"
id="svg3866">
id="clearSVG">
<defs
id="defs3868" />
<metadata
Expand All @@ -61,16 +67,16 @@ <h2>by Casey Hofford and Soeren Walls</h2>
<path
d="m 425.71428,382.36218 a 145.71428,147.14285 0 1 1 -291.42856,0 145.71428,147.14285 0 1 1 291.42856,0 z"
transform="matrix(0,-1,1,0,-102.36218,662.36218)"
id="path2985"
style="fill:#ff0000;stroke:#ffffff;stroke-width:2.0999999;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
id="backcircle"
style="stroke-width:2.0999999;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
d="m 281.66236,500.85703 c 0,-126.29791 -0.55009,-195.85893 -1.16752,-234.15721"
id="path2987"
style="fill:none;stroke:#000000;stroke-width:35.04429626;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
id="x_part1"
style="fill:none;stroke:#ffffff;stroke-width:35.04429626;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
d="m 162.91799,385.18403 c 129.02475,0 199.87534,-0.55412 238.76691,-1.17431"
id="path2987-6"
style="fill:none;stroke:#000000;stroke-width:35.35589981;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
id="x_part2"
style="fill:none;stroke:#ffffff;stroke-width:35.35589981;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</g>
</svg>
Expand Down
105 changes: 85 additions & 20 deletions paint_client.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var cell_size = 3; // Each cell is 3x3 pixels.

var pen_color = "#000000";
var pen_size = 8; // This must always be a multiple of 4.
var brushSizeSelectors;

var changedCells = [];
var clickedCells = [];
Expand All @@ -27,7 +28,7 @@ function load()
console.log("Loaded");
window.setInterval(sendColors, 100);
window.setTimeout(
function() { window.setInterval(pollColors, 500); },
function() { window.setInterval(pollColors, 100); },
500
);
setupTable();
Expand Down Expand Up @@ -81,7 +82,7 @@ function setupCanvasOverlay()
clickCell();
}
}, true);
canvasOverlay.addEventListener("mouseup", function() {
document.addEventListener("mouseup", function() {
if(!clickDragFlag || !clickDownFlag) {
console.log("click");
}
Expand Down Expand Up @@ -110,6 +111,38 @@ function setupColorSelectors()
for(var i=0; i<colorSelectors.length; i++) {
colorSelectors.item(i).onclick = changePenColor;
}
var clearButton = document.getElementById("clear");
clearButton.onclick = clearCanvas;
brushSizeSelectors = document.getElementsByClassName("brush");
for(i=0; i<brushSizeSelectors.length; i++) {
brushSizeSelectors.item(i).onclick = changePenSize;
}
}

function changePenColor()
{
pen_color = this.style.backgroundColor;
console.log("Changed pen color to " + pen_color);
}

function changePenSize()
{
pen_size = parseInt(this.getAttribute("data-size"));
for(var i=0; i<brushSizeSelectors.length; i++) {
var brush = brushSizeSelectors.item(i);
if(brush === this) {
brush.className = "brush selected";
} else {
brush.className = "brush";
}
}
}

function clearCanvas()
{
var send_change = new XMLHttpRequest();
send_change.open("get", "clear_canvas");
send_change.send();
}

function clickCell()
Expand All @@ -125,7 +158,8 @@ function clickCell()
var tableCell = tableArray[rowIndex][cellIndex];
tableCell.style.backgroundColor = c;
tableCell.lastUpdated = new Date().getTime();
clickedCells.push({ x: cellIndex, y: rowIndex, c: c.replace("#","") });
if(clickedCells.indexOf(tableCell) === -1)
clickedCells.push(tableCell);
} catch(e) {
console.log("Error: Couldn't paint cell ["+rowIndex+", "+cellIndex+"].");
}
Expand All @@ -135,6 +169,7 @@ function clickCell()

function changeClickedCells()
{
// console.log("MOUSEUP. Clicked "+clickedCells.length+" cells.");
for(var i=0; i<clickedCells.length; i++) {
changedCells.push(clickedCells[i]);
}
Expand All @@ -143,13 +178,16 @@ function changeClickedCells()

function sendColors()
{
console.log("Sending colors.");
// console.log("Sending colors.");
if(changedCells.length > 0) {
var url = "change_cells?";
for(var i=0; i<changedCells.length; i++) {
var i;
for(i=0; i<changedCells.length; i++) {
var cell = changedCells[i];
url += "c"+i+"="+cell.x+"-"+cell.y+"-"+cell.c+"&";
var newData = "c"+i+"="+cell.x+"-"+cell.y+"-"+cell.style.backgroundColor+"&";
url += newData;
}
// console.log("SENDING. Url has "+i+" cells.");
changedCells = [];
var send_change = new XMLHttpRequest();
send_change.open("get", url);
Expand All @@ -159,7 +197,7 @@ function sendColors()

function pollColors()
{
console.log("Polling colors.");
// console.log("Polling colors.");
var request_colors = new XMLHttpRequest();
request_colors.startTime = new Date().getTime();
request_colors.onload = colorsListener;
Expand All @@ -170,8 +208,10 @@ function pollColors()
function colorsListener()
{
this.endTime = new Date().getTime();
console.log("Request load time: "+(this.endTime-this.startTime)+". Parsing response...");
// console.log("Request load time: "+(this.endTime-this.startTime)+". Parsing response...");
var canvas = JSON.parse(this.responseText);
var cellCount = 0;
var changedCellCount = 0;
if(canvas instanceof Array) {
for(var i=0; i<canvas.length; i++) {
var canvasRow = canvas[i];
Expand All @@ -181,31 +221,56 @@ function colorsListener()
var cellColor = canvasRow[j];
var tableCell = tableRow[j];
if(tableCell) {
cellCount++;
var currentColor = tableCell.style.backgroundColor;
if(currentColor != cellColor &&
this.startTime - tableCell.lastUpdated > 0 &&
changedCells.indexOf(tableCell) === -1 &&
clickedCells.indexOf(tableCell) === -1) {
if(!colorsSame(currentColor, cellColor) &&
this.startTime - tableCell.lastUpdated > 0 &&
changedCells.indexOf(tableCell) === -1 &&
clickedCells.indexOf(tableCell) === -1) {

changedCellCount++;
tableCell.style.backgroundColor = cellColor;
// console.log("Changing cell ["+i+", "+j+"] to " + cellColor + ".");

} else {
// console.log("Warning: Cell ["+i+", "+j+"] has been updated on the client more recently than the server. Won't overwrite.");
}
} else {
console.log("Response did not match table cell.");
console.log("Error: Response did not match table cell.");
}
}
} else {
console.log("Response was not a multidimensional array.");
console.log("Error: Response was not a multidimensional array.");
}
}
} else {
console.log("Response was not an array.");
console.log("Error: Response was not an array.");
}
// console.log("DONE PARSING. Response changed "+changedCellCount+" cells ("+cellCount+" total).");
}

function changePenColor()
{
pen_color = this.style.backgroundColor;
console.log("Changed pen color to " + pen_color);
function colorsSame(color1, color2) {
var same = false;
if(color1 === color2) {
same = true;
} else {
if(color1.toString().indexOf("#") > -1 && color2.toString().indexOf("rgb") > -1) {
color1 = hexToRgb(color1);
} else if(color2.toString().indexOf("#") > -1 && color1.toString().indexOf("rgb") > -1) {
color2 = hexToRgb(color2);
}
if(color1 === color2) {
same = true;
}
}
return same;
}

/* This function from http://stackoverflow.com/a/5624139/3673087 */
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ?
"rgb(" + parseInt(result[1], 16) + ", " +
parseInt(result[2], 16) + ", " +
parseInt(result[3], 16) + ")"
: null;
}
Loading

0 comments on commit 5704930

Please sign in to comment.