Daniel Adams
Daniel Adams

Reputation: 35

how to add tools to my canvas app

I have a fully working canvas app but its a bit plain at the moment and i would like to add tool, i am very new to java, but still now alot so i will be able to understand most of it, all i want to add is like shapes like rectangle and triangle and squares.

Here is a working demo of it so far.

HTML

<!doctype html>
<html>
 <head>
<link rel="shortcut icon" type="image/x-icon" href="SiteIcon.ico">
<title>Canvas</title>
<link rel="stylesheet" href="style.css">
<span style="cursor:crosshair"> 
</head>
<body>
<div id="toolbar">
    <div id="rad">
        Radius <span id="radval">10</span>

<div id="decrad" class="radcontrol">-</div>
<div id="incrad" class="radcontrol">+</div> 
<a href="../Be Creative.html"><font color="white">BACK</font></a>
<a href="Canvas.html"><font color="white">CLEAR</font></a>
</div>
<div id="colors">
    .          Colour:
        <input type="color" name="color1" id="color1" />
        <br />
        <br />
</div>
<canvas id="canvas" style="display: block;">sorry, your browser does not support our canvas tag.</canvas>
<script src="jQuery.js"></script>
</body>
</html>

CSS

* {
box-sizing: border-box;
-moz-box-sizing: border-box;
font-family: sans-serif;
margin: 0;
user-select:none;
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;


}
#toolbar {
width: 100%;
height: 50px;
padding: 10px;
position: fixed;
top: 0;
background-color: #2f2f2f;
color: white;
}
.radcontrol {
width: 30px;
height: 30px;
background-color: #4f4f4f;
display: inline-block;
text-align: center;
padding: 5px;
}
#rad {
float: left;
}
#colors {
}
.swatch {
width: 30px;
height: 30px;
border-radius: 15px;
box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.5), 0px 2px 2px rgba(0, 0, 0, 0.5);
display: inline-block;
margin-left: 10px;
}
.swatch.active {
border: 2px solid white;
box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.5);
}
#back {
width: 60px;
height: 5px;
padding: 5%;
background-color: white;
}

JavaScript

 function processData(c1, c2) {
            var cv1 = document.getElementById(c1).value;
            var cv2 = document.getElementById(c2).value;
            alert(cv1 + "\n" + cv2);
        }

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

var radius = 10;
var dragging = false;

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

context.lineWidth = radius * 2;

var putPoint = function (e) {
if (dragging) {
    var bounds = canvas.getBoundingClientRect();
    var mouseX = e.clientX + bounds.left;
    var mouseY = e.clientY - bounds.top;
    var mouseX = e.clientX + bounds.left - 20;
    context.lineTo(mouseX, mouseY)
    context.strokeStyle = document.getElementById('color1').value;
    context.stroke();
    context.beginPath();
    context.arc(mouseX, mouseY, radius, 0, Math.PI * 2);
    context.fillStyle = document.getElementById('color1').value;
    context.fill();
    context.beginPath();
    context.moveTo(mouseX, mouseY);
}
}

var engage = function (e) {
dragging = true;
putPoint(e);
}

var disengage = function () {
dragging = false;
context.beginPath();
}

canvas.addEventListener('mousedown', engage);
canvas.addEventListener('mousemove', putPoint);
canvas.addEventListener('mouseup', disengage);

var setRadius = function (newRadius) {
if (newRadius < minRad) newRadius = minRad;
else if (newRadius > maxRad) newRadius = maxRad;
radius = newRadius;
context.lineWidth = radius * 2;

radSpan.innerHTML = radius;
}

var minRad = 1,
maxRad = 100,
defaultRad = 20,
interval = 5,
radSpan = document.getElementById('radval'),
decRad = document.getElementById('decrad'),
incRad = document.getElementById('incrad');

decRad.addEventListener('click', function () {
setRadius(radius - interval);
});
incRad.addEventListener('click', function () {
setRadius(radius + interval);
});

setRadius(defaultRad);

Upvotes: 0

Views: 168

Answers (2)

Shomz
Shomz

Reputation: 37701

The first step would be extending the engage (mousedown) function because the way you have it now only works for a single functionality (putPoint). Then, you need to set a different event handler for mousemove for the same reason.

Your app needs to have states, like free drawing, rectangle, triangle, etc. The engage function first needs to read the current state (you can store the state in a variable), so if it's free drawing, it would work just as it works now, but if it is, for example, rectangle, then it would call a different function that you use for drawing rectangles.

You can go different ways about the implementation: you can simply click on the starting coordinates and click another time on the ending coordinates. Or you can start drawing the rectangle on mousedown and finish drawing it on mouseup. Both approaches still use 2 parameters: starting coordinates and ending coordinates.

With triangles it's a bit different since you obviously can't use the second approach from above (holding the mouse down while creating it) because the triangle requires three parameters (three dots).


UPDATE

And here is a super simple example of rectangle drawing using the mouse-down method I described above.

http://jsfiddle.net/egpr99k9/45/

This is the function that does the trick - it's call both on mouseup and mousedown events:

var rectData = {};
function drawRect(e, start) {
    var bounds = canvas.getBoundingClientRect();
    var mouseX = e.clientX + bounds.left - 20;
    var mouseY = e.clientY - bounds.top;
    if (start) {
        rectData.start = {
            x: mouseX,
            y: mouseY
        }
    }
    else {
        if (rectData.start) {
            context.beginPath();     
            context.rect(
                rectData.start.x, 
                rectData.start.y,
                mouseX - rectData.start.x, 
                mouseY - rectData.start.y
            );
            context.fillStyle = document.getElementById('color1').value;
            context.fill();
        }
        rectData.start = {};
    }
}

The next step here would be creating a live preview of the rectangle you're currently drawing (currently you won't see anything until you actually finish drawing it by releasing the mouse button). The best way to do it would be to use a temporary canvas on top of the main one, so that you can avoid problems with keeping the content "below" the rectangle you're currently drawing because you'd need to clear the canvas and refresh the preview on each mouse move while the button is down.

And once you release the mouse button, you would simply draw the contents of the temporary canvas to the main one, and delete or remove the temporary canvas.

I hope this is enough to get you started.


UPDATE

I went ahead and wrote you a simple example with live preview on a temporary canvas: http://jsfiddle.net/egpr99k9/46/

function processData(c1, c2) {
    var cv1 = document.getElementById(c1).value;
    var cv2 = document.getElementById(c2).value;
    alert(cv1 + "\n" + cv2);
}

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

var radius = 10;
var dragging = false;

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

context.lineWidth = radius * 2;

var putPoint = function (e) {
    if (dragging) {
        var bounds = canvas.getBoundingClientRect();
        var mouseX = e.clientX + bounds.left;
        var mouseY = e.clientY - bounds.top;
        var mouseX = e.clientX + bounds.left - 20;
        context.lineTo(mouseX, mouseY)
        context.strokeStyle = document.getElementById('color1').value;
        context.stroke();
        context.beginPath();
        context.arc(mouseX, mouseY, radius, 0, Math.PI * 2);
        context.fillStyle = document.getElementById('color1').value;
        context.fill();
        context.beginPath();
        context.moveTo(mouseX, mouseY);
    }
}

var tmpCanvas = document.getElementById('tmp');
tmpCanvas.width = canvas.width;
tmpCanvas.height = canvas.height;
tmpCanvas.id = 'tmp';
document.body.appendChild(tmpCanvas);
var tmpCtx = tmpCanvas.getContext('2d');

var rectData = {};

function drawRect(e, start, move) {
    var bounds = canvas.getBoundingClientRect();
    var mouseX = e.clientX + bounds.left - 20;
    var mouseY = e.clientY - bounds.top;
    if (start) {        
        rectData.start = {
            x: mouseX,
            y: mouseY
        }
    } else if (move) {
        tmpCanvas.width = tmpCanvas.width;
        tmpCtx.beginPath();
        tmpCtx.rect(
            rectData.start.x,
            rectData.start.y,
            mouseX - rectData.start.x,
            mouseY - rectData.start.y);
        tmpCtx.fillStyle = document.getElementById('color1').value;
        tmpCtx.fill();
    } else {
        if (rectData.start) {
            tmpCanvas.width = tmpCanvas.width;
            context.beginPath();
            context.rect(
                rectData.start.x,
                rectData.start.y,
                mouseX - rectData.start.x,
                mouseY - rectData.start.y);
            context.fillStyle = document.getElementById('color1').value;
            context.fill();
        }
        rectData.start = {};
    }
}

var engage = function (e) {
    dragging = true;
    //putPoint(e);
    drawRect(e, true);
}

var disengage = function (e) {
    dragging = false;
    context.beginPath();
    drawRect(e, false);
}

canvas.addEventListener('mousedown', engage);
canvas.addEventListener('mousemove', function(e){
    drawRect(e, false, true);
});
canvas.addEventListener('mouseup', disengage);

var setRadius = function (newRadius) {
    if (newRadius < minRad) newRadius = minRad;
    else if (newRadius > maxRad) newRadius = maxRad;
    radius = newRadius;
    context.lineWidth = radius * 2;
    
    radSpan.innerHTML = radius;
}

var minRad = 1,
    maxRad = 100,
    defaultRad = 20,
    interval = 5,
    radSpan = document.getElementById('radval'),
    decRad = document.getElementById('decrad'),
    incRad = document.getElementById('incrad');

decRad.addEventListener('click', function () {
    setRadius(radius - interval);
});
incRad.addEventListener('click', function () {
    setRadius(radius + interval);
});

setRadius(defaultRad);
* {
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    font-family: sans-serif;
    margin: 0;
    user-select:none;
    -webkit-user-select:none;
    -moz-user-select:none;
    -ms-user-select:none;
}
#toolbar {
    width: 100%;
    height: 50px;
    padding: 10px;
    position: fixed;
    top: 0;
    background-color: #2f2f2f;
    color: white;
}
.radcontrol {
    width: 30px;
    height: 30px;
    background-color: #4f4f4f;
    display: inline-block;
    text-align: center;
    padding: 5px;
}
#rad {
    float: left;
}
#colors {
}
.swatch {
    width: 30px;
    height: 30px;
    border-radius: 15px;
    box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.5), 0px 2px 2px rgba(0, 0, 0, 0.5);
    display: inline-block;
    margin-left: 10px;
}
.swatch.active {
    border: 2px solid white;
    box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.5);
}
#back {
    width: 60px;
    height: 5px;
    padding: 5%;
    background-color: white;
}
canvas {
  cursor: crosshair;
  display: block;
}
#tmp {
  pointer-events: none;
  display: block; position: absolute;left: 10px;top: 50px;
  opacity: 0.5;
}
<div id="toolbar">
    <div id="rad">Radius <span id="radval">10</span>

        <div id="decrad" class="radcontrol">-</div>
        <div id="incrad" class="radcontrol">+</div>	<a href="../Be Creative.html"><font color="white">BACK</font></a>
	<a href="Canvas.html"><font color="white">CLEAR</font></a>

    </div>
    <div id="colors">. Colour:
        <input type="color" name="color1" id="color1" />
        <br />
        <br />
    </div>
    <canvas id="canvas">sorry, your browser does not support our canvas tag.</canvas>
    <canvas id="tmp">sorry, your browser does not support our canvas tag.</canvas>
</div>

Upvotes: 1

Tegos
Tegos

Reputation: 422

Look, I rewrote your code with jQuery and Fabric.

function getRandInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}
var canvas = new fabric.Canvas('canvas', {
    isDrawingMode: true
});
var w = canvas.width;
var h = canvas.height;

$('#tri').click(function () {
    var triangle = new fabric.Triangle({
        width: getRandInt(10, w / 2),
        height: getRandInt(10, h / 2),
        fill: $('#color1').val(),
        left: getRandInt(10, w / 2),
        top: getRandInt(10, h / 2)
    });
    canvas.add(triangle);
});
$("#rect").click(function () {
    var rect = new fabric.Rect({
        width: getRandInt(10, w / 2),
        height: getRandInt(10, h / 2),
        fill: $('#color1').val(),
        left: getRandInt(10, w / 2),
        top: getRandInt(10, h / 2)
    });
    canvas.add(rect);
});
$("#circle").click(function () {
    var circle = new fabric.Circle({
        radius: getRandInt(10, w / 4),
        fill: $('#color1').val(),
        left: getRandInt(10, w / 2),
        top: getRandInt(10, h / 2)
    });
    canvas.add(circle);
});
$('#radius').change(function () {
    canvas.freeDrawingBrush.width = parseInt($(this).val(), 10) || 1;
});
$('#color1').change(function () {
    canvas.freeDrawingBrush.color = $(this).val();
});
$('#edit').click(function () {
    canvas.isDrawingMode = !canvas.isDrawingMode;
    $("#draw").prop('disabled', false);
    $(this).prop('disabled', true);
});
$('#draw').click(function () {
    canvas.isDrawingMode = !canvas.isDrawingMode;
    $("#edit").prop('disabled', false);
    $(this).prop('disabled', true);
});
$('#c').click(function () {
    canvas.clear();
});

Result JSFiddle!

Upvotes: 1

Related Questions