am using pdf.js here am rendering my pdf in canvas,
My code is:
<div id="viewerContainer" tabindex="0">
<div id="viewer" class="pdfViewer"></div>
</div>
The above canvas is generating through viewer.js
Now I am trying to draw rectangle on my pdf, but its not showing my rectangle,
My script is in below:
<script type="text/javascript">
var canvas, context, startX, endX, startY, endY;
var mouseIsDown = 0;
function init() {
canvas = document.getElementById("page1");
context = canvas.getContext("2d");
canvas.addEventListener("mousedown", mouseDown, false);
canvas.addEventListener("mousemove", mouseXY, false);
canvas.addEventListener("mouseup", mouseUp, false);
}
function mouseUp() {
if (mouseIsDown !== 0) {
mouseIsDown = 0;
drawSquare(); //update on mouse-up
}
}
function mouseDown() {
mouseIsDown = 1;
startX = endX = event.clientX - canvas.offsetLeft; //remember to subtract
startY = endY = event.clientY - canvas.offsetTop; //canvas offset
drawSquare(); //update
}
function mouseXY(eve) {
if (mouseIsDown !== 0) {
if (!eve) {
var eve = event;
}
endX = event.pageX - canvas.offsetLeft;
endY = event.pageY - canvas.offsetTop;
drawSquare();
}
}
function drawSquare() {
// creating a square
var width = Math.abs(startX - endX);
var height = Math.abs(startY - endY);
context.clearRect(0, 0, context.width, context.height);
//or use fillRect if you use a bg color
context.beginPath();
context.rect(startX, startY, width, height);
context.fillStyle = "yellow";
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();
}
</script>
viwer.js code:
var canvasWrapper = document.createElement('div');
canvasWrapper.style.width = div.style.width;
canvasWrapper.style.height = div.style.height;
canvasWrapper.classList.add('canvasWrapper');
if (this.annotationLayer && this.annotationLayer.div) {
div.insertBefore(canvasWrapper, this.annotationLayer.div);
} else {
div.appendChild(canvasWrapper);
}
var textLayer = null;
if (this.textLayerFactory) {
var textLayerDiv = document.createElement('div');
textLayerDiv.className = 'textLayer';
textLayerDiv.style.width = canvasWrapper.style.width;
textLayerDiv.style.height = canvasWrapper.style.height;
if (this.annotationLayer && this.annotationLayer.div) {
div.insertBefore(textLayerDiv, this.annotationLayer.div);
} else {
div.appendChild(textLayerDiv);
}
textLayer = this.textLayerFactory.createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport, this.enhanceTextSelection);
}
var viewport = this.viewport;
var canvas = document.createElement('canvas');
canvas.id = this.renderingId;
canvas.setAttribute('hidden', 'hidden');
var isCanvasHidden = true;
var showCanvas = function showCanvas() {
if (isCanvasHidden) {
canvas.removeAttribute('hidden');
isCanvasHidden = false;
}
};
canvasWrapper.appendChild(canvas);
Is there any mistake in my code? I have searched many source but I could not able to find the correct one. Kindly help me in this issue.
Related
I have a canvas, which will display videos taken from file upload on the first layer, and the second layer allow rectangles to be drawn. As I am trying to annotate videos and not still images, I will need the annotations to be saved then cleared, and then redrawn again and again until the video is over. However, I have no clue how I should do so as I am relatively new to JavaScript.
This is the code I have for now for the drawing of the annotations:
// Drawing boxes
function handleMouseDown(e) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
console.log(mouseX, mouseY);
$("#downlog").html("Down: " + mouseX + " / " + mouseY);
// Put your mousedown stuff here
if (mouseIsDown) {
console.log('1');
canvas2.style.cursor = "crosshair";
mouseIsDown = false;
mouseIsUp = false;
console.log(mouseIsDown);
} else {
handleMouseUp();
}
mouseIsDown = false;
mouseIsUp = true;
}
function handleMouseUp(e) { // array? user input?
mouseIsDown = false;
startX = parseInt(e.clientX - offsetX);
startY = parseInt(e.clientY - offsetY);
/*if (mouseIsUp) {
console.log('2');*/
draw();
}
function draw() {
/* context2.clearRect(0, 0, canvas2.width, canvas2.height);*/
context2.beginPath();
context2.rect(startX, startY, mouseX - startX, mouseY - startY);
context2.strokeStyle = "limegreen";
context2.lineWidth = 2;
context2.stroke();
canvas2.style.cursor = "default";
}
$("#canvas2").mousedown(function(e) {
handleMouseDown(e);
});
$("#canvas2").mouseup(function(e) {
handleMouseUp(e);
});
function clearcanvas()
{
var canvas2 = document.getElementById('canvas2'),
context2 = canvas2.getContext("2d");
context2.clearRect(0, 0, canvas2.width, canvas2.height);
}
I will really appreciate any help, thank you!
Please read the comments. I hope my code is clear enough.
let c = document.getElementById("canvas");
let ctx = c.getContext("2d");
// the array of all rectangles
let rectsRy = [];
// the actual rectangle, the one that is beeing drawn
let o={};
// a variable to store the mouse position
let m = {},
// a variable to store the point where you begin to draw the rectangle
start = {};
// a boolean
let isDrawing = false;
function handleMouseDown(e) {
start = oMousePos(c, e);
isDrawing = true;
//console.log(start.x, start.y);
c.style.cursor = "crosshair";
}
function handleMouseMove(e) {
if(isDrawing){
m = oMousePos(c, e);
draw();
}
}
function handleMouseUp(e) { // array? user input?
c.style.cursor = "default";
isDrawing = false;
// push a new rectangle into the rects array
rectsRy.push({x:o.x,y:o.y,w:o.w,h:o.h});
}
function draw() {
o.x = start.x;
o.y = start.y;
o.w = m.x - start.x;
o.h = m.y - start.y;
clearcanvas();
// draw all the rectangles saved in the rectsRy
rectsRy.map(r => {drawRect(r)})
// draw the actual rectangle
drawRect(o);
}
c.addEventListener("mousedown", handleMouseDown);
c.addEventListener("mousemove", handleMouseMove);
c.addEventListener("mouseup", handleMouseUp);
function clearcanvas(){
ctx.clearRect(0, 0, c.width, c.height);
}
function drawRect(o){
ctx.strokeStyle = "limegreen";
ctx.lineWidth = 2;
ctx.beginPath(o);
ctx.rect(o.x,o.y,o.w,o.h);
ctx.stroke();
}
// a function to detect the mouse position
// the function returns an object
function oMousePos(canvas, evt) {
let ClientRect = canvas.getBoundingClientRect();
return {
x: Math.round(evt.clientX - ClientRect.left),
y: Math.round(evt.clientY - ClientRect.top)
}
}
canvas{border:1px solid #d9d9d9;}
<canvas id="canvas" width="600" height="300">
Before I edited my code to create the boxes as objects and push them into an array, I could draw multiple boxes on the canvas and all of them would show up at once (until I cleared the canvas). However, now only one box shows up on the canvas at once, and when I draw another box, the previous box would be removed (although they would still be created as an object and pushed into the array). How do I edit my code so that I can draw multiple boxes onto the canvas and have them all show up together, until I clear the canvas?
Code:
const annotation = {
xcoordi: 0,
ycoordi: 0,
width: 0,
height: 0,
printCoordinates: function () {
console.log(`X: ${this.xcoordi}px, Y: ${this.ycoordi}px, Width: ${this.width}px, Height: ${this.height}px`);
}
};
//the array of all rectangles
let boundingBoxes = [];
// the actual rectangle, the one that is being drawn
let o={};
// a variable to store the mouse position
let m = {},
// a variable to store the point where you begin to draw the rectangle
start = {};
// a boolean
let isDrawing = false;
function handleMouseDown(e) {
start = oMousePos(canvas2, e);
isDrawing = true;
//console.log(start.x, start.y);
canvas2.style.cursor = "crosshair";
}
function handleMouseMove(e) {
if(isDrawing){
m = oMousePos(canvas2, e);
draw();
}
}
function handleMouseUp(e) {
canvas2.style.cursor = "default";
isDrawing = false;
const box = Object.create(annotation);
box.xcoordi = o.x;
box.ycoordi = o.y;
box.width = o.w;
box.height = o.h;
boundingBoxes.push(box);
draw();
box.printCoordinates();
console.log(boundingBoxes)
}
function draw() {
o.x = start.x; // start position of x
o.y = start.y; // start position of y
o.w = m.x - start.x; // width
o.h = m.y - start.y; // height
clearcanvas();
// draw all the rectangles saved in the rectsRy
boundingBoxes.map(r => {drawRect(r)})
// draw the actual rectangle
drawRect(o);
}
canvas2.addEventListener("mousedown", handleMouseDown);
canvas2.addEventListener("mousemove", handleMouseMove);
canvas2.addEventListener("mouseup", handleMouseUp);
function savecanvas(){
context2.clearRect(0, 0, canvas2.width, canvas2.height);
var savedBoxes = boundingBoxes.slice(0);
console.log(savedBoxes); // ok
}
function resetcanvas(){
context2.clearRect(0, 0, canvas2.width, canvas2.height);
boundingBoxes.length = 0;
console.log(boundingBoxes); // ok
}
function drawRect(o){
context2.strokeStyle = "limegreen";
context2.lineWidth = 2;
context2.beginPath(o);
context2.rect(o.x,o.y,o.w,o.h);
context2.stroke();
}
// Function to detect the mouse position
function oMousePos(canvas2, evt) {
let ClientRect = canvas2.getBoundingClientRect();
return {
x: Math.round(evt.clientX - ClientRect.left),
y: Math.round(evt.clientY - ClientRect.top)
}
}
Any help is really appreciated, thank you!
You have 2 errors:
in your code you are using a clearcanvas(); function which is not defined. I've replaced it with context2.clearRect(0, 0, canvas2.width, canvas2.height);
and this is more important: the object you save has these properties: xcoordi, ycoordi, width, height, BUT in drawRect(o) you are using x, y, w, h to draw the rect, but x, y, w, h are undefined, and thus no rect is drawn.
Please check my code:
const canvas2 = document.getElementById("canvas");
const context2 = canvas.getContext("2d");
const annotation = {
x: 0,
y: 0,
w: 0,
h: 0,
printCoordinates: function () {
console.log(`X: ${this.x}px, Y: ${this.y}px, Width: ${this.w}px, Height: ${this.h}px`);
}
};
//the array of all rectangles
let boundingBoxes = [];
// the actual rectangle, the one that is being drawn
let o={};
// a variable to store the mouse position
let m = {},
// a variable to store the point where you begin to draw the rectangle
start = {};
// a boolean
let isDrawing = false;
function handleMouseDown(e) {
start = oMousePos(canvas2, e);
isDrawing = true;
//console.log(start.x, start.y);
canvas2.style.cursor = "crosshair";
}
function handleMouseMove(e) {
if(isDrawing){
m = oMousePos(canvas2, e);
draw();
}
}
function handleMouseUp(e) {
canvas2.style.cursor = "default";
isDrawing = false;
const box = Object.create(annotation);
box.x = o.x;
box.y = o.y;
box.w = o.w;
box.h = o.h;
boundingBoxes.push(box);
draw();
box.printCoordinates();
console.log(boundingBoxes)
}
function draw() {
o.x = start.x; // start position of x
o.y = start.y; // start position of y
o.w = m.x - start.x; // width
o.h = m.y - start.y; // height
//clearcanvas();
context2.clearRect(0, 0, canvas2.width, canvas2.height);//////***********
// draw all the rectangles saved in the rectsRy
boundingBoxes.map(r => {drawRect(r)})
// draw the actual rectangle
drawRect(o);
}
canvas2.addEventListener("mousedown", handleMouseDown);
canvas2.addEventListener("mousemove", handleMouseMove);
canvas2.addEventListener("mouseup", handleMouseUp);
function savecanvas(){
context2.clearRect(0, 0, canvas2.width, canvas2.height);
var savedBoxes = boundingBoxes.slice(0);
console.log(savedBoxes); // ok
}
function resetcanvas(){
context2.clearRect(0, 0, canvas2.width, canvas2.height);
boundingBoxes.length = 0;
console.log(boundingBoxes); // ok
}
function drawRect(o){
context2.strokeStyle = "limegreen";
context2.lineWidth = 2;
context2.beginPath(o);
context2.rect(o.x,o.y,o.w,o.h);
context2.stroke();
}
// Function to detect the mouse position
function oMousePos(canvas2, evt) {
let ClientRect = canvas2.getBoundingClientRect();
return {
x: Math.round(evt.clientX - ClientRect.left),
y: Math.round(evt.clientY - ClientRect.top)
}
}
canvas{border:1px solid;}
<canvas id="canvas"></canvas>
void function() {
"use strict";
// Variables
var canvasWidth = 180;
var canvasHeight = 160;
var canvas = null;
var ctx = null;
var rectangles = [];
var isDrawing = false;
var mouseStartX = 0.0;
var mouseStartY = 0.0;
var mouseEndX = 0.0;
var mouseEndY = 0.0;
// Functions
// Constructor function (called with 'new')
function Rectangle(x,y,width,height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
function draw() {
ctx.fillStyle = "black";
ctx.fillRect(0,0,canvasWidth,canvasHeight);
ctx.strokeStyle = "limegreen";
ctx.lineWidth = 2;
ctx.beginPath();
for (var i = 0; i < rectangles.length; ++i) {
var rectangle = rectangles[i];
ctx.rect(
rectangle.x,
rectangle.y,
rectangle.width,
rectangle.height
);
}
ctx.stroke();
}
function getMousePosition(e) {
if (canvas && e) {
var bounds = canvas.getBoundingClientRect();
return [
e.clientX - bounds.left,
e.clientY - bounds.top
];
} else {
return [
0.0,
0.0
];
}
}
// Event Handlers
window.onmousedown = function(e) {
if (!isDrawing) {
isDrawing = true;
// Destructuring Assignment
[mouseStartX,mouseStartY] = getMousePosition(e);
canvas.style.cursor = "crosshair";
}
}
window.onmouseup = function(e) {
if (isDrawing) {
isDrawing = false;
// Destructuring Assignment
[mouseEndX,mouseEndY] = getMousePosition(e);
rectangles.push(
new Rectangle(
mouseStartX,
mouseStartY,
mouseEndX - mouseStartX,
mouseEndY - mouseStartY
)
);
draw();
canvas.style.cursor = "default";
}
}
window.onmousemove = function(e) {
if (isDrawing) {
// Destructuring Assignment
[mouseEndX,mouseEndY] = getMousePosition(e);
draw();
ctx.strokeStyle = "darkred";
ctx.lineWidth = 2;
ctx.beginPath();
ctx.rect(
mouseStartX,
mouseStartY,
mouseEndX - mouseStartX,
mouseEndY - mouseStartY
);
ctx.stroke();
}
}
// Runs when the page loads
window.onload = function() {
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
ctx = canvas.getContext("2d");
draw();
}
}();
canvas {
display: block;
margin: auto;
border: solid 2px black;
border-radius: 10px;
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
In this drawing tool for html I want to replace the color (#ddd) with a photo.
Instead of the current version I want to replace the grey rectangle with a photo. Any idea on how to do that? And it won't let me reposition the rectangle, any idea why?
(function() {
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(container, width, height, fillColor) {
var canvas = createCanvas(container, width, height);
var ctx = canvas.context;
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
ctx.clearTo = function(fillColor) {
ctx.fillStyle = fillColor;
ctx.fillRect(0, 0, width, height);
};
ctx.clearTo(fillColor || "#ddd");
// bind mouse events
canvas.node.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var radius = 25; // or whatever
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
canvas.node.onmousedown = function(e) {
canvas.isDrawing = true;
};
canvas.node.onmouseup = function(e) {
canvas.isDrawing = false;
};
}
var container = document.getElementById('canvas');
init(container, 400, 400, '#ddd');
})();
You can achieve this by layering a solid canvas on top of another canvas. Erasing parts of the top canvas should reveal the canvas below.
The following reuses 99% of the code from two separate posts.
Loading the image onto the canvas.
Erasing the top canvas (layer).
// Borrowed from here: https://stackoverflow.com/a/4776378
var canvasWrapper = document.getElementsByClassName('layer-wrapper')[0];
var imageLayer = canvasWrapper.querySelector('.layer-image');
var drawLayer = canvasWrapper.querySelector('.layer-draw');
var img = new Image;
img.onload = function() {
imageLayer.width = drawLayer.width = img.width;
imageLayer.height = drawLayer.height = img.height;
var imageCtx = imageLayer.getContext('2d');
imageCtx.drawImage(img, 0, 0);
var drawCtx = drawLayer.getContext('2d');
drawCtx.fillStyle = '#7F7F7F';
drawCtx.fillRect(0, 0, img.width, img.height);
};
img.src = 'https://pbs.twimg.com/profile_images/462372073982025728/jTHaxsxd.jpeg';
// Borrowed from here: https://stackoverflow.com/a/25916334
var RADIUS = 32;
var canvas = canvasWrapper.querySelector('.layer-wrapper .layer-draw');
var ctx = canvas.getContext('2d');
var lastX;
var lastY;
var strokeColor = 'red';
var strokeWidth = 5;
var mouseX;
var mouseY;
var canvasOffset = $(canvas).offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var isMouseDown = false;
function handleMouseDown(e) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
// Put your mousedown stuff here
lastX = mouseX;
lastY = mouseY;
isMouseDown = true;
}
function handleMouseUp(e) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
// Put your mouseup stuff here
isMouseDown = false;
}
function handleMouseOut(e) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
// Put your mouseOut stuff here
isMouseDown = false;
}
function handleMouseMove(e) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
// Put your mousemove stuff here
if (isMouseDown) {
ctx.beginPath();
if (mode == "pen") {
ctx.globalCompositeOperation = "source-over";
ctx.moveTo(lastX, lastY);
ctx.lineTo(mouseX, mouseY);
ctx.stroke();
} else {
ctx.globalCompositeOperation = "destination-out";
ctx.arc(lastX, lastY, RADIUS, 0, Math.PI * 2, false);
ctx.fill();
}
lastX = mouseX;
lastY = mouseY;
}
}
$(canvas).mousedown(function(e) {
handleMouseDown(e);
}).mousemove(function(e) {
handleMouseMove(e);
}).mouseup(function(e) {
handleMouseUp(e);
}).mouseout(function(e) {
handleMouseOut(e);
});
var mode = 'eraser';
//$('#pen') .click(function() { mode = 'pen'; });
//$('#eraser').click(function() { mode = 'eraser'; });
.layer-wrapper {
position: relative;
width: 400px;
height: 300px;
}
.layer-wrapper canvas.layer {
position: absolute;
top: 0;
left: 0;
}
.layer-image {
z-index: 1;
}
.layer-draw {
z-index: 100;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="layer-wrapper">
<canvas class="layer layer-image"></canvas>
<canvas class="layer layer-draw"></canvas>
</div>
Hello everybody I've just trying to understands how this does it work
I have a basic canvas base just in javascript and I would like to move it using touch event
I'm not sure about this but Can I use the drag event ?
Do I need to use a loop function ?
How can I trigger that blue cube ?
I know there are lot of javascript engine in fact i'm using phaser but I would like to undertand this
Thank you
var canvas, cx, width, height;
var cube = {
x: 80,
y: 100,
update: function () {
},
draw: function (ctx) {
ctx.save();
ctx.fillStyle = "blue";
ctx.fillRect(100, 410, 50, 50);
ctx.restore();
}
};
function onpress(e) {
e.preventDefault();
var whichArt = e.target;
var touch = e.touches[0];
var moveOffsetX = whichArt.offsetLeft - touch.pageX;
var moveOffsetY = whichArt.offsetTop - touch.pageY;
whichArt.addEventListener('touchmove', function () {
var positionX = touch.pageX + moveOffsetX;
var positionY = touch.pageY + moveOffsetY;
cube.x = positionX;
cube.y = positionY;
console.log(cube.x);
}, false);
}
function main() {
canvas = document.createElement("canvas");
width = window.innerWidth;
height = window.innerHeight;
if (width >= 500) {
width = 320;
height = 480;
canvas.style.border = "1px solid #000";
}
document.addEventListener("touchstart", onpress);
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
run();
}
function run() {
var loop = function () {
update();
render();
window.requestAnimationFrame(loop, canvas);
}
window.requestAnimationFrame(loop, canvas);
}
function update() {
}
function render() {
cube.draw(ctx);
}
main();
http://jsfiddle.net/marcogomesr/sxbo3r83/
The canvas is only a passive drawing surface : You have to handle the drag by yourself.
Below a short example :
draggables object have to implement isPointInside, and to be added to the list of draggables object.
I used a dragData object that stores the list of draggables object, the currently dragged object, maybe you'll want to store the start/current point of the drag, and handle a drag-offset so the user holds the object right on the point where he/she started dragging.
http://jsfiddle.net/3ksvn4y0/3/
var canvas, cx, width, height;
var canvasRect;
var cube1, cube2;
var dragData = {
draggables: [],
start: { x: 0, y: 0
},
current: { x: 0, y: 0
},
target: null
};
function Cube(x,y,w,h, color) {
this.x=x; this.y=y; this.w=w; this.h = h;
this.color = color;
}
Cube.prototype = {
update: function () {
},
draw: function (ctx) {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.w, this.h);
},
isPointInside: function (x, y) {
return (x >= this.x) && (x < this.x + this.w) && (y > this.y) && (y < this.y + this.h);
}
};
var pointerCoords = {
x: 0,
y: 0,
update: function (e) {
var coords = e.touches ? e.touches[0] : e;
this.x = coords.pageX - canvasRect.left;
this.y = coords.pageY - canvasRect.top;
}
};
function onStart(e) {
e.preventDefault();
pointerCoords.update(e);
// look if we start the touch within a draggable object
var target = null;
for (var i = 0; i < dragData.draggables.length; i++) {
var draggable = dragData.draggables[i];
if (draggable.isPointInside(pointerCoords.x, pointerCoords.y)) {
target = draggable;
break;
}
}
dragData.target = target;
}
function onMove(e) {
pointerCoords.update(e);
var target = dragData.target;
if (!target) return;
target.x = pointerCoords.x;
target.y = pointerCoords.y;
}
function onStop(e) {
pointerCoords.update(e);
e.preventDefault();
if (!dragData.target) return;
onMove(e);
dragData.target = null;
}
function main() {
canvas = document.createElement("canvas");
width = window.innerWidth;
height = window.innerHeight;
if (width >= 500) {
width = 320;
height = 480;
canvas.style.border = "1px solid #000";
}
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
canvasRect = canvas.getBoundingClientRect();
canvas.addEventListener("touchstart", onStart);
canvas.addEventListener('touchmove', onMove);
canvas.addEventListener("touchstop", onStop);
canvas.addEventListener("mousedown", onStart);
canvas.addEventListener('mousemove', onMove);
canvas.addEventListener("mouseup", onStop);
cube1 = new Cube(100, 80, 30, 30, 'blue');
cube2 = new Cube(150, 160, 20, 20, 'red');
dragData.draggables.push(cube1, cube2);
run();
}
function run() {
var loop = function () {
requestAnimationFrame(loop);
update();
render();
}
loop();
}
function update() {
}
function render() {
ctx.clearRect(0, 0, width, height);
cube1.draw(ctx);
cube2.draw(ctx);
}
main();
I am trying to create a simple canvas program where the user can consistently create new shapes. This one is just a basic rectangle creator (I am hoping to expand it more to circles, lines, and maybe even other stuff). Right now though I have created something that is working in a really weird way.
<html>
<head>
<meta chartset="utf-8">
<title>Dragging a square</title>
<script type="text/javascript">
var canvas, context, startX, endX, startY, endY;
var mouseIsDown = 0;
function init() {
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
canvas.addEventListener("mousedown", mouseDown, false);
canvas.addEventListener("mousemove", mouseXY, false);
document.body.addEventListener("mouseup", mouseUp, false);
}
function mouseUp() {
mouseIsDown = 0;
//mouseXY();
}
function mouseDown() {
mouseIsDown = 1;
startX = event.clientX;
startY = event.clientY;
mouseXY();
}
function mouseXY(eve) {
if (!eve) {
var eve = event;
}
endX = event.pageX - canvas.offsetLeft;
endY = event.pageY - canvas.offsetTop;
drawSquare();
}
function drawSquare() {
// creating a square
var width = Math.abs(startX - endX);
var height = Math.abs(startY - endY);
context.beginPath();
context.rect(startX, startY, width, height);
context.fillStyle = "yellow";
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();
}
</script>
</head>
<body onload="init()">
<canvas id="canvas" width="400" height="400" style="border: 1px solid black; cursor: pointer;"></canvas>
</body>
</html>
Sorry about the slightly weird formatting when I copy and pasted my code. I think the problem is my mouseXY function. What I want is the user to click somewhere on the canvas a drag the mouse to create a rectangle, when the user lets go that is the end of that operation and they can create a whole new rectangle right after. At this point the program kind of just lets me click and create a new rectangle but if I let go of the mouse button it doesn't stop, in fact I have to click again to make it stop which then creates a new rectangle. I am still very new to this and I am having a lot of trouble with this, I will continue to work on this and if I figure it out I will let the site know. Thank you and have a great day!
Well I got this to work (thanks to #Ken) but now I am trying to solve a new problem. I want to be able to put multiple rectangles on the canvas. I created a function that represents the Rectangle and then created a draw function within the rectangle function to draw out a rectangle. I created a new function called addShape() that ideally creates the rectangle object and pushes into an array called square and drawShapes() that is supposed to erase everything on the canvas and redraws everything. Here is what I have so far:
<html>
<head>
<meta chartset="utf-8">
<title>Dragging a square</title>
<script type="text/javascript">
function Rectangle(canvas, x, y, width, height,color) {
//this.context = canvas.getContext("2d");
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
this.draw = function() {
this.context.globalAlpha = 0.85;
this.context.beginPath();
this.context.rect(this.x, this.y, this.width, this.height);
this.context.fillStyle = this.color;
this.context.strokeStyle = "black";
this.context.lineWidth = 1;
this.context.fill();
this.context.stroke();
};
};
// hold the canvas and context variable, as well as the
// starting point of X and Y and the end ones
var canvas, context, startX, endX, startY, endY;
var mouseIsDown = 0;
// An array that holds all the squares
var squares = [];
window.onload = function() {
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
canvas.addEventListener("mousedown", mouseDown, false);
canvas.addEventListener("mousemove", mouseXY, false);
canvas.addEventListener("mouseup", mouseUp, false);
}
function mouseUp(eve) {
if (mouseIsDown !== 0) {
mouseIsDown = 0;
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
//Square(); //update on mouse-up
addShape(); // Update on mouse-up
}
}
function mouseDown(eve) {
mouseIsDown = 1;
var pos = getMousePos(canvas, eve);
startX = endX = pos.x;
startY = endY = pos.y;
// Square(); //update
addShape();
}
function mouseXY(eve) {
if (mouseIsDown !== 0) {
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
//Square();
addShape();
}
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
function addShape() {
var w = endX - startX;
var h = endY - startY;
var offsetX = (w < 0) ? w : 0;
var offsetY = (h < 0) ? h : 0;
var width = Math.abs(w);
var height = Math.abs(h);
var s = new Rectangle(startX + offsetX, startY + offsetY, width, height, "yellow");
squares.push(s);
// Update the display
drawShapes();
}
function drawShapes() {
context.clearRect(0,0,canvas.width,canvas.height);
for (var i = 0; i < squares.length; i++) {
var shape = squares[i];
shape.draw();
};
}
function clearCanvas() {
squares = [];
drawShapes();
}
</script>
</head>
<body onload="addShape()">
<canvas id="canvas" width="400" height="400" style="border: 1px solid black; cursor: pointer;"></canvas><br>
<button onclick="clearCanvas()">Clear Canvas</button>
</body>
</html>
I am pretty sure I broke the original code... thank you for any help!
You need to modify a couple of things in the code: (edit: there are many issues with this code. I went through some of them inline here, but haven't tested. If you put it in a fiddle it's easier for us to check)..
Fiddle
When mouse down occur initialize both start and end points. Call a common draw function that is not dependent on the event itself:
function mouseDown(eve) {
mouseIsDown = 1;
var pos = getMousePos(canvas, eve);
startX = endX = pos.x;
startY = endY = pos.y;
drawSquare(); //update
}
At mouse up, only register if isMouseDown is true, else this function will handle all incoming up-events (as you have attatched it to document, which is correct - window could have been used too):
function mouseUp(eve) {
if (mouseIsDown !== 0) {
mouseIsDown = 0;
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
drawSquare(); //update on mouse-up
}
}
Only draw if mouseisdown is true:
function mouseXY(eve) {
if (mouseIsDown !== 0) {
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
drawSquare();
}
}
In addition you will need to clear the previous area of the rectangle before drawing a new or else it won't show when you draw a bigger rectangle and then move the mouse back to draw a smaller one.
For simplicity you can do:
function drawSquare() {
// creating a square
var width = Math.abs(startX - endX);
var height = Math.abs(startY - endY);
context.clearRect(0, 0, context.width, context.height);
//or use fillRect if you use a bg color
context.beginPath();
context.rect(startX, startY, width, height);
context.fillStyle = "yellow";
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();
}
Use this for mouse position:
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}