How to change direction of text using javascript - javascript

I've been trying to create a 2-part circle using JS where 2 different sentences will be used to compile a whole circle.
I can't find out how to make the direction of the bottom sentence to be from left to right.
No matter what i do the bottom sentence starts from the right side of the circle and circles back to the left.
function drawTextAlongArc(context, str, centerX, centerY, radius, angle,side){
context.save();
context.translate(centerX, centerY);
context.rotate( -1 * angle / 2);
context.rotate(-1 * (angle / str.length) / 2);
for (var n = 0; n < str.length; n++) {
context.rotate(angle / str.length);
context.save();
context.translate(0, side * radius);
var char = str[n];
context.fillText(char, 0, 0);
context.restore();
}
context.restore();
}
window.onload = function(){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
canvas.dir = 'ltr';
context.font = "14px Arial";
context.textAlign = "center";
context.direction = "ltr";
var centerX = canvas.width / 2;
var centerY = canvas.height - 190;
var angle = 3; // radians
var radius = 180;
var radius2 = 189;
drawTextAlongArc(context, "Upper Text goes here", centerX, centerY, radius, angle, '-1');
canvas.setAttribute('dir','ltr');
drawTextAlongArc(context, "Bottom Text goes here", centerX, centerY, radius2, angle, '1');
};
<canvas id="myCanvas" width="578" height="550" dir="ltr"></canvas>

I believe this is what you're trying to achieve. I simply took what you already had and called split followed by reverse on the bottom string:
function drawTextAlongArc(context, str, centerX, centerY, radius, angle, side) {
context.save();
context.translate(centerX, centerY);
context.rotate(-1 * angle / 2);
context.rotate(-1 * (angle / str.length) / 2);
for (var n = 0; n < str.length; n++) {
context.rotate(angle / str.length);
context.save();
context.translate(0, side * radius);
var char = str[n];
context.fillText(char, 0, 0);
context.restore();
}
context.restore();
}
window.onload = function() {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
canvas.dir = 'ltr';
context.font = "14px Arial";
context.textAlign = "center";
context.direction = "ltr";
var centerX = canvas.width / 2;
var centerY = canvas.height - 190;
var angle = 3; // radians
var radius = 180;
var radius2 = 189;
drawTextAlongArc(context, "Upper Text goes here", centerX, centerY, radius, angle, '-1');
canvas.setAttribute('dir', 'ltr');
drawTextAlongArc(context, "Bottom Text goes here".split('').reverse(), centerX, centerY, radius2, angle, '1');
};
<canvas id="myCanvas" width="578" height="550" dir="ltr"></canvas>

Ciao, the first solution I found is to reverse the string like this:
<canvas id="myCanvas" width="578" height="550" dir="ltr"></canvas>
<script>
function drawTextAlongArc(context, str, centerX, centerY, radius, angle,side){
context.save();
context.translate(centerX, centerY);
context.rotate( -1 * angle / 2);
context.rotate(-1 * (angle / str.length) / 2);
for (var n = 0; n < str.length; n++) {
context.rotate(angle / str.length);
context.save();
context.translate(0, side * radius);
var char = str[n];
context.fillText(char, 0, 0);
context.restore();
}
context.restore();
}
window.onload = function(){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
canvas.dir = 'ltr';
context.font = "14px Arial";
context.textAlign = "center";
context.direction = "ltr";
var centerX = canvas.width / 2;
var centerY = canvas.height - 190;
var angle = 3; // radians
var radius = 180;
var radius2 = 189;
drawTextAlongArc(context, "Upper Text goes here", centerX, centerY, radius, angle, '-1');
canvas.setAttribute('dir','ltr');
let string = "Bottom Text goes here"
var splitString = string.split("");
var reverseArray = splitString.reverse();
var joinArray = reverseArray.join("");
drawTextAlongArc(context, joinArray, centerX, centerY, radius2, angle, '1');
};
</script>
Maybe is not the best solution but it works.

Related

Fixed width for a curved text in canvas

I have a canvas element, and a text is rendered in the canvas element, there is a slider outside, if you slide the text gets curved upside and downside, but I want the text to be a fixed width, right now the text gets expanded if you slide to both min max values, and gets shrinked at slider value zero. Also I need the straightened text on slider value zero. Hope you understand the problem.
var canvas = document.getElementById("CanvasText");
var ctx1 = canvas.getContext("2d");
ctx1.font = "30pt Arial";
ctx1.textAlign = "center";
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var angle = Math.PI * 0.8;
var slider = document.getElementsByClassName("sprd-slider");
for(var i = 0; i < slider.length ; i++){
slider[i].addEventListener('input', function() { drawTextAlongArc(ctx1, "SHOYEB", centerX, centerY, this.value, angle) }, false)
}
function drawTextAlongArc(context, str, centerX, centerY, radius, angle) {
var isPositive = (Number(radius)>=0) ? true : false;
angle = isPositive ? -angle : angle;
context.clearRect(0, 0, 800, 800);
context.save();
context.translate(centerX, centerY);
context.rotate(-1 * angle / 2);
context.rotate(-1 * (angle / str.length) / 2);
for (var n = 0; n < str.length; n++) {
context.rotate(angle / str.length);
context.save();
context.translate(0, radius );
var char = str[n];
context.fillText(char, 0, 0);
context.restore();
}
context.restore();
}
<input data-testid="text-angle" class="sprd-slider" type="range" min="-355" max="355" step="1" value="100" >
<canvas id="CanvasText" width="800" height="800" ></canvas>

How to draw part of ellipse? (0-100%)

I'd like to draw an ellipse given a cx and cy position-property and a width and height property of the ellipse itself.
Below you can find some working code for this setup:
But now I want to generate a kind of "progress display" by painting a percentage (from 0 to 100) of the ellipse instead of the complete ellipse.
I have attached a graphic here to illustrate the whole thing:
I don't really have a clear idea how to do that. I would prefer a solution where I can do without resizing the canvas - just for performance reasons and I hope someone has a good idea how to solve my problem.
let canvas = document.getElementById("canvas")
let ctx = canvas.getContext("2d");
canvas.width = 400;
canvas.height = 280;
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height)
let ellipse = function(cx, cy, w, h) {
let lx = cx - w / 2,
rx = cx + w / 2,
ty = cy - h / 2,
by = cy + h / 2;
let magic = 0.551784;
let xmagic = magic * w / 2,
ymagic = h * magic / 2;
let region = new Path2D();
region.moveTo(cx, ty);
region.bezierCurveTo(cx + xmagic, ty, rx, cy - ymagic, rx, cy);
region.bezierCurveTo(rx, cy + ymagic, cx + xmagic, by, cx, by);
region.bezierCurveTo(cx - xmagic, by, lx, cy + ymagic, lx, cy);
region.bezierCurveTo(lx, cy - ymagic, cx - xmagic, ty, cx, ty);
ctx.strokeStyle = "red";
ctx.lineWidth = "10";
region.closePath();
ctx.stroke(region);
}
ellipse(canvas.width / 2, canvas.height / 2, 300, 120)
<canvas id="canvas"></canvas>
You can use the built-in function ctx.ellipse - first we draw the green line as a full ellipse. Next, draw the red partial ellipse on top:
let canvas = document.getElementById("canvas")
let ctx = canvas.getContext("2d");
canvas.width = 400;
canvas.height = 280;
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height)
function ellipse(ctx, color, x,y, w, h, thickness, angle) {
ctx.strokeStyle = color;
ctx.beginPath();
ctx.ellipse(canvas.width / 2, canvas.height / 2, h/2,w/2, Math.PI*3/2, 0, angle);
ctx.lineWidth = thickness;
ctx.stroke();
}
function ell(percent) {
let x= canvas.width / 2;
let y= canvas.height / 2;
let w=300;
let h=120;
let th = 10; // example thickness 10px
ellipse(ctx, '#608a32', x,y, w, h, th, Math.PI*2);
ellipse(ctx, '#ed3833', x,y , w, h, th+.3, 2*Math.PI*percent/100);
}
ell(90); // here we start draw for 90%
<canvas id="canvas"></canvas>
You can draw the ellipse with a bit of trigonometry
let canvas = document.getElementById("canvas")
let ctx = canvas.getContext("2d");
canvas.width = 400;
canvas.height = 170;
let ellipse = function(cx, cy, ds, de, w, h, color) {
for (var i = ds; i < de; i ++) {
var angle = i * ((Math.PI * 2) / 360);
var x = Math.cos(angle) * w;
var y = Math.sin(angle) * h;
ctx.beginPath();
ctx.fillStyle = color;
ctx.arc(cx+ x, cy+y, 6, 0, 2 * Math.PI);
ctx.fill();
}
}
let draw = function(cx, cy, ds, de, w, h, color) {
ctx.clearRect(0, 0, canvas.width, canvas.height)
delta += 10
if (delta > 350) delta = 40
hw = canvas.width / 2
hh = canvas.height / 2
ellipse(hw, hh, 0, 360, 150, 60, "red")
ellipse(hw, hh, 0, delta, 150, 60, "blue")
ctx.font = "80px Arial";
ctx.fillStyle = "green";
ctx.fillText(Math.round(delta/3.6) + "%", hw-70, hh+30);
}
delta = 90
setInterval(draw, 100)
<canvas id="canvas"></canvas>
Once you have a nice function you can animate it

html5 canvas loading circle image

I'm trying to create a loading circle from an image in HTML5 canvas.
Here's the result I expect when percentage is at 50%:
here's what I've done after a lot of tests: (the blue stroke is just to see the circle, it'll be removed after)
var img = new Image();
img.onload = draw;
img.src = "http://i.imgur.com/HVJBZ1L.png";
var canvas = document.getElementsByTagName("canvas")[0];
canvas.width = 500;
canvas.height = 500;
var ctx = canvas.getContext("2d");
function draw() {
ctx.globalAlpha = 0.5
ctx.drawImage(img, 0, 0);
ctx.globalAlpha = 1;
var X = 50;
var Y = 50;
var Radius = img.width / 2;
var end = 40;
var start = 0;
var PI2 = Math.PI * 2;
var quart = Math.PI / 2;
var pct = 50 / 100;
var extent = (end - start) * pct;
var current = (end - start) / 100 * PI2 * pct - quart;
var pattern = ctx.createPattern(img, 'no-repeat');
ctx.beginPath();
ctx.arc(X, Y, Radius, -quart, current);
ctx.closePath();
ctx.fillStyle=pattern;
ctx.fill();
ctx.strokeStyle = "blue";
ctx.stroke();
}
<canvas></canvas>
as you can see, the result here isn't as excepted
What is wrong?
First, you need to correctly calculate your center point:
var X = img.width / 2;
var Y = img.height / 2;
Then you need to circle back in counter-clockwise direction tracing the inner radius Radius - 17:
ctx.beginPath();
ctx.arc(X, Y, Radius, -quart, current);
ctx.arc(X, Y, Radius - 17, current, -quart, true);
ctx.closePath();
If you aren't interested in the stroke outline, you could move to the center first, and then arc:
ctx.beginPath();
ctx.moveTo(X, Y);
ctx.arc(X, Y, Radius, -quart, current);
ctx.closePath();
Example:
var img = new Image();
img.onload = draw;
img.src = "http://i.imgur.com/HVJBZ1L.png";
var canvas = document.getElementsByTagName("canvas")[0];
canvas.width = 500;
canvas.height = 500;
var ctx = canvas.getContext("2d");
function draw() {
ctx.globalAlpha = 0.5
ctx.drawImage(img, 0, 0);
ctx.globalAlpha = 1;
var X = img.width / 2;
var Y = img.height / 2;
var Radius = img.width / 2;
var end = 40;
var start = 0;
var PI2 = Math.PI * 2;
var quart = Math.PI / 2;
var pct = 50 / 100;
var extent = (end - start) * pct;
var current = (end - start) / 100 * PI2 * pct - quart;
var pattern = ctx.createPattern(img, 'no-repeat');
ctx.beginPath();
ctx.moveTo(X, Y);
ctx.arc(X, Y, Radius, -quart, current);
ctx.closePath();
ctx.fillStyle = pattern;
ctx.fill();
}
<canvas></canvas>
const img = new Image();
img.src = "http://i.imgur.com/HVJBZ1L.png";
img.onload = imageLoaded;
var W,H; // width and height when image ready
const ctx = canvas.getContext("2d");
// define the distance of the progress 0- 100
const min = 0;
const max = 100;
var pattern;
var radius;
// get pattern, radius canvas size from image ans start animation
function imageLoaded(){
requestAnimationFrame(mainLoop);
W = this.width;
H = this.height;
pattern = ctx.createPattern(this, 'no-repeat');
radius = W / 2;
canvas.width = W;
canvas.height = H;
}
// draw the background and forground images
// amount is the amount of progress. amount >= min amount <= max
function draw(amount) {
ctx.globalAlpha = 0.5
ctx.drawImage(img, 0, 0);
ctx.globalAlpha = 1;
ctx.fillStyle=pattern;
ctx.strokeStyle = "blue";
ctx.beginPath();
ctx.arc( // draw inside circle CCW
W/2,
H/2,
radius - 17,
((amount - min) / (max-min)) * Math.PI * 2 - Math.PI / 2,
-Math.PI / 2,
true
);
ctx.arc( // draw outer circle CW
W/2,
H/2,
radius,
-Math.PI / 2,
((amount - min) / (max-min)) * Math.PI * 2 - Math.PI / 2
);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
// animate the thing.
function mainLoop(time){
ctx.clearRect(0,0,canvas.width,canvas.height);
draw((time / 50) % max);
requestAnimationFrame(mainLoop);
}
canvas { border : 2px solid black;}
<canvas id="canvas"></canvas>

Text Animating around a circle

So I have code that works when I dont add the rotate() code, but when I add it it spins by the J of my name in more of a pinwheel effect. I want the text to rotate around a circle.
Here is what i have
How can I fix this to do what I want?
CODE
function showCircularNameRotating(text,x,y,radius,space,top){
var w = canvas.width,
h = canvas.height,
cx = w * 0.5,
cy = h * 0.5,
angleStep = 0.1,
txt = 'Justin Esders';
space = space || 0;
var numRadsPerLetter = (Math.PI - space * 2) / text.length;
context.save();
context.translate(x,y);
var k = (top) ? 1 : -1;
context.rotate(-k * ((Math.PI - numRadsPerLetter) / 2 - space));
for(var i=0;i<text.length;i++){
context.save();
context.rotate(k*i*(numRadsPerLetter));
context.textAlign = "center";
context.textBaseline = (!top) ? "top" : "bottom";
context.fillText(text[i],0,-k*(radius));
context.restore();
}
context.restore();
(function rotate() {
context.clearRect(0, 0, canvas.width, canvas.height);
context.translate(cx, cy);
context.rotate(angleStep);
context.translate(-cx, -cy);
context.fillText(txt, cx, cy);
requestAnimationFrame(rotate);
})();
}
Sample Usage
showCircularNameRotating("Justin Esders",150,150,75,Math.PI/12);

How to make the text write in counterclockwise direction

How do I make text write counter-clockwise?
function drawTextAlongArc(context, str, centerX, centerY, radius, angle){
context.save();
context.translate(centerX, centerY);
context.rotate(-1 * angle / 2);
context.rotate(-1 * (angle / str.length) / 2);
for (var n = 0; n < str.length; n++) {
context.rotate(angle / str.length);
context.save();
context.translate(0, -1 * radius);
var char = str[n];
context.fillText(char, 0, 0);
context.restore();
}
context.restore();
}
window.onload = function(){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.font = "30pt Calibri";
context.textAlign = "center";
context.fillStyle = "blue";
context.strokeStyle = "blue";
context.lineWidth = 4;
var centerX = canvas.width / 2;
var centerY = canvas.height - 30;
var angle = Math.PI * 0.8; // radians
var radius = 150;
drawTextAlongArc(context, "Text along arc path", centerX, centerY, radius, angle);
// draw circle underneath text
context.arc(centerX, centerY, radius - 10, 0, 2 * Math.PI, false);
context.stroke();
};
I want to text to appear like this in counter clockwise
Not sure what you're asking, but if you want to write your text backwards in a counter-clockwise direction you'd just change this line:
drawTextAlongArc(context, "Text along arc path", centerX, centerY, radius, -angle);
last argument changed to -angle
the text is going to be backwards though, as you would expect.

Categories