Drawing on canvas in Bootstrap - javascript

So I have been having this problem with HTML5 canvas and Bootstrap. Esentially, I inserted a canvas inside a Bootstrap template (put it in an element with the class of "jumbotron"). And I want to be able to draw inside that canvas using my mouse. But, my mouse position and the editable-canvas area seem off. I took a snap-shot (hope I uploaded it correctly), the canvas is the pale-yellow thing with the purple border and the actual mouse position is the arrow I drew with blue, the blue dot is where the page sees the mouse position and begins drawing the line. Also, it won`t let me use the whole canvas area, I can only draw in the green square I outlined in the photo...
HTML code:
<div class="jumbotron">
<canvas id="draw" width="800" height="800"></canvas>
</div>
JS code to activate the drawing:
function draw(e) {
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
[lastX, lastY] = [e.offsetX, e.offsetY];
}
I also have to add that if I get the canvas into a new HTML (without Bootstrap), the code works perfectly (dot/line is following the mouse cursor fine). Also, if I delete the class "jumbotron", the mouse Position will be read correctly. I tried looking into the styles for "jumbotron", digged it up, tried using BoundingRect and others, but I could not figure this one out.
I am new here, so take me slow :) Many thanks in advance!

This happens because mouse position is relative to window. You must make some math to calculate coordinates relative to canvas. Some code for understanding
rect = canvas.getBoundingClientRect()
x = e.offsetX - rect.x
y = e.offsetY - rect.y
Then use x, y to draw something on canvas.
Also you can check my example where I draw with mouse without some additional calculations.
https://codepen.io/Profesor08/pen/aYJWRZ

Related

Javascript Canvas - Draw rectangle drag and drop

I want to be able to click and drag to draw a rectangle on a javascript canvas.
I need to be able to see the rectangle as I'm dragging to change size as I'm dragging like a "rubber band" as I've heard it been called. And then it creates on mouseup.
I'm having serious difficulties with this, any help is appreciated, thanks!
An algorithm to investigate would be to
Use animation frame callback to clear and write a new rectangle to the canvas. ( See requestAnimationFrame )
Use mousedown and mouseup events over the canvas to initiate tracking mouse movement. The mousedown event could start animation calls to draw a 1x1 pixel rectangle.
mousemove events record the position of the mouse for use by animation frame drawing code - and may call requestAnimationFrame if no callback is pending.
If you can clear the canvas of previous content to create the rubber band effect, the last drawn rectangle on mouseup is the result.
If existing content needs to be preserved, investigate making a copy of the canvas on mousedown, and copying it back to the canvas before drawing new rectangles. See questions like how to copy a canvas locally and/or how to (deep) clone a canvas
Happy coding, there's a lot to learn!
First of all, to draw rect on drag (or mouse move), you just clear the canvas, and draw a new rect. Second of all, canvas shapes are not object, so you can't interact with them as far as I know, if you want interactivity, consider using svg. Here is a sloppy implementation of drawing on dragging.
$("canvas").mousedown(function(event){
var ctx = this.getContext("2d");
ctx.clearRect(0,0,$(this).width(),$(this).height());
var initialX = event.clientX - this.getBoundingClientRect().left;
var initialY = event.clientY - this.getBoundingClientRect().top;
$(this).mousemove(function(evt) {
ctx.strokeRect(initialX, initialY, evt.clientX - event.clientX, evt.clientY - event.clientY);
});
});

Easeljs draw different kinds of arrows

This application is made with Easeljs, to work in HTML5 canvas.
I want to be able to draw different kinds of arrows on the board. I tried inserting arrows as images and then making them draggable and resizable, but that made these images pretty ugly.
To illustrate:
Field to draw on
Arrows to draw on the field
The functionality should be as follows:
Click on the button
Draw a line
At mouseup event: convert line into corresponding arrow
Arrow should be draggable and resizable
How would I get this result?
You can fairly easily draw arrows using the Graphics API. I spent about 20 mins making this demo:
http://jsfiddle.net/lannymcnie/ukjb1g2g/2/
http://jsfiddle.net/lannymcnie/ukjb1g2g/3/
Code:
var w = startX - endX;
var h = startY - endY;
var lineLength = Math.sqrt(w*w+h*h);
arrow.graphics.clear().setStrokeStyle(3).beginStroke("#000").moveTo(0,0);
// Logic to draw to the end. This is just a straight line
arrow.lineTo(lineLength-arrowHeadSize, 0);
arrow.graphics.beginFill("#000");
arrow.graphics.drawPolyStar(lineLength, 0, arrowHeadSize, 3);
// Rotate
arrow.rotation = Math.atan2(h, w) * 180/Math.PI;
Drawing it straight and rotating it is the easiest way to add effects to the line. The demo I posted draws a sort of sine-wave like one of your examples. There is some more magic in there to make it the right length, etc.

Drawing arrows on a chess board in Javascript

I am trying to make my own chess analysis board to use when teaching chess. I currently have the board, pieces that I can drag and drop, as well as a method for clearing the board and setting up different board positions. I can also click on squares to highlight them.
I want to be able to draw arrows from one square to another to show lines of attack and influence but have no idea how to accomplish this. My board is made up of <div> tags. A short example is below (pseudo-code and actual code for brevity).
// a couple of CSS styles to define the width, height, and color of the squares
CSS Style Class "dark square"
CSS Style Class "light square"
//my board is made up of <div> tags
<div id="board">
<div id="a1" class="lightsquare"></div>
<div id="a2" class="darksquare"></div>
<div id="a3" class="lightsquare"></div>
//second rank
<div id="b1" class="darksquare"></div>
<div id="b2" class="lightsquare"></div>
<div id="b3" class="darksquare"></div>
//third rank
<div id="c1" class="lightsquare"></div>
<div id="c2" class="darksquare"></div>
<div id="c3" class="lightsquare"></div>
</div>
I can place pieces on the board, move them around, take other pieces, clear the board, set up unique positions, and highlight individual squares just fine, but would also like to be able to have the user click, drag, and draw arrows live on the board while still being able to manipulate the pieces on the board.
I looked at using the tag but based on my reading and research, it doesn't seem like the <canvas> tag was designed to do what I am looking for.
Does anyone have any ideas on how to do this in JavaScript? I have not learned to use JQuery yet, and would prefer to avoid using JQuery as I don't want to have to download an extra file or necessarily be on the internet to use this program.
So after a month of tinkering I have finally found a solution. As much effort as I put into using < div > tags and images to solve this problem, I could never get the arrow to position itself correctly when rotated. I therefore went back to trying out the < canvas > tag and I did finally find a solution that works.
function drawArrow(fromx, fromy, tox, toy){
//variables to be used when creating the arrow
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var headlen = 10;
var angle = Math.atan2(toy-fromy,tox-fromx);
//starting path of the arrow from the start square to the end square and drawing the stroke
ctx.beginPath();
ctx.moveTo(fromx, fromy);
ctx.lineTo(tox, toy);
ctx.strokeStyle = "#cc0000";
ctx.lineWidth = 22;
ctx.stroke();
//starting a new path from the head of the arrow to one of the sides of the point
ctx.beginPath();
ctx.moveTo(tox, toy);
ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7));
//path from the side point of the arrow, to the other side point
ctx.lineTo(tox-headlen*Math.cos(angle+Math.PI/7),toy-headlen*Math.sin(angle+Math.PI/7));
//path from the side point back to the tip of the arrow, and then again to the opposite side point
ctx.lineTo(tox, toy);
ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7));
//draws the paths created above
ctx.strokeStyle = "#cc0000";
ctx.lineWidth = 22;
ctx.stroke();
ctx.fillStyle = "#cc0000";
ctx.fill();
}
This code will get its start and end coordinates based on the coordinates of the squares at the mouse down and mouse up events. It will then use those coordinates to determine how the arrow should be drawn with the proper rotation.
If your asking how to approach this (fun) problem, I would go about it like this.
Make your arrow with 2 pngs: 2 divs with background images (body
and point of the arrow) inside one container div.
Once you have the code to properly display the arrow, make sure
you know how to append it to the DOM using javascript.
Now try to make the arrow longer and shorter with javascript (by
changing the size of the div containing the body of the arrow)
Once you can do this, it's time for math. Use javascript to
calculate the coordinates of the DIV that is clicked first when
making an arrow, and the DIV that is clicked second. When you have
these coordinates, calculate (using Pythagoras) the length of the
arrow you need, and the amound of rotation you need (this is the
tricky part, but I have done it before so it can certainly be done
if you know some basic math). You are essentially creating triangles on the board.
With the coordinates, length and rotation, you can now place your
arrow on the playing board, adjust the length and the rotation, to
display it just the way you need it. And remember you can also turn the
arrow for say 350 degrees to get to -10 degrees.
This is by no means easy but a lot of fun if you like math, and considering chess, I guess you do.
By the way, this problem can certainly be solved with plain JS but using jQuery would make it easier en less work. You can also use jQuery offline by downloading the library.
To activate and disable pointerEvents I used this code.
//checks to see if the shift key was pressed
function disableImage(ev){
if(ev.shiftKey == 1){
var canvas = document.getElementById("arrowCanvas");
canvas.style.pointerEvents = "all";
}
}
function enableImage(){
var canvas = document.getElementById("arrowCanvas");
canvas.style.pointerEvents = "none";
}

Division / sub-canvas

I have few coordinates in an XML file. They are lines, circles and arcs. I am reading them in a data structure and then trying to plot them on a canvas. What i am trying to figure out is how to divide the canvas into sub canvases. e.g suppose my canvas is
<canvas id="myCanvas" width="800" height="600" role="img">
Your browser does not support the canvas element.
</canvas>
What I am trying to achieve is how to make an imaginary window of width and height of 200px starting from say x1=200px on canvas and y1=250. And draw the image I have only in that box.
I have managed to scale down the image based on the imaginary box but cannot get around the concept of how to draw only in that imaginary box. The points are randomly distributed.
There are other ways to achieve this but the one you'll probably find most useful in this context is to use translation and a clip mask:
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
/// for simplicity, save current settings
ctx.save();
/// move coordinate system to the upper left corner of isolated region
ctx.translate(offsetX, offsetY);
/// create a clipping mask by using a simple rectangle
ctx.beginPath();
ctx.rect(0, 0, width, height);
/// define the last path (rectangle) as clipping mask
ctx.clip();
/// ... draw other things into this region from offset 0...
ctx.restore(); /// done and back to full canvas
By moving the whole coordinate system to the upper left corner of your region you can use offsets relative to the new isolated area. By adding a clip mask anything drawn outside the region will be clipped.
You will need to do this for each region one by one.
Another way is to add an offset to all drawing points. For example:
ctx.lineTo(x + offsetX, y + offsetY);
where offsetX/Y is the upper left corner of the region.
However, it will get more complicated if you need clipping - not a huge issue with images as you can define the destination region but for lines and and other path operation you will need to clip yourself by using interpolation etc.
Here is a live demo demonstrating this:
Fiddle (updated link)
The demo sets up a canvas and context and then fills the whole with a red color.
Then if sets the clipping and mask and translate it.
We now have a "virtual canvas" and the other graphic is intact
We now fill the region with the same fill operation but with blue. Now we can see only this regions is filled even the size is outside the actual region
Then we remove the clip and draw a line as evidence that we are now back in full mode

Html5 canvas clickable ONLY on pre-existing line and add a Dot on click

I am having trouble finding a good method to limit my mouse to be only able to click on a pre existing line in canvas (stroke width of 3)
What I need to know
how to limit mouse so can only click on pre- existing line, add a dot on click
line is drawn with this function
function createLine(startX:Float, startY:Float, endX:Float, endY:Float)
{
surface.beginPath();
surface.moveTo(startX, startY);
surface.lineTo(endX, endY);
surface.closePath();
surface.strokeStyle = '#ffffff';
surface.lineWidth = 2;
surface.stroke();
}
I am working in haxe, but solution in JS is fine
Thanks in advance.
The only way is for you to keep track of what you have drawn and do the collision/mouse over detection on your own.
If you need your canvas to be highly interactive, you should probably be looking at SVG. http://raphaeljs.com/ is a great library for drawing which will use canvas or SVG, whichever is available.

Categories