How to make all drawn (rectangle, circles, lines, polygon) draggable? Pure JS - javascript

I have a simple paint canvas html5. Its can draw through a selection option some shapes like lines, circles, rectangles, polygon, but now i want to make all draws draggable if possible resizable, without 3 part library only pure JS.
var canvas,
context,
dragStartLocation,
snapshot;
dragdrop = false;
isDrag = false;
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
function getCanvasCoordinates(event) {
var x = event.clientX - canvas.getBoundingClientRect().left;
y = event.clientY - canvas.getBoundingClientRect().top;
return {x: x, y: y};
}
function takeSnapshot() {
snapshot = context.getImageData(0, 0, canvas.width, canvas.height);
}
function restoreSnapshot() {
context.putImageData(snapshot, 0, 0);
}
function drawLine(position) {
context.beginPath();
context.moveTo(dragStartLocation.x, dragStartLocation.y);
context.lineTo(position.x, position.y );
context.stroke();
}
function drawRect(position) {
context.beginPath();
//context.moveTo(dragStartLocation.x, dragStartLocation.y);
context.fillRect(position.x, position.y, dragStartLocation.x - position.x, dragStartLocation.y - position.y);
//context.stroke();
}
function drawCircle(position) {
var radius = Math.sqrt(Math.pow((dragStartLocation.x - position.x), 2) + Math.pow((dragStartLocation.y - position.y), 2));
context.beginPath();
context.arc(dragStartLocation.x, dragStartLocation.y, radius, 0, 2 * Math.PI, false);
}
/*
function drawPolygon(position, sides, angle) {
var coordinates = [],
radius = Math.sqrt(Math.pow((dragStartLocation.x - position.x), 2) + Math.pow((dragStartLocation.y - position.y), 2)),
index = 0;
for (index = 0; index < sides; index++) {
coordinates.push({x: dragStartLocation.x + radius * Math.cos(angle), y: dragStartLocation.y - radius * Math.sin(angle)});
angle += (2 * Math.PI) / sides;
}
context.beginPath();
context.moveTo(coordinates[0].x, coordinates[0].y);
for (index = 1; index < sides; index++) {
context.lineTo(coordinates[index].x, coordinates[index].y);
}
context.closePath();
}*/
function draw(position) {
var fillBox = document.getElementById("fillBox"),
shape = document.querySelector('#tools option:checked').value,
/*polygonSides = document.getElementById("polygonSides").value,
polygonAngle = document.getElementById("polygonAngle").value,*/
lineCap = document.querySelector('input[type="radio"][name="lineCap"]:checked').value;
/*composition = document.querySelector('input[type="radio"][name="composition"]:checked').value;*/
context.lineCap = lineCap;
/*context.globalCompositeOperation = composition;*/
if (shape === "circle") {
drawCircle(position);
}
if (shape === "line") {
drawLine(position);
}
if (shape === "rect") {
drawRect(position);
}
if (shape === "polygon") {
drawPolygon(position, polygonSides, polygonAngle * (Math.PI / 180));
}
if (shape !== "line") {
if (fillBox.checked) {
context.fill();
} else {
context.stroke();
}
}
}
function dragStart(event) {
dragging = true;
dragStartLocation = getCanvasCoordinates(event);
takeSnapshot();
}
function drag(event) {
var position;
if (dragging === true) {
restoreSnapshot();
position = getCanvasCoordinates(event);
draw(position);
}
}
function dragStop(event) {
dragging = false;
restoreSnapshot();
var position = getCanvasCoordinates(event);
draw(position);
}
function changeLineWidth() {
context.lineWidth = this.value;
event.stopPropagation();
}
function changeFillStyle() {
context.fillStyle = this.value;
event.stopPropagation();
}
function changeStrokeStyle() {
context.strokeStyle = this.value;
event.stopPropagation();
}
function changeBackgroundColor() {
context.save();
context.fillStyle = document.getElementById("backgroundColor").value;
context.fillRect(0, 0, canvas.width, canvas.height);
context.restore();
}
function eraseCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
function init() {
canvas = document.getElementById("canvas");
context = canvas.getContext('2d');
var lineWidth = document.getElementById("lineWidth"),
fillColor = document.getElementById("fillColor"),
strokeColor = document.getElementById("strokeColor"),
//canvasColor = document.getElementById("backgroundColor"),
clearCanvas = document.getElementById("clearCanvas");
//saveCanvas = document.getElementById("saveCanvas");
context.strokeStyle = strokeColor.value;
context.fillStyle = fillColor.value;
context.lineWidth = lineWidth.value;
/*window.addEventListener('resize', resizeCanvas, false);
window.addEventListener('orientationchange', resizeCanvas, false);
resizeCanvas();*/
canvas.addEventListener('mousedown', dragStart, false);
canvas.addEventListener('mousemove', drag, false);
canvas.addEventListener('mouseup', dragStop, false);
lineWidth.addEventListener("input", changeLineWidth, false);
fillColor.addEventListener("input", changeFillStyle, false);
strokeColor.addEventListener("input", changeStrokeStyle, false);
//canvasColor.addEventListener("input", changeBackgroundColor, false);
clearCanvas.addEventListener("click", eraseCanvas, false);
//saveCanvas.addEventListener("click", salvaCanvas, false);
}
window.addEventListener('load', init, false);

It is an essential feature of canvas that it stores only the raster image formed as a result of all the draw operations. This why canvas is fast and memory efficient.
The downside is that you have to erase the affected rectangle on the canvas (or the whole canvas in the worst case) and redraw all the shapes that need to be resized, moved, etc. The canvas does not store them as objects, so your JS code must take care of storing, modifying and re-drawing them on the canvas. The effort is substantial unless you use some third party library.
The alternative is to use SVG-like features of HTML5 instead of canvas: <line>, <path>, <rect>, etc. They are kept as objects by the browser and accessible via DOM. This is a totally different approach, however, and requires a full rewrite of your code.

Related

How to draw parallelogram with draggable points

I have been studying JS for a few days, but I need to draw a parallelogram and allow user to change its angles by dragging one of its points. I took a code from a related question, and tried to change it (I know, it's a nightmare). But the 4th point doesn't work properly. I get this:
https://i.stack.imgur.com/PAjE6.png
How can I make the 4th point create a parallelogram?
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
var mouse = {};
var draggable = false;
context.lineWidth = 2;
context.strokeStyle = "blue";
var coordinates = [];
var isDone = false;
var clicks = 0;
canvas.addEventListener("mousedown", function(e) {
handleMouseDown(e);
});
function GetMassCenterAndFourthPoint(knownpoints) {
let point4X = knownpoints[2].x - knownpoints[1].x + knownpoints[0].x;
let point4Y = knownpoints[2].y - knownpoints[1].y + knownpoints[0].y;
coordinates.push({
x: point4X,
y: point4Y
});
}
function handleMouseDown(e) {
mouse = oMousePos(canvas, e);
//if isDone you can drag
if (isDone) {
for (index = 0; index < coordinates.length; index++) {
// you draw a small circle no stroke, no fill
context.beginPath();
context.arc(
coordinates[index].x,
coordinates[index].y,
5,
0,
2 * Math.PI
);
// if the mouse is inside the circle
if (context.isPointInPath(mouse.x, mouse.y)) {
// you can drag this point
// I'm using index + 1 because index == 0 is false
draggable = index + 1;
// if I have a point a can break the loop
break;
}
}
} else {
coordinates.push({
x: mouse.x,
y: mouse.y
});
drawPolygon();
clicks++;
if (clicks === 3) {
isDone = true;
}
}
}
function drawPolygon() {
context.clearRect(0, 0, cw, ch);
if (isDone) {
GetMassCenterAndFourthPoint(coordinates);
}
context.beginPath();
context.moveTo(coordinates[0].x, coordinates[0].y);
for (index = 1; index < coordinates.length; index++) {
context.lineTo(coordinates[index].x, coordinates[index].y);
}
context.closePath();
context.stroke();
// Additionaly I'm drawing a small circle around every point
// you can delete this.
for (index = 0; index < coordinates.length; index++) {
context.beginPath();
context.arc(coordinates[index].x, coordinates[index].y, 5, 0, 2 * Math.PI);
context.stroke();
}
}
canvas.addEventListener("mousemove", function(e) {
if (isDone) {
if (draggable) {
mouse = oMousePos(canvas, e);
// draggable - 1 is the index of the point in the coordinates array
coordinates[draggable - 1].x = mouse.x;
coordinates[draggable - 1].y = mouse.y;
drawPolygon();
}
}
});
canvas.addEventListener("mouseup", function(e) {
if (draggable) {
draggable = false;
}
});
// a function to detect the mouse position
function oMousePos(canvas, evt) {
var ClientRect = canvas.getBoundingClientRect();
return {
//objeto
x: Math.round(evt.clientX - ClientRect.left),
y: Math.round(evt.clientY - ClientRect.top)
};
}
canvas {
border: 1px solid black;
}
<canvas id="canvas" width="600" height="600"></canvas>
I also tried to draw my own parallelogram, but can't do it draggable
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
startX;
startY;
}
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
var mouse = {};
var draggable = false;
var points = [];
let isDone = false;
var clicks =0;
let click = false;
canvas.addEventListener("click", function(e) {
console.log(clicks);
clicks++;
if(!isDone){
const point = new Point(e.offsetX, e.offsetY);
points.push(point);
context.beginPath();
context.arc(point.x, point.y, 5, 0, 2 * Math.PI);
context.fillStyle = "red";
context.fill();
if(clicks===3){
isDone=true;
}
}
if(isDone){
GetMassCenterAndFourthPoint(points);
drawParallelogramAndCircle();
}
});
function GetMassCenterAndFourthPoint(knownpoints){
const point4X = knownpoints[2].x-knownpoints[1].x+knownpoints[0].x;
const point4Y = knownpoints[2].y-knownpoints[1].y+knownpoints[0].y;
context.beginPath();
context.arc(point4X, point4Y, 5, 0, 2 * Math.PI);
context.fillStyle = "red";
context.fill();
points.push(new Point(point4X, point4Y));
const massCenterX = (knownpoints[1].x+knownpoints[3].x)/2;
const massCenterY = (knownpoints[1].y+knownpoints[3].y)/2;
points.push(new Point(massCenterX, massCenterY));
}
function drawParallelogramAndCircle(){
context.beginPath();
context.moveTo(points[0].x, points[0].y);
for(let i=1;i<points.length-1;i++){
context.lineTo(points[i].x, points[i].y);
if(i===3){
context.lineTo(points[0].x, points[0].y);
}
}
context.strokeStyle = "blue";
context.closePath();
context.stroke();
// find square. Here will be the logic to calculate square
let square = 250;
context.beginPath();
context.arc(points[4].x, points[4].y, 30, 0, 2 * Math.PI);
context.strokeStyle = "yellow";
context.closePath();
context.stroke();
}
canvas {
border: 1px solid black;
}
<canvas id="canvas" width="600" height="600"></canvas>

How to make a ctrl+z keyboard event in a canvas?

I am trying to make an 'undo' action like Ctrl + Z.
I made a simple canvas paint example to make it easier to understand what I would like. When the user moves the mouse without releasing mouse1, something will be drawn on the canvas. Then, when they stop pressing mouse1, the drawing ends. The Ctrl + Z shortcut will undo these drawings.
Here is the code:
//var
const canvas = document.getElementById('canvas');
const cC = canvas.getContext('2d');
//trigger for write or not
var pressedQ = false;
//
function getMousePosition(evt) {
var rect = canvas.getBoundingClientRect();
var root = document.documentElement;
var mouseX = evt.clientX - rect.left - root.scrollLeft;
var mouseY = evt.clientY - rect.top - root.scrollTop;
return {
x: mouseX,
y: mouseY
};
}
function writeCircle(posX, posY, size, color) {
cC.fillStyle = 'black';
cC.beginPath();
cC.arc(posX, posY, size, 0, Math.PI*2, true);
cC.fill();
}
function pencil(evt) {
if (pressedQ == true) {
var mousePos = getMousePosition(evt);
writeCircle(mousePos.x, mousePos.y, 50);
}
else{}
}
function activate(textmode, evt) {
pressedQ = true;
console.log('start');
}
function deactivate() {
pressedQ = false;
console.log('finish');
}
window.onload = function() {
cC.clearRect(0, 0, canvas.width, canvas.height);
canvas.addEventListener('mousedown', activate);
canvas.addEventListener('mousemove', pencil);
canvas.addEventListener('mouseup', deactivate);
}
<canvas id="canvas" width="700" height="490"></canvas>
Thanks!
Note: I cant understand ES2015+ syntax
What you're looking for is the command design pattern. Since you're using functions here, you just need to store the function name and its parameters. Then, you can use that data to call the function again later. The following example isn't perfect, but it should demonstrate the basic idea. (I tried to avoid any JavaScript syntax that was added after the 2015 update)
var canvas = document.getElementById('canvas');
var cC = canvas.getContext('2d');
var pressedQ = false; //trigger for write or not
var commands = [];
var commandTypes = {
drawCircle: function (posX, posY, size, color) {
cC.fillStyle = 'black';
cC.beginPath();
cC.arc(posX, posY, size, 0, Math.PI * 2, true);
cC.fill();
}
};
function execute() {
var commandType = arguments[0];
var data = Array.prototype.slice.call(arguments, 1);
if (!commandTypes.hasOwnProperty(commandType))
throw new Error(commandType + ' is not a real command');
commandTypes[commandType].apply(null, data);
}
function pushAndExecute() {
commands.push(arguments);
execute.apply(null, arguments);
}
function getMousePosition(evt) {
var rect = canvas.getBoundingClientRect();
var root = document.documentElement;
return {
x: evt.offsetX - rect.left - root.scrollLeft,
y: evt.offsetY - rect.top - root.scrollTop
};
}
function pencil(evt) {
if (!pressedQ) return;
var mousePos = getMousePosition(evt);
pushAndExecute('drawCircle', mousePos.x, mousePos.y, 50);
}
function activate(evt) {
pressedQ = true;
// console.log('start');
pencil(evt);
}
function deactivate() {
pressedQ = false;
// console.log('finish');
}
function handleKeys(evt) {
if (evt.ctrlKey && evt.key === 'z') {
// console.log('undo');
// Remove the most recent command from the list
commands.splice(-1, 1);
// Clear canvas
cC.clearRect(0, 0, canvas.width, canvas.height);
// Re-play all commands (re-draw canvas from scratch)
commands.forEach(function (command) {
execute.apply(null, command);
});
}
}
window.onload = function() {
cC.clearRect(0, 0, canvas.width, canvas.height);
canvas.addEventListener('mousedown', activate);
canvas.addEventListener('mousemove', pencil);
canvas.addEventListener('mouseup', deactivate);
window.addEventListener('keydown', handleKeys);
}
<canvas id="canvas" width="700" height="490"></canvas>

Not able to draw a full circle on canvas in JavaScript using mouse events

I want to draw a simple circle on a canvas using mouse events, but what I am getting is partial circles, half circles, and sometimes a full one. The rectangle is working fine.Picture of resulting partial circles is attached.enter image description here
Code is
function draw() {
if (circ == 1)
{
context.beginPath();
context.arc(rect.startX, rect.startY, rect.w, rect.h, Math.PI * 2, false);
context.stroke();
}
}
function mouseDownrect(e) {
rect.startX = (e.layerX - this.offsetLeft);
rect.startY = e.layerY - this.offsetTop;
drag = true;
}
function mouseUprect() {
draw();
rect.w = 0;
rect.h = 0;
drag = false;
}
function mouseMoverect(e) {
if (drag == true) {
rect.w = (e.layerX - this.offsetLeft) - rect.startX;
rect.h = (e.layerY - this.offsetTop) - rect.startY;
}
}
function rectangle() {
color = 'black';
rectan = 1;
circ = 0;
pen = 0;
canvas.addEventListener('mousedown', mouseDownrect, false);
canvas.addEventListener('mouseup', mouseUprect, false);
canvas.addEventListener('mousemove', mouseMoverect, false);
}
function Circle()
{
color = 'black';
circ = 1;
rectan = 0;
pen = 0;
canvas.addEventListener('mousedown', mouseDownrect, false);
canvas.addEventListener('mouseup', mouseUprect, false);
canvas.addEventListener('mousemove', mouseMoverect, false);
}
The fourth argument in arc() is the starting ANGLE. So you want 0 to Math.PI * 2 for a full circle.
context.arc(rect.startX, rect.startY, rect.w, 0, Math.PI * 2, false);
Also, the 3rd argument is the RADIUS, and i don't know what you want that to be.

Draw polygons of fixed sides with mouse on canvas

I am trying to draw polygons(lets say 4 sided) on a canvas using mouse click and move events.
Click on canvas the moveTo(this point).
Now move the cursor a lineTo(the current point) but not intermediate point. Line should keep moving with mousemove and should be draw to the canvas only once clicked.
After fourth click(or any x) the polygon should closepath();
var pressed = false;
function myfunc1(e){
context.beginPath();
context.arc(e.clientX, e.clientY, radius, 0, Math.PI*2);
context.fill();
context.beginPath();
context.moveTo(e.clientX,e.clientY);
pressed = true;
}
function myfunc2(e){
if(pressed ===true){
context.lineTo(e.clientX,e.clientY);
context.stroke();
}
}
canvas.addEventListener('click',myfunc1);
canvas.addEventListener('mousemove',myfunc2);
I wrote this, but i don't want the intermediate lines
What you need is a stack. Don't think of drawing lines. Think of storing all your points of click in an array. And when you have clicked 4 times, draw the polygon (assuming that is what you want). Something like this:
var stack = [];
myfunc1(e){
stack.push(e.clientX, e.clientY);
if(stack.length == 4)
actuallyDraw();
}
var actuallyDraw(){
//take the 4 points in stack and draw the polygon
//clearing the stack for the next polygon
stack.length = 0;
}
canvas.addEventListener('click', myfunc1);
Use below code it will help you to solve your problem.
Click to assign polygon vertices point
<button id=done>Click when done assigning points</button>
<canvas id="canvas" width=450 height=450></canvas>
var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
context.lineWidth=2;
context.strokeStyle='blue';
var coordinates = [];
var isDone=false;
$('#done').click(function(){
isDone=true;
});
$("#canvas").mousedown(function(e){handleMouseDown(e);});
function handleMouseDown(e){
if(isDone || coordinates.length>10){return;}
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
coordinates.push({x:mouseX,y:mouseY});
drawPolygon();
}
function drawPolygon(){
context.clearRect(0,0,cw,ch);
context.beginPath();
context.moveTo(coordinates[0].x, coordinates[0].y);
for(index=1; index<coordinates.length;index++) {
context.lineTo(coordinates[index].x, coordinates[index].y);
}
context.closePath();
context.stroke();
}
I created an array(cords[]) which holds the coordinates of the polygon i am drawing and push them to another array (polygons[]) if the current polygon is completed. Then i can clear the canvas when required and redraw the polygons from polygon[]
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = document.getElementById("myimg");
ctx.drawImage(img, 0, 0);
var canvasOffset = $("#canvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var polygons = [];
var cords = [];
var start = false;
var control = false;
var clicks = 0;
ctx.strokeStyle = "orange";
ctx.lineWidth = 1;
$("#canvas").mousedown(function(e) {
handleMouseDown(e);
});
$("#canvas").mousemove(function(e) {
handleMouseMove(e);
});
function handleMouseDown(e) {
start = false;
clicks = clicks + 1;
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
cords.push([mouseX, mouseY]);
console.log(cords);
clearanddraw();
if (clicks % 4 === 0) {
return;
}
start = true;
}
function handleMouseMove(e) {
if (!start) {
return;
}
canvasclear();
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
ctx.beginPath();
ctx.moveTo(cords[clicks - 1][0], cords[clicks - 1][1]);
ctx.lineTo(mouseX, mouseY);
ctx.stroke();
}
function canvasclear() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(myimg, 0, 0);
drawOtherPol();
ctx.beginPath();
ctx.moveTo(cords[0][0], cords[0][1]);
for (var i = 0; i < clicks - 1; i++) {
ctx.lineTo(cords[i + 1][0], cords[i + 1][1]);
//alert("redrwan");
}
ctx.stroke();
return;
}
function clearanddraw() {
if (clicks > 1) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(myimg, 0, 0);
drawOtherPol();
ctx.beginPath();
ctx.moveTo(cords[0][0], cords[0][1]);
for (var i = 0; i < clicks - 1; i++) {
ctx.lineTo(cords[i + 1][0], cords[i + 1][1]);
}
if (clicks < 4) {
ctx.stroke();
}
if (clicks === 4) {
ctx.closePath();
ctx.stroke();
savepolygon();
cords = [];
clicks = 0;
return;
}
}
start = true;
}
function savepolygon() {
polygons.push(cords);
console.log(polygons);
return
}
function drawOtherPol() {
if (polygons.length === 0) {
return;
} else {
for (var i = 0; i < polygons.length; i++) {
ctx.beginPath();
ctx.moveTo(polygons[i][0][0], polygons[i][0][1]);
ctx.lineTo(polygons[i][1][0], polygons[i][1][1]);
ctx.lineTo(polygons[i][2][0], polygons[i][2][1]);
ctx.lineTo(polygons[i][3][0], polygons[i][3][1]);
ctx.closePath();
ctx.stroke();
}
return;
}
}

cloning a moving ball in javascript on a HTML canvas

Need help with cloning a moving ball in javascript. So the ball inherits the same property and actions of the moving ball when clicking it. I have tried using cloneNode(), using prototype and inheritance.
The cloning area within the code is after the comment //Clone prototype and constructor
Here is the full code below and the Demo in JS fiddle at the bottom of this code.
#balling {
border:1px solid rgb(0,0,0);
}
</style>
</head>
<body>
<canvas id="balling" width="500" height="400"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('balling');
var context = canvas.getContext('2d');
// The Properties of the Circle and Position within the Viewport
var CircleOptions = {
posBall: {
x: 160,
y: 180
},
radius: 40,
startAngle: 0,
endAngle: Math.PI * 2,
anticlockwise: false,
radians: 0,
xMove: Math.random(),
yMove: Math.random(),
speed:2,
angle:80,
velocityX:1,
velocityY:1
};
//Math to make the ball move
function moveBall() {
CircleOptions.radians = CircleOptions.angle * Math.PI/180;
CircleOptions.xMove = Math.cos(CircleOptions.radians) * CircleOptions.speed * CircleOptions.velocityX;
CircleOptions.yMove = Math.sin(CircleOptions.radians) * CircleOptions.speed * CircleOptions.velocityY;
}
//Function to draw the ball
function DrawOptions() {
//Reset Canvas
context.fillStyle = "white";
context.fillRect(0, 0, canvas.width, canvas.height);
//Drawing of the ball
context.fillStyle = "rgb(142, 68, 173)";
context.beginPath();
context.arc(CircleOptions.posBall.x, CircleOptions.posBall.y, CircleOptions.radius, CircleOptions.startAngle, CircleOptions.endAngle, CircleOptions.anticlockwise);
context.closePath();
context.fill();
}
//finding the coordinates of the circle
function CircleCoordinates() {
CircleOptions.left = CircleOptions.posBall.x - CircleOptions.radius,
CircleOptions.right = CircleOptions.posBall.x + CircleOptions.radius,
CircleOptions.top = CircleOptions.posBall.y - CircleOptions.radius,
CircleOptions.bottom = CircleOptions.posBall.y + CircleOptions.radius;
}
// Animate and call the function to move the ball
setInterval(Move, 20);
//Function call for the ball
moveBall();
//The function to make it move, reset canvas for movement and color/create shape of ball
function Move() {
//Function call for drawing and pinpointing the coordinates
DrawOptions();
CircleCoordinates();
//Power to make it move
CircleOptions.posBall.x += CircleOptions.xMove;
CircleOptions.posBall.y += CircleOptions.yMove;
//checks for ball hitting the Wall
if(CircleOptions.posBall.x > canvas.width || CircleOptions.posBall.x < 0) {
CircleOptions.angle -= 770;
moveBall();
} else if(CircleOptions.posBall.y > canvas.height || CircleOptions.posBall.y < 0) {
CircleOptions.angle -= 2760;
moveBall();
} else if(CircleOptions.posBall.y == canvas.height || CircleOptions.posBall.y > canvas.width) {
CircleOptions.angle += 90;
moveBall();
}
}
canvas.addEventListener('click', function (e) {
var clickedX = e.pageX - this.offsetLeft;
var clickedY = e.pageY - this.offsetTop;
if (clickedX < CircleOptions.right && clickedX > CircleOptions.left && clickedY > CircleOptions.top && clickedY < CircleOptions.bottom) {
// alert('Double Me Please!');
Clone();
}
});
// Clone prototype and constructor
function Clone() {
var newCanvas = document.getElementById('balling');
var context = newCanvas.getContext('2d');
context.fillStyle = "rgb(142, 68, 173)";
context.beginPath();
context.arc(CircleOptions.posBall.x, CircleOptions.posBall.y, CircleOptions.radius, CircleOptions.startAngle, CircleOptions.endAngle, CircleOptions.anticlockwise);
context.closePath();
context.fill();
return newCanvas;
}
//function call for clone
//For cursor style in and out element
canvas.addEventListener('mouseover', function () {
document.body.style.cursor = "pointer";
});
canvas.addEventListener('mouseout', function () {
document.body.style.cursor = "default";
});
</script>
An Updated Fiddle Demo: http://jsfiddle.net/coder101/CMW24/5/
In your jsFiddle version:
The Clone method and call at the bottom don't do anything.
Your CircleOptions is really not options, it's the object that represents the ball.
Your Move function is the repeating controller that makes it move around.
Your setInterval method is what starts it running by calling Move and uses the existing DrawOptions and CircleOptions; CircleCoordinates doesn't do anything at all.
If you want to clone the ball, you'd want to create an array of CircleOptions objects (change the name) and then loop through them inside Move or they should probably each have their own Move method and act on that. But if it's JavaScript, having them all move within one method would be less processor intensive.
I cleaned up the code and removed the code that didn't do anything. Now I'd make the balls belong to an array and make your click event add more balls. I'll leave that exercise to you.
var canvas = document.getElementById('balling');
var context = canvas.getContext('2d');
var ball = function( new_x, new_y) {
var b = {};
b.posBall = {
x: new_x,
y: new_y
};
b.radius = 40;
b.startAngle = 0;
b.endAngle = Math.PI * 2;
b.anticlockwise = false;
b.radians = 0;
b.xMove = Math.random();
b.yMove = Math.random();
b.speed = 2;
b.angle = 80;
b.velocityX = 1;
b.velocityY = 1;
return b;
}
//Function to clear the canvas
function DrawReset() {
//Reset Canvas
context.fillStyle = "white";
context.fillRect(0, 0, canvas.width, canvas.height);
//Drawing of the ball
context.fillStyle = "rgb(142, 68, 173)";
context.beginPath();
context.arc(CurrentBall.posBall.x, CurrentBall.posBall.y, CurrentBall.radius, CurrentBall.startAngle, CurrentBall.endAngle, CurrentBall.anticlockwise);
context.closePath();
context.fill();
}
//Math to make the ball move
function moveBall() {
CurrentBall.radians = CurrentBall.angle * Math.PI / 180;
CurrentBall.xMove = Math.cos(CurrentBall.radians) * CurrentBall.speed * CurrentBall.velocityX;
CurrentBall.yMove = Math.sin(CurrentBall.radians) * CurrentBall.speed * CurrentBall.velocityY;
}
//The function to make it move, reset canvas for movement and color/create shape of ball
function Move() {
//Function call for drawing and pinpointing the coordinates
DrawReset();
//Power to make it move
CurrentBall.posBall.x += CurrentBall.xMove;
CurrentBall.posBall.y += CurrentBall.yMove;
//checks for ball hitting the Wall
if (CurrentBall.posBall.x > canvas.width || CurrentBall.posBall.x < 0) {
CurrentBall.angle -= 770;
moveBall();
} else if (CurrentBall.posBall.y > canvas.height || CurrentBall.posBall.y < 0) {
CurrentBall.angle -= 2760;
moveBall();
} else if (CurrentBall.posBall.y == canvas.height || CurrentBall.posBall.y > canvas.width) {
CurrentBall.angle += 90;
moveBall();
}
}
canvas.addEventListener('click', function (e) {
var clickedX = e.pageX - this.offsetLeft;
var clickedY = e.pageY - this.offsetTop;
alert(e.pageX + ' ' + e.pageY);
if (clickedX > CurrentBall.right && clickedX > CurrentBall.left && clickedY > CurrentBall.top && clickedY < CurrentBall.bottom) {
alert('clicked number ');
}
});
var CurrentBall = ball(160,180);
// Animate and call the function to move the ball
setInterval(Move, 20);

Categories