Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Canvas - keeping curved text centered
Forum Updated to NodeBB v4.3 + New Features

Canvas - keeping curved text centered

Scheduled Pinned Locked Moved Solved QML and Qt Quick
2 Posts 1 Posters 277 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • MarkkyboyM Offline
    MarkkyboyM Offline
    Markkyboy
    wrote on last edited by Markkyboy
    #1

    Hi all,

    I'm recreating a watch face with working time/day/date. I'm pretty much there but can't workout how to keep the day name central to the top of the arc.

    I thought I would go with using the index of the given day to call the angle for that text. I've failed and gone round in circles.

    The day names vary slightly in length which is why I'm trying to use an array of angles to set the position within the day window of the watch face.

    I've omitted a lot of code, the watch face/hands/date/etc, leaving just the code for Canvas including stuff I've tried/wanted to keep/play with.

    Perhaps there is a better way than my current approach?

    import QtQuick 2.6
    import QtQuick.Controls 2.0       //originally Sailfish.Silica 1.0
    //import "../images"
    
    Item {
        anchors.fill: parent
    
        Canvas {
            id: day
            smooth: true
            antialiasing: true
            anchors.fill: parent
            onPaint: {
                var ctx = getContext("2d");
                var radius  = 1080;
                var centerX = width/2;
                var centerY = height/2;
                var angle   = Math.PI * .28;
                ctx.font = "bold 44px Mono Bold";
                ctx.textAlign = "center";
                var dayname = Qt.formatDate(new Date(), "dddd")
                //var days = {"sunday":-1.16, "monday":-1.16, "tuesday":-1.15, "wednesday":-1.11, "thursday":-1.13, "friday":-1.17, "saturday":-1.13};
                //function getAnglePosition(day) {
                //    return days[day];
                //}
                //console.log(getAnglePosition(dayname));
    
                var ang = [-1.16,    -1.16,    -1.15,     -1.11,       -1.13,      -1.17,    -1.13     ];
    
                //var dayname = ["sunday","monday","tuesday","wednesday","thursday","friday","saturday"][new Date().getDay()]
                console.log(dayname)
    
                drawTextAlongArc(ctx, dayname, centerX, centerY, radius, angle);
    
                //console.log(days = Qt.formatDate(new Date(), "dddd"))
                //console.log(days)
                //var ang = [-1.16,    -1.16,    -1.15,     -1.11,       -1.13,      -1.17,    -1.13     ];
            }
            function drawTextAlongArc(ctx, str, centerX, centerY, radius, angle) {
                ctx.save();
                ctx.clearRect(0, 0, day.width, day.height);
                ctx.fillStyle = "white";
                ctx.translate(centerX, centerY);
                //ctx.rotate(-1.15 * angle / 2);
    
                ctx.rotate(dayname.rotation * angle / 2); // rotate day name
    
                ctx.rotate(0.00 * (angle / str.length));
                for (var n = 0; n < str.length; n++) {
                    var char1 = str[n];
                    ctx.rotate(angle / str.length);
                    ctx.save();
                    ctx.translate(0, -0.386 * radius);
                    ctx.fillText(char1.toUpperCase(), 0, 0);
                    ctx.restore();
                }
                ctx.restore();
            }
            Label {
                id: dayname
                //text: Qt.formatDate(new Date(), "dddd")
                //rotation: -1.15
            }
    
            Timer {
                id: timer
                running: pageStack.depth === 1
                repeat: true
                onTriggered: {
                    day.requestPaint();
                    //console.log(day.drawTextAlongArc.dayname = Qt.formatDate(new Date(), "dddd"))
                    //console.log(rotateDay.text = angleValue.value)
                }
                triggeredOnStart: true
            }
        }
    }
    
    

    The end result looks something like the following image;

    Screenshot_20240815_122011_001.png

    Don't just sit there standing around, pick up a shovel and sweep up!

    I live by the sea, not in it.

    1 Reply Last reply
    0
    • MarkkyboyM Offline
      MarkkyboyM Offline
      Markkyboy
      wrote on last edited by Markkyboy
      #2

      This is how it is done, with the help of ChatGPT!;

          Canvas {
              id: canvas
              width: 400
              height: 400
              rotation: 180
              anchors.centerIn: parent
      
              onPaint: {
                  var ctx = getContext("2d");
                  ctx.clearRect(0, 0, width, height);
      
                  / / Get the name of today
                  var today = new Date();
                  var dayName = Qt.formatDate(today, "dddd").toUpperCase();
                  //var dayName = "wednesday".toUpperCase();
      
                  // Arc parameters
                  var centerX = width / 2;
                  var centerY = height / 2;
                  var radius = 430;
                  var totalArcLength = Math.PI * 0.24; // The length of the arc (3/4th of a circle)
      
                  // Calculate dynamic letter spacing based on available arc length and number of letters
                  var letterSpacing = totalArcLength / (dayName.length - 1);
                  var startAngle = (Math.PI - totalArcLength) / 2; // Center the text on the arc
      
                  ctx.font = "44px Mono Bold";
                  ctx.textAlign = "center";
                  ctx.textBaseline = "middle";
      
                  for (var i = 0; i < dayName.length; i++) {
                      var angle = startAngle + i * letterSpacing;
                      var x = centerX + radius * Math.cos(angle);
                      var y = centerY + radius * Math.sin(angle);
      
                      ctx.save();
                      ctx.translate(x, y);
                      ctx.rotate(angle + Math.PI / 2); // Rotate the context to align the text along the arc
                      ctx.fillText(dayName[i], 0, 0);
                      ctx.restore();
                  }
              }
              Component.onCompleted: canvas.requestPaint()
          }
      }
      

      Don't just sit there standing around, pick up a shovel and sweep up!

      I live by the sea, not in it.

      1 Reply Last reply
      0
      • MarkkyboyM Markkyboy has marked this topic as solved on

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved