How to draw Angle in between two lines in javascript - javascript

i have four divs that is p1,p2,p3,p4. it is draggable. at any point i click "draw" button iwant to draw angle sign like below
$(document).ready(function(){
var c=document.getElementById('canvas');
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(parseInt($("#p1").css("left"))-5,parseInt($("#p1").css("top"))-5)
ctx.lineTo(parseInt($("#p2").css("left"))-5,parseInt($("#p2").css("top"))-5)
ctx.lineTo(parseInt($("#p3").css("left"))-5,parseInt($("#p3").css("top"))-5)
ctx.lineTo(parseInt($("#p4").css("left"))-5,parseInt($("#p4").css("top"))-5)
ctx.lineTo(parseInt($("#p1").css("left"))-5,parseInt($("#p1").css("top"))-5)
ctx.fillStyle='#E6E0EC';
ctx.fill();
ctx.strokeStyle="#604A7B";
ctx.lineWidth="3"
ctx.stroke();
ctx.closePath();
$("#p1,#p2,#p3,#p4").draggable({
drag:function(){
ctx.clearRect(0,0,500,500);
ctx.beginPath();
ctx.moveTo(parseInt($("#p1").css("left"))-5,parseInt($("#p1").css("top"))-5)
ctx.lineTo(parseInt($("#p2").css("left"))-5,parseInt($("#p2").css("top"))-5)
ctx.lineTo(parseInt($("#p3").css("left"))-5,parseInt($("#p3").css("top"))-5)
ctx.lineTo(parseInt($("#p4").css("left"))-5,parseInt($("#p4").css("top"))-5)
ctx.lineTo(parseInt($("#p1").css("left"))-5,parseInt($("#p1").css("top"))-5)
ctx.fillStyle='#E6E0EC';
ctx.fill();
ctx.strokeStyle="#604A7B";
ctx.lineWidth="3"
ctx.stroke();
ctx.closePath();
}
});
How can i make this please provide simple solution.
the fiddle:http://jsfiddle.net/b954W/
i want to draw the arc inside the shape at any point.

Here's how to illustrate the angle between line segments
Demo: http://jsfiddle.net/m1erickson/XnL3B/
Step#1: Calculate the angles
You can calculate the angle between 2 lines connected at a vertex using Math.atan2:
// calculate the angles in radians using Math.atan2
var dx1=pt1.x-pt2.x;
var dy1=pt1.y-pt2.y;
var dx2=pt3.x-pt2.x;
var dy2=pt3.y-pt2.y;
var a1=Math.atan2(dy1,dx1);
var a2=Math.atan2(dy2,dx2);
Step#2: Draw the angle's wedge
You can draw the wedge illustrating the angle using context.arc:
// draw angleSymbol using context.arc
ctx.save();
ctx.beginPath();
ctx.moveTo(pt2.x,pt2.y);
ctx.arc(pt2.x,pt2.y,20,a1,a2);
ctx.closePath();
ctx.fillStyle="red";
ctx.globalAlpha=0.25;
ctx.fill();
ctx.restore();
Step#3: Draw the degree angle in text
And you can draw the text of the angle (converted to degrees) using context.fillText:
// draw the degree angle in text
var a=parseInt((a2-a1)*180/Math.PI+360)%360;
ctx.fillStyle="black";
ctx.fillText(a,pt2.x+15,pt2.y);

Related

HTML Canvas color specific area

How can I do if I want to change the color of the area on the top of the drawed line. Here is my example:
https://www.w3schools.com/code/tryit.asp?filename=GG3IR6IS9TZ1
Thanks
Make a shape with your values and fill her.
https://www.w3schools.com/code/tryit.asp?filename=GG3J6QC13SU5
// your graph
ctx.beginPath();
ctx.moveTo(0, 40);
ctx.lineTo(300, 60);
ctx.stroke();
// fillment
ctx.beginPath();
ctx.moveTo(0, 40); //y our dynamic values
ctx.lineTo(300, 60); // your dynamic values
ctx.lineTo(300, 300); // canvas bottom right end
ctx.lineTo(0, 300); // canvas bottom left end
ctx.closePath();
Pass this logic for a function for other graph use, keep your code dry.

Canvas special shape - animating

I'm finishing a project, but I have one more step to finish.
I want to visualize microphone input by a canvas.
Getting the data from the microphone isn't a problem.
But I want to visualize it in a special way. (see image)
I want to animate each element from the wave.
My problem isn't the animation.
My problem is to create those shapes in the CANVAS.
This is an example of one shape:
I can create a rounded corner shape with the canvas
const draw = () => {
fillRoundedRect(20, 20, 100, 100, 20);
ctx.fillStyle = "red";
ctx.fill();
};
const fillRoundedRect = (x, y, w, h, r) => {
ctx.beginPath();
ctx.moveTo(x+r, y);
ctx.lineTo(x+w-r, y);
ctx.quadraticCurveTo(x+w, y, x+w, y+r);
ctx.lineTo(x+w, y+h-r);
ctx.quadraticCurveTo(x+w, y+h, x+w-r, y+h);
ctx.lineTo(x+r, y+h);
ctx.quadraticCurveTo(x, y+h, x, y+h-r);
ctx.lineTo(x, y+r);
ctx.quadraticCurveTo(x, y, x+r, y);
ctx.fill();
};
Can someone help me with creating a shape like in the second image?
Thanks in advance guys!
Instead of trying to make a single shape with dependency on surrounding shapes and a high risk of headache math-wise, use instead two shapes which you merge using composition. My suggestion anyways.
Draw all the bars in full height using composition mode source-over (default)
Define a single shape on top using some sort of spline (I would suggest a cardinal spline).
Set composition mode to destination-out and render an enclosed shape using the spline as top "line".
Example
This should work in a loop (remember to clear canvas for each frame) but shows only the building stones needed here -
var ctx = c.getContext("2d");
var points = [];
var skippy = 0;
// render all bars
ctx.globalCompositeOperation = "source-over"; // not needed here, but in a loop yes!
// produce bars
ctx.beginPath(); // not needed here, but in a loop yes!
for(var x = 0; x < c.width; x += 30) {
ctx.rect(x, 0, 16, c.height)
// OKIDOKI, lets produce the spline using random points (y) as well
// but not for all, only every second for prettyness... modify to taste
if (skippy++ % 2 === 0) points.push(x, c.height * Math.random());
}
points.push(c.width, c.height * Math.random()); // one last
ctx.fillStyle = "rgb(198, 198, 198)";
ctx.fill();
// render spline
ctx.beginPath();
ctx.moveTo(0, c.height); // bottom left corner
curve(ctx, points); // spline
ctx.lineTo(c.width, c.height); // bottom right corner
ctx.closePath();
ctx.globalCompositeOperation = "destination-out";
ctx.fill();

Inner line not removed from circle in Canvas

Right now I am playing around with Canvas and its features, however I am experiencing a weird problem. I am currently trying to draw a circle inside of a Triangle made of several "lineTo's". My problem being when I just implement an arc; it draws the Circle but with a line from the center and out towards the right side (angle 0). If I enclose my arc in beginPath and closePath it draws it perfectly however the Triangle disappears (JSFiddle is provided). Why is this happening also am I doing something specifically wrong? I am new to Canvas and I want to learn, thank you in advance!
JSFIDDLE https://jsfiddle.net/720hg2aq/1/
// Draw Triangle
ctx.moveTo((width*0.4), (height*0.05));
ctx.lineTo((width*0.6), (height*0.05));
ctx.moveTo((width*0.6), (height*0.05));
ctx.lineTo((width*0.5), (height*0.15));
ctx.moveTo((width*0.5), (height*0.15));
ctx.lineTo((width*0.4), (height*0.05));
ctx.moveTo((width*0.5), (height*0.09));
// End of Triangle
// Begin Circle
ctx.beginPath();
ctx.arc((width*0.5), (height*0.09), 20, 0 , 2 * Math.PI);
ctx.closePath();
// End Circle
// Draw it out
ctx.strokeStyle = '#000';
ctx.stroke();
The beginPath() method begins a path, or resets the current path.
Once you begin a path, use moveTo(), lineTo(), quadricCurveTo(), bezierCurveTo(), arcTo(), or arc() to make the path, then storke() it.
So the code should be:
ctx.strokeStyle = "black";
// Draw Triangle
ctx.beginPath(); /// Let's start the work!
ctx.moveTo((width*0.4), (height*0.05));
ctx.lineTo((width*0.6), (height*0.05));
ctx.moveTo((width*0.6), (height*0.05));
ctx.lineTo((width*0.5), (height*0.15));
ctx.moveTo((width*0.5), (height*0.15));
ctx.lineTo((width*0.4), (height*0.05));
ctx.moveTo((width*0.5), (height*0.09));
ctx.stroke(); /// Brushing with your dye!!
// End of Triangle
// Begin Circle
ctx.beginPath(); /// Let's start the **NEW** work!
/// Don't let the previous path be connected with the current path!
ctx.arc((width*0.5), (height*0.09), 20, 0 , 2 * Math.PI);
ctx.closePath();
ctx.stroke(); /// Brushing with your dye!!
// End Circle

Rotate 'note' on the canvas to always touch the upper left corner

The final code that worked for me was:
<canvas id="bg-admin-canvas" width="500" height="500" style="margin:15px; background:#09F;"></canvas>
<script>
var postit = function(width,height,angle){
var canvas = document.getElementById("bg-admin-canvas");
var ctx = canvas.getContext("2d");
var radians = angle * Math.PI / 180;
var move = width*Math.sin(radians);
if(angle < 0 ){ ctx.translate(0,-move); }else{ ctx.translate(move,0); }
ctx.rotate(radians);
var gradient = ctx.createLinearGradient(0,height,width/2,height/2);
gradient.addColorStop(0.05,"rgba(0,0,0,0)");
gradient.addColorStop(0.5,"rgba(0,0,0,0.3)");
ctx.fillStyle = gradient;
ctx.fillRect(0,0,width,height);
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(width, 0);
ctx.lineTo(width,height);
ctx.lineTo(width-width*.8,height-height*.02);
ctx.quadraticCurveTo(0+width*.02,height-height*.02,0+width*.02,(height - height*.2));
ctx.closePath();
var gradient = ctx.createLinearGradient(0,height,width/2,height/2);
gradient.addColorStop(0,'#f7f8b9');
gradient.addColorStop(1,'#feffcf');
ctx.fillStyle = gradient;
ctx.fill();
ctx.beginPath();
ctx.moveTo(width-width*.8,height-height*.02);
ctx.quadraticCurveTo(0+width*.02,height-height*.02,0+width*.02,(height - height*.2));
ctx.quadraticCurveTo(width*.05,height-height*.05,width*.1,height-height*.1);
ctx.quadraticCurveTo(width*.1,height-height*.07,width-width*.8,height-height*.02);
ctx.closePath();
ctx.fillStyle = '#ffffff';
ctx.fill();
var gradient = ctx.createLinearGradient(0,height,width*.1,height-height*.1);
gradient.addColorStop(0,"rgba(222,222,163,0.8)");
gradient.addColorStop(1,'#feffcf');
ctx.fillStyle = gradient;
ctx.fill();
}
postit(300, 300, 10);
</script>
Hi,
I made a quick and dirty "post-it" note with html5's canvas and some js.
I want to be able to rotate them anyway I want so I tried to use the translate. The example below I have a translate of 0,250 just so you could see the whole thing.
Ideally, I know if my canvas was 300,300 then I would
ctx.translate(150,150);
ctx.rotate(-30);
ctx.translate(-150,-150);
Of course since I'm rotating a square it gets cut off.
How would I rotate the square and move it on the canvas so the whole thing is showing but at the very top left edge of the canvas?
I added an image with my thinking of just getting the height of a triangle and moving it that much, but when translated, it doesn't seem to work just right.
I'll paste my whole function so you can look at it, but if you have any ideas, I would appreciate it. This isn't important, just messing around today.
var postit = function(width,height,angle){
var canvas = jQuery("#bg-admin-canvas").get(0);
var ctx = canvas.getContext("2d");
/*var area = (width*width*Math.sin(angle))/2;
var h = (area*2) / width + 30;
ctx.translate(0,h);
*/
//ctx.translate(150,150);
ctx.translate(0,250);
ctx.rotate(angle*Math.PI / 180);
//ctx.translate(-150,-150);
var gradient = ctx.createLinearGradient(0,height,width/2,height/2);
gradient.addColorStop(0.05,"rgba(0,0,0,0)");
gradient.addColorStop(0.5,"rgba(0,0,0,0.3)");
ctx.fillStyle = gradient;
ctx.fillRect(0,0,width,height);
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(width, 0);
ctx.lineTo(width,height);
ctx.lineTo(width-width*.8,height-height*.02);
ctx.quadraticCurveTo(0+width*.02,height-height*.02,0+width*.02,(height - height*.2));
ctx.closePath();
var gradient = ctx.createLinearGradient(0,height,width/2,height/2);
gradient.addColorStop(0,'#f7f8b9');
gradient.addColorStop(1,'#feffcf');
ctx.fillStyle = gradient;
ctx.fill();
ctx.beginPath();
ctx.moveTo(width-width*.8,height-height*.02);
ctx.quadraticCurveTo(0+width*.02,height-height*.02,0+width*.02,(height - height*.2));
ctx.quadraticCurveTo(width*.05,height-height*.05,width*.1,height-height*.1);
ctx.quadraticCurveTo(width*.1,height-height*.07,width-width*.8,height-height*.02);
ctx.closePath();
ctx.fillStyle = '#ffffff';
ctx.fill();
var gradient = ctx.createLinearGradient(0,height,width*.1,height-height*.1);
gradient.addColorStop(0,"rgba(222,222,163,0.8)");
gradient.addColorStop(1,'#feffcf');
ctx.fillStyle = gradient;
ctx.fill();
}
postit(300, 300, -35);
MORE INFO
Phrog, I think you know what I'm trying to do. This image shows what I want to do:
Now, the only thing is, I want to be able to pass in any width and height and angle and make the adjustment on the fly.
As an example with the following code:
var canvas = document.getElementById("bg-admin-canvas");
var ctx = canvas.getContext("2d");
ctx.arc(0,0,3,0,360,true); ctx.fill();
ctx.translate(50, 50);
ctx.arc(0,0,3,0,360,true); ctx.fill();
ctx.translate(-25, -25);
ctx.arc(0,0,3,0,360,true); ctx.fill();
I get the following image:
Now, if I add a rotate in there like this:
var canvas = document.getElementById("bg-admin-canvas");
var ctx = canvas.getContext("2d");
ctx.arc(0,0,3,0,360,true); ctx.fill();
ctx.translate(50, 50);
ctx.arc(0,0,3,0,360,true); ctx.fill();
ctx.rotate(30*Math.PI/180);
ctx.translate(-25, -25);
ctx.arc(0,0,3,0,360,true); ctx.fill();
I now have a sloped coordinates as the result is:
As I found, this is because the coordinates are no longer horizontal and vertical.
So, with this rotated coordinate structure, I can't figure out how to move my square (which could be any size and rotated at any angle) back to the left and top (so it fits in as little space as possible)
Does that make sense?
In short:
Translate the context in the Y direction only to put the corner where it should be.
Rotate the context around this offset point.
Draw your object at 0,0.
Here is an interactive, working example, which you can see online here:
http://phrogz.net/tmp/canvas_rotate_square_in_corner.html
<!DOCTYPE HTML>
<html lang="en"><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>HTML5 Canvas Rotate Square in Corner</title>
<style type="text/css" media="screen">
body { background:#eee; margin:2em; text-align:center }
canvas { display:block; margin:auto; background:#fff; border:1px solid #ccc }
</style>
</head><body>
<canvas width="250" height="200"></canvas>
<script type="text/javascript" charset="utf-8">
var can = document.getElementsByTagName('canvas')[0];
var ctx = can.getContext('2d');
ctx.strokeStyle = '#600'; ctx.lineWidth = 2; ctx.lineJoin = 'round';
ctx.fillStyle = '#ff0'
document.body.onmousemove = function(evt){
var w=140, h=120;
var angle = evt ? (evt.pageX - can.offsetLeft)/100 : 0;
angle = Math.max(Math.min(Math.PI/2,angle),0);
ctx.clearRect(0,0,can.width,can.height); ctx.beginPath();
ctx.save();
ctx.translate(1,w*Math.sin(angle)+1);
ctx.rotate(-angle);
ctx.fillRect(0,0,w,h);
ctx.strokeRect(0,0,w,h);
ctx.restore();
};
document.body.onmousemove();
</script>
</body></html>
Analysis
In the above diagram, point A is the upper-left corner of our post-it note and point B is the upper-right corner. We have rotated the post-it note -a radians from the normal angle (clockwise rotations are positive, counter-clockwise are negative).
We can see that the point A stays on the y axis as the post-it rotates, so we only need to calculate how far down the y axis to move it. This distance is expressed in the diagram as BD. From trigonometry we know that
sin(a) = BD / AB
Rearranging this formula gives us
BD = AB * sin(a)
We know that AB is the width of our post-it note. A few details:
Because our angle will be expressed as a negative number, and the sin of a negative number yields a negative result, but because we want a positive result, we must either negate the result
BD = -AB * sin(-a)
or just 'cheat' and use a positive angle:
BD = AB * sin(a)
We need to remember to translate our context before we rotate it, so that we first move directly down the axis to establish our origin at the right spot.
Remember that rotations in HTML5 Canvas use radians (not degrees). If you want to rotate by 20 degrees, you need to convert that to radians by multiplying by Math.PI/180:
ctx.rotate( 20*Math.PI/180 );
This also applies to the arc command; you should be doing ctx.arc(x,y,r,0,Math.PI*2,false); for a full circle.
You should create you canvas element and then rotate it using CSS. It would keep your canvas intact and only rotate the element itself.
Here is some example css rules:
-webkit-transform: rotate(-30deg);
-moz-transform: rotate(-30deg);
Refer to http://snook.ca/archives/html_and_css/css-text-rotation

rotating an arrow in canvas

I want to rotate the arrow to any given angle. What i need to add/modify so that it can be rotated to any angle. Currently its on 180 degree.
function drawArrowAtAngle(cx,cy,angle,context){
context.save();
context.beginPath();
context.lineWidth = 1;
context.strokeStyle = '#aaa';
context.moveTo(cx+25,cx-2);
context.lineTo(cx-55,cx-2);
context.lineTo(cx-58,cx);
context.lineTo(cx-55,cx+2);
context.lineTo(cx+25,cx+2);
context.lineTo(cx+25,cx-2);
context.stroke();
context.closePath();
context.restore();
}
Assuming that you want the center of rotation to be (cx,cx), insert the following three lines after the context.save(); statement.
context.translate(cx,cx) ;
context.rotate(angle) ;
context.translate(-cx,-cx) ;
This will cause the arrow to be rotated clockwise by angle (in radians).
You use (cx,cx) in your code to anchor the arrow. If you really mean (cx,cy), then adjust the above snippet accordingly.

Categories

Resources