I am trying to create graph in a HTML5 canvas. But text in the x axis is overlapping. I am trying to rotate it so it looks neat.
Example jsfiddle: http://jsfiddle.net/67tddgcj/1/
I tried to save, rotate, and restore like below
c.save();
c.rotate(-Math.PI/2);
c.fillText(data.values[i].X, getXPixel(i), graph.height() - yPadding + 20);
c.restore();
But the text appears in a different place.
You could angle your text so it always fits the graph like this:
Save the starting context state (untransformed)
Set the desired font
Measure the pixel width of the text
Translate to the desired endpoint
Rotate to the desired angle
Set the text baseline so the text is vertically centered on the endpoint
Draw the text offset by the negative width so the text ends at the desired endpoint
Rrestore the context to its starting state
Here is example code and a Demo:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
for(var i=0;i<10;i++){
var endingX=30+i*15;
drawRotatedText(endingX,50,-Math.PI/4,'Jan '+i,'9px verdana');
}
function drawRotatedText(endingX,centerY,radianAngle,text,font){
// save the starting context state (untransformed)
ctx.save();
// set the desired font
ctx.font=font;
// measure the pixel width of the text
var width=ctx.measureText(text).width;
// translate to the desired endpoint
ctx.translate(endingX,centerY);
// rotate to the desired angle
ctx.rotate(radianAngle);
// set the text baseline so the text
// is vertically centered on the endpoint
ctx.textBaseline='middle';
// draw the text offset by the negative width
// so the text ends at the desired endpoint
ctx.fillText(text,-width,0);
// restore the context to its starting state
ctx.restore();
}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=300 height=300></canvas>
Related
I'm drawing a polygon to the canvas, which has an image clipped inside of it.
On touch start and end, I'm slicing that polygon into two polygons and rotating them and pushing them away from each other. Similar functionality to Fruit Ninja.
My issue is drawing the image to the new polygons, so make it look like you have sliced the image in half and it's now rotating away.
Does anyone have any advice. I don't necessarily need code, I just need to understand how it's done so I can program it.
Thanks heaps.
Infinite designs are possible, but for example...
Use translate to set the rotation point outside the polygon.
rotate to a positive angle and draw the left half of the poly.
Reset the transformations.
Use translate to set the rotation point outside the polygon.
rotate to a negative angle and draw the right half of the poly.
Reset the transformations.
Demo:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var cx=50;
var cy=20;
var r=20;
var angle=0;
ctx.fillStyle='salmon';
ctx.strokeStyle='forestgreen';
ctx.lineWidth=3;
requestAnimationFrame(animate);
function draw(angle){
ctx.clearRect(0,0,cw,ch);
// left side
ctx.translate(cx,cy+40);
ctx.rotate(angle);
ctx.beginPath();
ctx.arc(cx,cy,r,Math.PI/2,Math.PI*3/2);
ctx.fill();
ctx.stroke();
ctx.setTransform(1,0,0,1,0,0);
// right side
ctx.translate(cx,cy+40);
ctx.rotate(-angle);
ctx.beginPath();
ctx.arc(cx,cy,r,Math.PI*3/2,Math.PI/2);
ctx.fill();
ctx.stroke();
ctx.setTransform(1,0,0,1,0,0);
}
function animate(){
draw(angle);
angle+=Math.PI/720;
if(angle<Math.PI/4){ requestAnimationFrame(animate); }
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=200 height=200></canvas>
In HTML/CSS we can align a child to any side of the parent through: top, right, left, bottom
Can this be applied to rectangles, lines etc.. on canvas's?
Alternatively is their a way to use percentages in positioning?
My end goal is to get a rectangle whose position snaps to the right of the canvas and stays their if the canvas is resized.
I can't seam to figure out a way to do this.
This is what I'm working with it.
ctx.rect(20,20,150,100);
Html & CSS can reposition child elements because the definitions of those children are saved in the Document Object Model (DOM).
The Html Canvas element does not save the definitions of any rectangles, lines, etc. that it draws on itself. Therefore, it cannot "recall" your rectangle to reposition it. To Canvas, your rectangle becomes unremembered pixels on its bitmap display.
To reposition your rectangle, you will have to manually "remember" its definition using code. This is usually done by saving your rectangle's definition in a javascript object like this:
var myRect={
x:20,
y:20,
width:150,
height:100,
}
When you want to reposition a canvas rectangle (as when you want it to "stick" to a resized canvas), you:
Resize the canvas. (Note: resizing the canvas element automatically clears its contents).
Calculate the new [x,y] that will keep your rectangle "stuck" to the right side of the canvas. If you want your rectangle stuck to the right side, you recalculate: var newX=canvas.width-myRect.width
Change the [x,y] in myRect to those new x,y values.
Use myRect to redraw your rectangle in its new desired postion.
Here's annotated example code and a Demo:
// canvas related variables
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
// the definition of your rectangle
// (this definition is used when your rectangle must be redrawn)
var myRect={
x:20,
y:20,
width:150,
height:100,
}
// call helper function to reset your rectangle's "x"
// so it's positioned to the right side
stickRight(myRect);
// call helper function to redraw your rectangle
redrawRect(myRect);
// listen for changes in the html slider that resizes the canvas
$myslider=$('#myslider');
$myslider.change(function(){
// fetch the scaling factor the user has specified with the slider
var scale=parseInt($(this).val());
// resize the canvas to the specified size
// NOTE: resizing the canvas automatically erases all content
canvas.width=cw*scale/100;
canvas.height=ch*scale/100;
// again call helper function to reset your rectangle's "x"
// so it's positioned to the right side
stickRight(myRect);
// call helper function to redraw your rectangle
redrawRect(myRect);
});
function stickRight(rect){
rect.x=canvas.width-myRect.width;
}
function redrawRect(rect){
ctx.beginPath();
ctx.rect(rect.x,rect.y,rect.width,rect.height);
ctx.stroke()
}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
Resize: <input id=myslider type=range min=0 max=200 value=100><br>
<canvas id="canvas" width=300 height=300></canvas>
I'm dynamically drawing a polygon inside a canvas using this code I found. (the coordinates are provided by the user)
https://stackoverflow.com/a/4841057/1667856
Is it possible to move this polygon into the center of a canvas after/before it has been created?
I found out that you can use the canvas translate() method to move shapes around but I can't seem to figure out how to recalculate the coordinates so that the polygon will automatically appear in the middle of the canvas and not on its original coordinates.
As you've probably discovered, html canvas is just a pixel drawing.
The shapes you draw on the canvas are just like dried paint. They can't be moved or remolded into another shape.
The typical way of "moving" a shape is to clear the canvas and redraw the same shape with different coordinates.
You can create those coordinates by adding an offsetX and offsetY to all the polygon coordinates.
Alternatively (more simply) you can translate the coordinates.
Important note: context.translate does not just move the coordinates of your polygon. It changes every coordinate for all NEW drawings.
ctx.translate(50,50) "moves" the canvas's origin to 50,50. That means if you start drawing your polygon at 5,5 you will visually start drawing at 50+5,50+5.
Here is example code and a Demo: http://jsfiddle.net/m1erickson/2Gm73/
<!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");
// calculate the middle of the canvas
var centerX=canvas.width/2;
var centerY=canvas.height/2;
// just for testing: draw crosshairs on center canvas
ctx.beginPath();
ctx.moveTo(centerX,0);
ctx.lineTo(centerX,canvas.height);
ctx.moveTo(0,centerY);
ctx.lineTo(canvas.width,centerY);
ctx.stroke();
// define some points for your polygon
var poly=[ 5,5, 100,50, 50,100, 10,90 ];
// save the canvas context in its untranslated state
ctx.save();
// translate the canvas
// the context now uses centerX,centerY as its 0,0 origin
ctx.translate(centerX,centerY);
// draw the polygon
ctx.beginPath();
ctx.moveTo(poly[0], poly[1]);
for(var i=2;i<poly.length;i+=2){
ctx.lineTo( poly[i] , poly[i+1] )
}
ctx.closePath();
ctx.fillStyle = '#f00';
ctx.fill();
// restore the context to its untranslated state
// (otherwise all further drawings will be "moved"
// just like this polygon
ctx.restore();
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
If you want your polygon to be visually centered in the canvas, you must also calculate the offset of the center of your polygon itself:
// calc the max values of x,y in the polygon and divide by 2
var centerPolyX = 100/2; // max x comes from coordinate 100,50
var centerPolyY = 100/2; // max y comes from coordinate 50,100
Then translate to center canvas minus the polygon center:
// move to center canvas
// but then move left and up by half the polygon's size
ctx.translate(centerX-centerPolyX,centerY-centerPolyY);
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
Is it possible to add a glow effect to an already drawn canvas without having to calculate it myself? (Using gradients, shadow or something...)
I have tried adding a glow by drawing the canvas as an image to a different canvas and drawing it back with a shadow added.
The problem with it is that it depends on the amount of pixels around the shadow - because it blurs the image - so that is not good enough.
There is a website that goes over the glow effect along with other typographic effects for canvas text here.
Here's the gist of the glow effect:
// Assuming your canvas element is ctx
// Color of the shadow; RGB, RGBA, HSL, HEX, and other inputs are valid.
ctx.shadowColor = "red"; // string
// Horizontal distance of the shadow, in relation to the text.
ctx.shadowOffsetX = 0; // integer
// Vertical distance of the shadow, in relation to the text.
ctx.shadowOffsetY = 0; // integer
// Blurring effect to the shadow, the larger the value, the greater the blur.
ctx.shadowBlur = 10; // integer