Text Animating around a circle - javascript

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);

Related

How to change direction of text using 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.

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

How i can create a curved text in qml canvas element?

i want to create a curved text in qml it's possible? Is there a javascript library that i can import to do it?
My idea is that it's possible maybe with canvas element but i don't know how i can do it... it's a good idea??
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Canvas{
anchors.fill: parent
onPaint: {
var ctx = getContext("2d");
ctx.fillStyle = Qt.rgba(1, 0, 0, 1);
ctx.fillRect(0, 0, width, height);
//how i can create curved text???
}
}
}
Hello I tried the code into the link posted by #folibis , work perfectly!!!
This is the code :
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Canvas{
property string nameFont: webFont.name
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 char1 = str[n];
context.fillText(char1, 0, 0);
context.restore();
}
context.restore();
}
anchors.fill: parent
onPaint: {
var ctx = getContext("2d");
ctx.fillStyle = Qt.rgba(1, 1, 1, 1);
ctx.fillRect(0, 0, width, height);
ctx.font='50px Verdana'
//ctx.font = '30px Courier New'
ctx.textAlign = "center";
var centerX = width / 2;
var centerY = height/2; //height - 30;
var angle = Math.PI * 0.8; // radians
var radius = 180;
ctx.fillStyle="#000000"
drawTextAlongArc(ctx, "Hello World", centerX, centerY, radius, angle);
}
}
}

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