Error drawing arrow in canvas - javascript

I write code but it's not run.
I have 2 tag canvas. When i change properties height of canvas < 100 then arrow hidden. And if i didn't write tag div before tag canvas its run normal. Thank you for support!!!!
Source code:
<body>
<div id="yendau">LOL</div>
<canvas id="c" width="500" height="100">Brower of you doesn't not support Canvas</canvas>
<div>Yolooooooooooo</div>
<canvas id="d" width="500" height="300">Brower of you doesn't not support Canvas</canvas>
<script src="jquery-1.9.1.js"></script>
<script langauage="javascript">
function canvas_arrow(context, fromx, fromy, tox, toy){
var headlen = 20; // length of head in pixels
var dx = tox-fromx;
var dy = toy-fromy;
var angle = Math.atan2(dy,dx);
context.moveTo(fromx, fromy);
context.lineTo(tox, toy);
context.lineWidth=2;
context.moveTo(tox, toy);
context.lineTo(tox-headlen*Math.cos(angle+Math.PI/6),toy-headlen*Math.sin(angle+Math.PI/6));
context.moveTo(tox, toy);
context.lineTo(tox-headlen*Math.cos(angle-Math.PI/6),toy-headlen*Math.sin(angle-Math.PI/6));
}
$('document').ready(function(){
var count= parseInt($("canvas").length);
for(var i=0; i< count; i++){
var ctx= $("canvas")[i].getContext('2d');
ctx.beginPath();
//var x= $('#c').offset().left-15;
//var y= $('#c').offset().top-15;
var x= $('#'+$("canvas")[i].id).offset().left;
var y= $('#'+$("canvas")[i].id).offset().top+15;
var x1= x+100;
canvas_arrow(ctx,x,y,x1,y);
ctx.stroke();
}
});

You don't need to add the offset of the canvas when calculating x,y. In your case, doing that will quickly push your arrow off the canvas.
The canvas offset is useful when calculating the mouse position, but not useful when drawing on the canvas itself. That's because the mouse coordinates are always relative to the top-left of the page--not the top left of the canvas.
The top-left corner of the canvas is x=0, y=0. So just set x,y to your desired coordinates bases on:
x increases from zero as you move rightward across the canvas.
y increased from zero as you move downward across the canvas.

Related

Canvas place image in shape [duplicate]

This question already has an answer here:
How to fillstyle with Images in canvas html5
(1 answer)
Closed 7 years ago.
I'm trying to create a spinning wheel of sorts, where an image is displayed as a prize. I'm reusing a project I found online, and I'm pretty new to canvas, so I would appreciate some help.
This is how it looks, here an image would be displayed in each of the fields, with as angle to match the wheel. Here is the code generating it:
var outsideRadius = 210;
var textRadius = 160;
var insideRadius = 155;
ctx = canvas.getContext("2d");
ctx.clearRect(0,0,500,500);
ctx.strokeStyle = "#943127";
ctx.lineWidth = 4;
for(var i = 0; i < 12; i++) {
var angle = startAngle + i * arc;
ctx.fillStyle = '#a9382d';
ctx.beginPath();
ctx.arc(250, 250, outsideRadius, angle, angle + arc, false);
ctx.arc(250, 250, insideRadius, angle + arc, angle, true);
ctx.closePath();
ctx.stroke();
ctx.fill();
}
In each of the fields above should be displayed a image of a prize from an array. Im having problems drawing the images in the fields. I've tried using createPattern() without luck.
EDIT: Added jsfiddle: http://jsfiddle.net/46k72m7z/
To clip an image inside one of your wheel-wedges:
See illustration below.
Calculate the 4 vertices of your specified wedge.
Begin a new Path with context.beginPath and move to point0.
Draw a line from point0 to point1.
Draw an arc from point1 to point2.
Draw a line from point2 to point3.
Draw an arc from point3 back to point0.
Close the path (not needed, just being extra careful).
Call context.clip() to create a clipping area of your wedge.
Drawing the image at the appropriate angle
See illustration below.
Find the centerpoint of the wedge.
Set the canvas origin to that centerpoint with context.translate.
Calculate the angle from the wheel center (point#1 below) to the wedge center.
Rotate the canvas by the calculated angle.
Draw the image offset by half the image's width & height. This causes the image to be visually centered inside the wedge.
Other useful information
When you set a clip with context.clip the only way to undo that clip is to wrap the clip between context.save and context.restore. (Or resize the canvas, but that's counter-productive when you're trying to draw multiple clipped regions because all content is erased when the canvas is resized).
// save the begininning unclipped context state
context.save();
... draw your path
// create the clipping area
context.clip();
... draw the image inside the clipping area
// restore the context to its unclipped state
context.restore();
To center an image anywhere, find the center point where you want the image centered and then draw the image offset by half it's width & height:
ctx.drawImage( img,-img.width/2, -img.height/2 );
Calculating points on the circumference of a circle:
// given...
var centerX=150; // the circle's center
var centerY=150;
var radius=25; // the circle's radius
var angle=PI/2; // the desired angle on the circle (angles are expressed in radians)
var x = centerX + radius * Math.cos(angle);
var y = centerY + radius * Math.sin(angle);
An efficiency: The path command will automatically draw a line from the previous command's endpoint to your new command's startpoint. Therefore, you can skip step#3 & step#5 because the lines will be drawn automatically when you draw the arcs.
Example code and a Demo:
var canvas=document.getElementById("canvas");
var ctx=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(); }
var PI=Math.PI;
var cx=250;
var cy=250;
var outsideRadius = 210;
var textRadius = 160;
var insideRadius = 155;
var wedgecount=12;
var arc=Math.PI*2/wedgecount;
var startAngle=-arc/2-PI/2;
var mm=new Image;
mm.onload=start;
mm.src='https://dl.dropboxusercontent.com/u/139992952/multple/mm1.jpg';
var goldCar=new Image();
goldCar.onload=start;
goldCar.src='https://dl.dropboxusercontent.com/u/139992952/multple/carGold.png';
var redCar=new Image();
redCar.onload=start;
redCar.src='https://dl.dropboxusercontent.com/u/139992952/multple/cars1.png';
var imgCount=2;
function start(){
if(++imgCount<2){return;}
drawWheel();
for(var i=0;i<wedgecount;i++){
var img=(i%2==0)?goldCar:redCar;
if(i==3){img=mm;}
clipImageToWedge(i,img);
}
}
function drawWheel(){
ctx.clearRect(0,0,500,500);
ctx.lineWidth = 4;
for(var i = 0; i < 12; i++) {
var angle = startAngle + i * arc;
ctx.fillStyle = '#a9382d';
ctx.beginPath();
ctx.arc(cx,cy, outsideRadius, angle, angle + arc, false);
ctx.arc(cx,cy, insideRadius, angle + arc, angle, true);
ctx.closePath();
ctx.stroke();
ctx.fill();
}
}
function clipImageToWedge(index,img){
var angle = startAngle+arc*index;
var angle1= startAngle+arc*(index+1);
var x0=cx+insideRadius*Math.cos(angle);
var y0=cy+insideRadius*Math.sin(angle);
var x1=cx+outsideRadius*Math.cos(angle);
var y1=cy+outsideRadius*Math.sin(angle);
var x3=cx+outsideRadius*Math.cos(angle1);
var y3=cy+outsideRadius*Math.sin(angle1);
ctx.save();
ctx.beginPath();
ctx.moveTo(x0,y0);
ctx.lineTo(x1,y1);
ctx.arc(cx,cy,outsideRadius,angle,angle1);
ctx.arc(cx,cy,insideRadius,angle1,angle,true);
ctx.clip();
var midRadius=(insideRadius+outsideRadius)/2;
var midAngle=(angle+angle1)/2;
var midX=cx+midRadius*Math.cos(midAngle);
var midY=cy+midRadius*Math.sin(midAngle);
ctx.translate(midX,midY);
ctx.rotate(midAngle+PI/2);
ctx.drawImage(img,-img.width/2,-img.height/2);
ctx.restore();
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=500 height=500></canvas>

How to draw text through line and How to highlight the text on mouse enter using Html Canvas. Please help me

I can draw a line as per direction but I am not being able to draw a text as per line direction. My paint will be like this...
You need to figure out how wide the text will be and that can be solved with:
ctx.measureText(text).width;
Then just create a funtion that draws lines on either side of it (and a arrow head). Finish everything off with rotating the whole canvas before drawing it, like so:
Original answer: http://jsfiddle.net/txrvLLjp
EDIT
New code allows for adding starting and stopping points instead.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var text = "Knows";
var TO_RADIANS = Math.PI / 180;
ctx.font = "12px Arial";
drawArrow(text,40,40,200,200);
function drawArrow(text,startX,startY,stopX,stopY) {
var deltaX = (stopX-startX);
var deltaY = (stopY-startY)
//calculating the total length of the line
var arrowLength=Math.sqrt(deltaX*deltaX+deltaY*deltaY);
//calculating the angle
var angle=Math.atan2(deltaY,deltaX) * 180 / Math.PI;
ctx.save();
ctx.translate(startX,startY);
ctx.rotate(angle*TO_RADIANS);
var textLength = ctx.measureText(text).width;
var padding=(arrowLength-textLength)/2;
ctx.moveTo(0,0);
ctx.lineTo(padding,0);
ctx.stroke();
ctx.fillText(text,padding,4);
ctx.moveTo(padding+textLength,0);
ctx.lineTo(padding+textLength+padding,0);
ctx.stroke();
//Arrow point below
ctx.moveTo(padding+textLength+padding,0);
ctx.lineTo(padding+textLength+padding-8,8);
ctx.stroke();
ctx.moveTo(padding+textLength+padding,0);
ctx.lineTo(padding+textLength+padding-8,-8);
ctx.stroke();
ctx.restore();
}
<canvas id="myCanvas" width="200" height="400"></canvas>

Canvas - Restrict line in a circle boundary

How can I restrict a line in a circle boundary?
I want my drawed line to be cut off when it exceeds the max length (100px) but the line keeps restricting inside a rectangle.
I think I'm missing something obvious but I can't figure it out.
var midX = canvas.width/2,
midY = canvas.height/2,
x = (mouseCurrent.x - midX),
y = (mouseCurrent.y - midY),
maxX = midX+clamp(x,-MAX_LENGTH,MAX_LENGTH),
maxY = midY+clamp(y,-MAX_LENGTH,MAX_LENGTH);
ctx.moveTo(midX, midY);
ctx.lineTo(maxX, maxY);
I've created a fiddle to show my problem:
fiddle
Your clamp function, when you pass it -MAX_LENGTH and MAX_LENGTH as the min and max boundaries, doesn't take into account anything related to the angle the line is at.
For example, in your picture, the y value would be clamped to -MAX_LENGTH, which obviously, from the middle, will extend to the bottom-most point of the circle, and the x value will be clamped to MAX_LENGTH, extending as far as the right-most point of the circle.
What you should do is calculate the angle made from the mouse position, and use the sine and cosine of that angle to determine the coordinates.
You'll want something like this:
var x = (mouseCurrent.x - midX),
y = (mouseCurrent.y - midY);
var angleInRadians = Math.atan2(x - midX, y - midY);
var realX = Math.cos(angleInRadians);
var realY = Math.sin(angleInRadians);
Then, from the realX and realY values, you should be able to create your line. You might have to tweak this a little bit. I tried to adjust based on the fact that the origin isn't at (0, 0).
Here's one way:
Get the angle from the mouse to the circle centerpoint.
Use trigonometry to get the point at radius distance at the calculated angle.
draw a line from the centerpoint to the calculated point on the circumference.
Example code and a Demo: http://jsfiddle.net/m1erickson/Zje8Y/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var isDown=false;
var startX;
var startY;
draw(100,100);
function draw(x,y){
var cx=150;
var cy=150;
var r=50;
var dx=x-cx;
var dy=y-cy;
var angle=Math.atan2(dy,dx);
var xx=cx+r*Math.cos(angle);
var yy=cy+r*Math.sin(angle);
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
ctx.arc(cx,cy,r,0,Math.PI*2);
ctx.closePath();
ctx.stroke()
ctx.beginPath();
ctx.arc(x,y,5,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.moveTo(cx,cy);
ctx.lineTo(xx,yy);
ctx.stroke();
ctx.beginPath();
ctx.arc(xx,yy,5,0,Math.PI*2);
ctx.closePath();
ctx.fill();
}
function handleMouseMove(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
draw(mouseX,mouseY);
}
$("#canvas").mousemove(function(e){handleMouseMove(e);});
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
You can use basic trigonometry to calculate the angle and you can find the point intersecting with both the line and the circle.
First use tangent of the line to calculate angle. Then use angle value to find x and y coordinates of the point that you are looking for. Here is the code:
angle = Math.atan2(mouseCurrent.y - midY, mouseCurrent.x - midX);
maxY = midY + Math.sin(angle) * MAX_LENGTH;
maxX = midX + Math.cos(angle) * MAX_LENGTH;

what I did wrong with my accelerometer and canvas 2d? android

I'm trying to create a 2d canvas with the accelerometer API.
The API full example works when I tilt the phone the acceleration.x and acceleration.y changes.
So I made a canvas 2d circle and implemented the acceleration.x and acceleration.y but when I did that, the circle is gone.
This is my html
<canvas id="myCanvas" width="200" height="200" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
This is my partial script
function movingCircle (acceleration) {
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var x = acceleration.x;
var y = acceleration.y;
ctx.fillStyle = "rgba(255, 255, 0, .5)";
ctx.beginPath();
ctx.arc(x,y,20,0,2*Math.PI, true);
ctx.stroke();
ctx.closePath();
ctx.fill();
c.innerHTML = 'testing';
}
ctx.arc(x,y,20,0,2*Math.PI, true); if I change the x and y into 47.5, 25 then I can see my circle clearly positioned near the top left corner.
Anyone can give me a hand what I did wrong here?
Acceleration's x & y keys are not absolute cordinates on which you can plot your circle. Acceleration is difference in velocity over time. So rather you them as quantities to add to your current circle position.
Something like: x = x + acceleration.x;

How do I rotate a single object on an html 5 canvas?

I'm trying to figure out how to rotate a single object on an html 5 canvas.
For example: http://screencast.com/t/NTQ5M2E3Mzct - I want each one of those cards to be rotated at a different degree.
So far, all I've seen are articles and examples that demonstrate ways to rotate the entire canvas. Right now, I'm guessing I'll have to rotate the canvas, draw an image, and then rotate the canvas back to it's original position before drawing the second image. If that's the case, then just let me know! I just have a feeling that there's another way.
Anyone have any idea?
I ran into the same problem in a recent project (where I kicked rotating aliens all over the place). I just used this humble function that does the same thing and can be used the same way as ctx.rotate but can be passed an angle. Works fine for me.
function drawImageRot(img,x,y,width,height,deg){
// Store the current context state (i.e. rotation, translation etc..)
ctx.save()
//Convert degrees to radian
var rad = deg * Math.PI / 180;
//Set the origin to the center of the image
ctx.translate(x + width / 2, y + height / 2);
//Rotate the canvas around the origin
ctx.rotate(rad);
//draw the image
ctx.drawImage(img,width / 2 * (-1),height / 2 * (-1),width,height);
// Restore canvas state as saved from above
ctx.restore();
}
Yay, my first answer!
Unfortunately in the HTML5 canvas element you can't rotate individual elements.
Animation works like drawing in MS Paint: You draw something, make a screen.. use the eraser to remove some stuff, draw something differently, make a screen.. Draw something else on top, make a screen.. etc etc.
If you have an existing item on the canvas - you'll have to erase it ( use ctx.fillRect() or clearRect() for example ), and then draw the rotated object.
If you're not sure how to rotate it while drawing in the first place:
ctx.save();
ctx.rotate(0.17);
// draw your object
ctx.restore();
To rotate a individual object you have to set the transformation matrix. This is really simple:
var context = document.getElementById('pageCanvas').getContext('2d');
var angle = 0;
function convertToRadians(degree) {
return degree*(Math.PI/180);
}
function incrementAngle() {
angle++;
if(angle > 360) {
angle = 0;
}
}
function drawRandomlyColoredRectangle() {
// clear the drawing surface
context.clearRect(0,0,1280,720);
// you can also stroke a rect, the operations need to happen in order
incrementAngle();
context.save();
context.lineWidth = 10;
context.translate(200,200);
context.rotate(convertToRadians(angle));
// set the fill style
context.fillStyle = '#'+Math.floor(Math.random()*16777215).toString(16);
context.fillRect(-25,-25,50,50);
context.strokeRect(-25,-25,50,50);
context.restore();
}
// Ideally use getAnimationFrame but for simplicity:
setInterval(drawRandomlyColoredRectangle, 20);
<canvas width="1280" height="720" id="pageCanvas">
You do not have a canvas enabled browser
</canvas>
Basically, to make an object rotate properly without having other shape rotating around, you need to:
save the context: ctx.save()
move the pivot point to the desired location: ctx.translate(200, 200);
rotate: context.rotate(45 * Math.PI / 180);
draw the shape, sprite, whatever: ctx.draw...
reset the pivot: ctx.translate(-200, -200);
restore the context to its original state: ctx.restore();
function spinDrawing() {
ctx.save();
ctx.translate(200, 200);
context.rotate(45 * Math.PI / 180);
ctx.draw //your drawing function
ctx.translate(-200, -200);
ctx.restore();
}
Caveats: After you translating , the origin of the canvas changed, which means when you drawing the shape, the coordinate of the shape should be aligned accordingly.
Shapes drawn outside the list mentioned above won´t be affected. I hope it helps.
This html/javascript code might shed some light on the matter:
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="233" height="233" style="border:1px solid #d3d3d3;">
your browser does not support the canvas tag </canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var canvasWidth=233;
var canvasHeight=233;
var rectWidth=100;
var rectHeight=150;
var x=30;
var y=30;
var translateX= x+(rectWidth/2);
var translateY= y+(rectHeight/2);
ctx.fillRect(x,y,rectWidth,rectHeight);
ctx.translate(translateX,translateY);
ctx.rotate(5*Math.PI/64); /* just a random rotate number */
ctx.translate(-translateX,-translateY);
ctx.fillRect(x,y,rectWidth,rectHeight);
</script>
</body>
</html>
I find it helpful to see the math related to rotating, I hope this was helpful to you too.
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="500" height="450" style="border:1px solid #d3d3d3;">
</canvas>
<Button id = "right" onclick = "rotateRight()">Right</option>
<Button id = "left" onclick = "rotateLeft()">Left</option>
<script src = "zoom.js">
</script>
<script>
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
createRect();
function rotateRight()
{
ctx.save();
ctx.clearRect(0,0,500,450);
ctx.translate(c.width/2,c.height/2);
ctx.rotate(10*Math.PI/180 );
ctx.translate(-c.width/2,-c.height/2);
createRect();
}
function rotateLeft()
{
ctx.save();
ctx.clearRect(0,0,500,450);
ctx.translate(c.width/2,c.height/2);
ctx.rotate(-10*Math.PI/180 );
ctx.translate(-c.width/2,-c.height/2);
createRect();
}
function createRect()
{
ctx.beginPath();
ctx.fillStyle = "#AAAA00";
ctx.fillRect(250,250,90,50);
}
</script>
</body>
</html>
To rotate an object you can use rotate() method. Here the example how to rotate a rectangular object to 135 degrees of clockwise.
<script>
var canvas = document.getElementById('Canvas01');
var ctx = canvas.getContext('2d');
var rectWidth = 100;
var rectHeight = 50;
//create line
ctx.strokeStyle= '#ccc';
ctx.beginPath();
ctx.moveTo(canvas.width / 2, 0);
ctx.lineTo(canvas.width / 2, canvas.height);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.moveTo(0, canvas.height/2);
ctx.lineTo(canvas.width, canvas.height/2);
ctx.stroke();
ctx.closePath();
// translate ctx to center of canvas
ctx.translate(canvas.width / 2, canvas.height / 2);
// rotate the rect to 135 degrees of clockwise
ctx.rotate((Math.PI / 180)*135);
ctx.fillStyle = 'blue';
ctx.fillRect(0, 0, rectWidth, rectHeight);
</script>
</body>
Here the demo and you can try yourself: http://okeschool.com/examples/canvas/html5-canvas-rotate
I found this question because I had a bunch of stuff on a canvas, drawn with canvas lines, painstakingly, and then decided some of them should be rotated. Not wanting to do a whole bunch of complex stuff again I wanted to rotate what I had. A simple solution I found was this:
ctx.save();
ctx.translate(x+width_of_item/2,y+height_of_item/2);
ctx.rotate(degrees*(Math.PI/180));
ctx.translate(-(x+width_of_item/2),-(y+height_of_item/2));
// THIS IS THE STUFF YOU WANT ROTATED
// do whatever it is you need to do here, moveto and lineto is all i used
// I would expect anything to work. use normal grid coordinates as if its a
// normal 0,0 in the top left kind of grid
ctx.stroke();
ctx.restore();
Anyway - it might not be particularly elegant but its a dead easy way to rotate one particular element onto your canvas.
Look at all those rotated elements!

Categories