Can you please take a look at following demo and let me know how I can enable the code to draw 100% straight Line on the canvas?
$(function() {
var drawLine = false;
var theCanvas = document.getElementById('map');
var ctx = theCanvas.getContext('2d');
theCanvas.width = 420;
theCanvas.height = 300;
var canvasOffset = $('#map').offset();
$('#map').mousemove(function(e) {
if (drawLine === true) {
ctx.lineTo(e.pageX - canvasOffset.left, e.pageY - canvasOffset.top);
ctx.stroke();
}
});
$('#map').mousedown(function() {
drawLine = true;
ctx.strokeStyle = 'blue';
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.beginPath();
ctx.moveTo(e.pageX - canvasOffset.left, e.pageY - canvasOffset.top);
});
$(window).mouseup(function() {
drawLine = false;
});
});
#map{border:solid; margin-top: 50px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<canvas id="map"></canvas>
As you can see the code is working fine but what I want is drawing a straight line on drawing
Thanks
You would need to have 2 canvases:
temporary for animation
permanent to store drawing.
Algorithm:
ondown write start coordinates.
onmove record endpoint, clear canvas 1, draw a line on canvas 1 from start point to end point.
onup draw final line on 2nd canvas clear 1st canvas.
Too lazy create second canvas (it'll clear it every try now);
Put a comment where pass different canvas for permanent draw
$(function() {
var drawLine = false;
var theCanvas = document.getElementById('map');
var finalPos = {x:0, y:0};
var startPos = {x:0, y:0};
var ctx = theCanvas.getContext('2d');
theCanvas.width = 420;
theCanvas.height = 300;
var canvasOffset = $('#map').offset();
function line(cnvs) {
cnvs.beginPath();
cnvs.moveTo(startPos.x, startPos.y);
cnvs.lineTo(finalPos.x, finalPos.y);
cnvs.stroke();
}
function clearCanvas()
{
ctx.clearRect(0, 0, theCanvas.width, theCanvas.height);
}
$('#map').mousemove(function(e) {
if (drawLine === true) {
finalPos = {x: e.pageX - canvasOffset.left, y:e.pageY - canvasOffset.top};
clearCanvas();
line(ctx);
}
});
$('#map').mousedown(function(e) {
drawLine = true;
ctx.strokeStyle = 'blue';
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.beginPath();
startPos = { x: e.pageX - canvasOffset.left, y: e.pageY - canvasOffset.top};
});
$(window).mouseup(function() {
clearCanvas();
// Replace with var that is second canvas
line(ctx);
finalPos = {x:0, y:0};
startPos = {x:0, y:0};
drawLine = false;
});
});
#map{border:solid; margin-top: 50px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<canvas id="map"></canvas>
Related
I am trying to create a whiteboarding web app using HTML5 and Canvas.
I have implement a simple pen and paintbrush shaped pen with help from this brilliant article:
http://perfectionkills.com/exploring-canvas-drawing-techniques/
My issue is withe dotted line pen and highlighter pen.
The dotted line looks like a simple unbroken line if the mouse moves slowly, and with large gaps if moved quickly. What I want is a consistently spaced dotted line.
I tried setting the context.setLineDash but this has no effect on the result.
I then tried to calculate a minimum distance between the last point and current point and draw if over the dot gap lenth but this also does not seemeingly affect the result.
Here is my code:
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var lastPoint;
var isDrawing = false;
context.lineWidth = 4;
context.lineJoin = context.lineCap = 'round';
canvas.onmousedown = function(e) {
isDrawing = true;
lastPoint = {
x: e.clientX,
y: e.clientY
};
lastPoint = {
x: e.offsetX,
y: e.offsetY
};
};
canvas.onmousemove = function(e) {
if (!isDrawing) return;
context.beginPath();
context.strokeStyle = 'red';
context.fillStyle = 'red';
mx = e.clientX; // mouse pointer and stroke path is off if use this
my = e.clientY;
mx = e.offsetX; // mouse pointer and stroke path match using this
my = e.offsetY;
context.setLineDash([5, 25]);
xlen = Math.abs(mx - lastPoint.x) + context.lineWidth;
ylen = Math.abs(my - lastPoint.y) + context.lineWidth;
gap = Math.sqrt((ylen * ylen) + (xlen * xlen));
if (gap >= 5) {
context.moveTo(lastPoint.x, lastPoint.y);
context.lineTo(mx, my);
context.stroke();
lastPoint = {
x: mx,
y: my
};
}
};
canvas.onmouseup = function() {
isDrawing = false;
};
html,body,canvas
{
width: 100%;
height: 100%;
margin: 0;
}
<canvas id="canvas" ></canvas>
The result is this:
With the highlighter, I get overlapping points which give dark spots on the path. The code for this is:
context.globalAlpha = 0.3;
context.moveTo(lastPoint.x, lastPoint.y);
context.lineTo(mx, my);
context.stroke();
lastPoint = { x: mx, y: my };
The result:
Currently, I am making a game and in need of making the image rotate toward the cursor. I am using node but the image is in a js tag in the HTML file that uses ctx to draw the image.
If I put a ctx.rotate(angle); pretty much anywhere it will rotate everything; player, map, etc. I need help so that only the player is rotated
this is a simplified version of my code:
<canvas id="ctx" width="200" height="200"></canvas>
<script>
//game
var ctx = document.getElementById("ctx").getContext("2d");
var WIDTH = 200;
var HEIGHT = 200;
var Img = {};
//player
Img.player = new Image();
Img.player.src = '/client/img/player.png';
var Player = function(/*node*/){
ctx.drawImage(Img.player, ...);
}
//map
Img.map = new Image();
Img.map.src = '/client/img/map.png';
//display everything
setInterval(function(){
ctx.clearRect(0,0,200,200);
drawMap();
for(var i in Player.list)
Player.list[i].draw();
},1000/60);
//functions
//move map so that player is always in the middle
var drawMap= function(){
var x = WIDTH/2 - Player.list[/*node*/].x;
var y = HEIGHT/2 - Player.list[/*node*/].y;
ctx.drawImage(Img.map,x,y);
}
</script>
Here's an example of what you may be looking for
const ctx = document.getElementById("ctx").getContext("2d");
const WIDTH = 500,
HEIGHT = 500;
document.getElementById("ctx").height = HEIGHT;
document.getElementById("ctx").width = WIDTH;
var Player = {
x: 50,
y: 55,
angle: 0
}
document.addEventListener("mousemove", (event) => {
var x = event.clientX - Player.x,
y = event.clientY- Player.y,
angle = Math.atan2(y,x);
Player.angle = angle
})
function draw() {
window.requestAnimationFrame(draw);
ctx.clearRect(0, 0, WIDTH, HEIGHT);
ctx.save();
ctx.translate(Player.x, Player.y);
ctx.rotate(Player.angle);
ctx.translate(-Player.x, -Player.y);
ctx.fillRect(Player.x, Player.y, 20, 20);
ctx.restore();
ctx.fillRect(150, 50, 20, 20);
}
draw();
<canvas id="ctx"></canvas>
jsfiddle here
Hope this helps!
I have a canvas code to draw a signature. The code works perfectly fine with chrome and Firefox but does not draw at all on IE 11.
My canvas is:
<canvas id="signitureCanvas" style="border: 3px solid #000; cursor:crosshair; background-color:white;"></canvas>
My code is as below:
var canvas = document.getElementById('signitureCanvas');
var ctx = canvas.getContext('2d');
var canvasWidth = 200;
var canvasLength = 120;
canvas.width = canvasWidth;
canvas.height = canvasLength;
var canvasx = $(canvas).offset().left;
var canvasy = $(canvas).offset().top;
var last_mousex = last_mousey = 0;
var mousex = mousey = 0;
var mousedown = false;
var tooltype = 'draw';
//Mousedown
$(canvas).on('mousedown', function (e) {
last_mousex = mousex = parseInt(e.clientX - canvasx);
last_mousey = mousey = parseInt(e.clientY - canvasy);
mousedown = true;
});
//Mouseup
$(canvas).on('mouseup', function (e) {
mousedown = false;
});
//Mousemove
$(canvas).on('mousemove', function (e) {
mousex = parseInt(e.clientX - canvasx);
mousey = parseInt(e.clientY - canvasy);
if (mousedown) {
ctx.beginPath();
if (tooltype == 'draw') {
ctx.globalCompositeOperation = 'source-over';
ctx.strokeStyle = 'black';
ctx.lineWidth = 3;
} else {
ctx.globalCompositeOperation = 'destination-out';
ctx.lineWidth = 10;
}
ctx.moveTo(last_mousex, last_mousey);
ctx.lineTo(mousex, mousey);
ctx.lineJoin = ctx.lineCap = 'round';
ctx.stroke();
}
last_mousex = mousex;
last_mousey = mousey;
});
function ClearCanvas() {
var canvas = document.getElementById('signitureCanvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
Is IE 11 in particular having problems?
Edit:
I figured out the problem is with my Iframe:
When height and width are set to 300 everything works fine:
<embed id="fred" type="application/pdf" style="border:1px solid #666CCC" title="PDF in an i-Frame" src="#Model.FilePath" frameborder="1" scrolling="yes" height="300" width="300" />
When I set it to 1000, it won't work:
<embed id="fred" type="application/pdf" style="border:1px solid #666CCC" title="PDF in an i-Frame" src="#Model.FilePath" frameborder="1" scrolling="yes" height="1000" width="1000" />
I believe it's something with the offset but I can't figure how to fix it.
any help?
For further knowledge to whom might ask:
I have found this piece of code that works on all browsers, layerX and layerY are different for firefox browsers:
var canvas = document.getElementById('signitureCanvas');
var ctx = canvas.getContext('2d');
var canvasWidth = 200;
var canvasLength = 120;
canvas.width = canvasWidth;
canvas.height = canvasLength;
var x = 0;
var y = 0;
function tool_pencil() {
var tool = this;
this.started = false;
// This is called when you start holding down the mouse button
// This starts the pencil drawing
this.mousedown = function (ev) {
ctx.beginPath();
ctx.strokeStyle = 'black';
ctx.lineWidth = 3;
ctx.lineJoin = ctx.lineCap = 'round';
ctx.moveTo(x, y);
tool.started = true;
};
// This function is called every time you move the mouse. Obviously, it only
// draws if the tool.started state is set to true (when you are holding down
// the mouse button)
this.mousemove = function (ev) {
if (tool.started) {
ctx.lineTo(x, y);
ctx.stroke();
}
};
// This is called when you release the mouse button
this.mouseup = function (ev) {
if (tool.started) {
tool.mousemove(ev);
tool.started = false;
}
};
}
// The general-purpose event handler. This function just determines
// the mouse position relative to the <canvas> element
function ev_canvas(ev) {
// Firefox
if (ev.offsetX || ev.offsetX == 0) {
x = ev.offsetX;
y = ev.offsetY;
// Opera
} else if (ev.layerX || ev.layerX == 0) {
x = ev.layerX;
y = ev.layerX;
}
// Call the event handler of the tool
var func = tool[ev.type];
if (func) {
func(ev);
}
}
function ClearCanvas() {
var canvas = document.getElementById('signitureCanvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
I need help trying to rotate the rectangle that I have drawn on the canvas. I would like the top of the rectangle to pivot either to the right or left once I press on the arrow keys on my keyboard. This is my code so far:
HTML:
<body >
<div id="canvas-container">
<canvas id="canvas" width="500" height="400"></canvas>
</div>
</body>
CSS:
canvas {
display: inline;
}
Javascript:
document.addEventListener("DOMContentLoaded", function() {
drawBorder();
});
var canvas;
var context;
var size;
drawRectangle();
drawHalfCircle();
function drawBorder() {
canvas = document.getElementById("canvas");
context = canvas.getContext('2d');
size = {
x: canvas.width,
y: canvas.height
};
//have to set colors etc befor it is drawn
context.strokeStyle = 'black';
//takes 4 parameters
context.strokeRect(0, 0, size.x, size.y);
}
function drawRectangle() {
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
ctx.rect(246, 290, 8, 80);
ctx.stroke();
}
function drawHalfCircle(){
var c= document.getElementById("canvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.arc(250,579,308,1.2*Math.PI, 1.8*Math.PI);
ctx.stroke();
}
I have mocked something up is this along the correct lines of what you are wanting.
document.addEventListener("DOMContentLoaded", function() {
drawBorder();
});
var canvas = document.getElementById("canvas");
var context = canvas.getContext('2d');
var size;
var angle = 0;
setInterval(function () {
context.save();
context.clearRect(0, 0, canvas.width, canvas.height);
drawBorder();
drawHalfCircle();
drawRectangle();
context.restore();
}, 100);
function drawBorder() {
size = {
x: canvas.width,
y: canvas.height
};
//have to set colors etc befor it is drawn
context.strokeStyle = 'black';
//takes 4 parameters
context.strokeRect(0, 0, size.x, size.y);
}
function drawRectangle() {
context.rotate(Math.PI / 180 * (angle));
context.rect(246, 290, 8, 80);
context.stroke();
}
function drawHalfCircle(){
context.beginPath();
context.arc(250,579,308,1.2*Math.PI, 1.8*Math.PI);
context.stroke();
}
document.onkeydown = function(e) {
var event = window.event ? window.event : e;
if (e.keyCode == '37') {
angle += 5;
}
else if (e.keyCode == '39') {
angle -= 5;
}
}
Basically set an interval and redraw (ie frames like in a movie) and rotate via a variable.
See a demo here
https://jsbin.com/qititacazu/edit?js,output
If you want to translate it so it will rotate around a different point do something like this.
context.translate(246, 290);
context.rotate(Math.PI / 180 * (angle));
context.rect(-4, 0, 4, 80);
I have an HTML5 Canvas that can be drawn on with the mouse. I would like to be able to clear the canvas so the user can make a new drawing. I do this with:
myContext.clearRect(0, 0, 500, 700);
The canvas appears clear but as soon as the user begins a new drawing the old drawing reappears. My JavaScript for the mouse drawing part is:
// Variables
var x1;
var y1;
var isPressed = false;
var myCanvas;
var myContext;
function startCanvas() {
// Canvas stuff
myCanvas = document.getElementById("can1");
myContext = myCanvas.getContext("2d");
// Specify a black background, and white lines that are 3 pixels thick.
myContext.fillStyle = '#000000';
myContext.strokeStyle = '#000000';
myContext.fillRect(0, 0, 500, 700);
myContext.lineWidth = 3;
myContext.fill();
}
function functionMouseDown(e) {
// Get coordinates
x1 = e.clientX - myCanvas.offsetLeft;
y1 = e.clientY - myCanvas.offsetTop;
isPressed = true;
}
function functionMouseMove(e) {
// If mouse is down and moved start drawing line
if (isPressed == true) {
drawLine(e);
}
}
function functionMouseUp() {
// Stop drawing line
isPressed = false;
}
function drawLine(e) {
// Draw line
var x = e.clientX - myCanvas.offsetLeft;
var y = e.clientY - myCanvas.offsetTop;
myContext.strokeStyle = '#ffffff';
myContext.lineWidth = 1;
myContext.moveTo(x1, y1);
myContext.lineTo(x, y);
myContext.stroke();
// Set start coordinates to current coordinates
x1 = x;
y1 = y;
}
startCanvas();
The HTML is:
<canvas id="can1" width="500" height="700"></canvas>
myContext.strokeStyle = '#000000';
myContext.beginPath();//<---- add this and read about this.
myContext.fillRect(0, 0, 500, 700);
myContext.lineWidth = 3; //why?
myContext.fill();