Altering the character by striking a key

I have a canvas with custom styling. In the center of the canvas is a single letter. Please see the code below for reference. The goal is to change the displayed letter by pressing a key on the keyboard. For instance:

Letter A is centered in the canvas: Pressing the g-key should change it to the letter G (uppercase)

Based on my current understanding, I believe I need to utilize the "keyup" method along with "document.addEventListener". I am currently learning JavaScript through a course, but I've noticed that the course heavily relies on certain libraries, which I personally do not prefer. While I understand the benefits, I would like to establish a foundation in pure JS before delving into unfamiliar libraries. Any guidance on this matter would be greatly appreciated.

body {
    background-color: #000000;
}

canvas {
    padding: 0;
    margin: auto;
    display: block;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: #111416; 
    border: 10px solid #a60000;
    border-style: double;
    box-shadow: 0 0 20px 5px #a60000;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
    <link rel="stylesheet" href="canvas.css">
    <canvas id="myCanvas" width="800" height="800"></canvas>

    <script> 
    
    // Obtain the canvas element by its ID
    var canvas = document.getElementById("myCanvas");

    // Provide the 2D rendering context for drawing on the canvas
    var context = canvas.getContext("2d");

    // Retrieve the width and height of the canvas element
    var canvW = document.getElementById("myCanvas").width;
    var canvH = document.getElementById("myCanvas").height;

    let text = "f";

    context.fillStyle = "#a60000";
    context.font = "700px serif"; 

    // Measure the dimensions of the letter based on the font style
    // Automatically center the letter within the canvas regardless of size
    // Display the size of the letter 
    
    const metrics = context.measureText(text);
    const mx = metrics.actualBoundingBoxLeft * -1;
    const my = metrics.actualBoundingBoxAscent * -1; 
    const mw = metrics.actualBoundingBoxLeft + metrics.actualBoundingBoxRight;
    const mh = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;

    const x = (canvW -mw) *0.5 - mx; 
    const y = (canvH - mh) *0.5 - my; 

    context.save();
    context.translate(x, y);
    context.beginPath();
    context.rect(mx, my, mw, mh);
    context.stroke();
    context.fillText(text, 0, 0);
    context.restore();

    const onKeyUp = (e) => {
        text = e.key.toUpperCase();
        manager.render();
    };

    document.addEventListener("keyup", onKeyUp);

    </script>
    
</body>
</html>

Answer №1

The error you encountered was due to the absence of the manager.render() function in the provided code snippet. I took the liberty of creating it and transferring your drawing operations into it. This function requires an input as an argument, alongside the addition of a clearRect() call to avoid overlapping characters.

// Obtain the canvas element by its id
var canvas = document.getElementById("myCanvas");

// Create a 2D rendering context for the canvas drawing surface
var context = canvas.getContext("2d");

// Retrieve the width and height of the canvas element
var canvW = document.getElementById("myCanvas").width;
var canvH = document.getElementById("myCanvas").height;

context.fillStyle = "#a60000";
context.font = "700px serif"; 
render("t");

function render(text) {
  // Calculate letter size based on specific font
  // Center the letter regardless of size
  const metrics = context.measureText(text);
  const mx = metrics.actualBoundingBoxLeft * -1;
  const my = metrics.actualBoundingBoxAscent * -1; 
  const mw = metrics.actualBoundingBoxLeft + metrics.actualBoundingBoxRight;
  const mh = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;

  const x = (canvW - mw) * 0.5 - mx; 
  const y = (canvH - mh) * 0.5 - my; 

  context.clearRect(0, 0, canvas.width, canvas.height)
  context.save();
  context.translate(x, y);
  context.beginPath();
  context.rect(mx, my, mw, mh);
  context.stroke();
  context.fillText(text, 0, 0);
  context.restore();
}

const onKeyUp = (e) => {
  const text = e.key.toUpperCase();
  render(text);
};

document.addEventListener("keyup", onKeyUp);
body {
    background-color: #000000;
}

canvas {
    padding: 0;
    margin: auto;
    display: block;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: #111416; 
    border: 10px solid #a60000;
    border-style: double;
    box-shadow: 0 0 20px 5px #a60000;
}
<canvas id="myCanvas" width="800" height="800"></canvas>

Answer №2

The issue arises when the canvas is not redrawn after clicking on the button. To fix this, you need to include the method

context.clearRect(0, 0, canvas.width, canvas.height);
in your event listener function. Wrap your logic in a separate function and call it from the event listener with the desired text as a parameter. Check out this Working Example for reference.

Here's the code snippet:

const refreshCanvas = function (text) {
  var canvas = document.getElementById('myCanvas');
  var context = canvas.getContext('2d');
  context.clearRect(0, 0, canvas.width, canvas.height);

  var canvW = document.getElementById('myCanvas').width;
  var canvH = document.getElementById('myCanvas').height;

  context.fillStyle = '#a60000';
  context.font = '700px serif';

  const metrics = context.measureText(text);
  const mx = metrics.actualBoundingBoxLeft * -1;
  const my = metrics.actualBoundingBoxAscent * -1;
  const mw = metrics.actualBoundingBoxLeft + metrics.actualBoundingBoxRight;
  const mh = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;

  const x = (canvW - mw) * 0.5 - mx;
  const y = (canvH - mh) * 0.5 - my;
  context.save();
  context.translate(x, y);
  context.beginPath();
  context.rect(mx, my, mw, mh);
  context.stroke();
  context.fillText(text, 0, 0);
  context.restore();
};
refreshCanvas('I');

const handleKeyPress = (e) => {
  text = e.key.toUpperCase();
  refreshCanvas(text);
};

document.addEventListener('keypress', handleKeyPress);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to adjust the height of an MP4 video to properly display within a Material Box in both landscape and portrait orientations

While I have been learning JavaScript React, I encountered an issue with positioning an MP4 movie. You can view the code in this Codesandbox If you check out the FileContentRenderer.jsx file, you will see that the html5-video is used for the MP4. The g ...

Comparison of valueChanges between ReactiveForms in the dom and component级主动形

Is there a method to determine if the change in valueChanges for a FormControl was initiated by the dom or the component itself? I have a scenario where I need to execute stuff() when the user modifies the value, but I want to avoid executing it if the v ...

Modifying the font style within an ePub document can affect the page count displayed in a UIWebView

Currently in the development phase of my epubReader app. Utilizing CSS to customize the font style within UIWebView, however encountering a challenge with the fixed font size causing fluctuations in the number of pages when changing the font style. Seeki ...

Storing Objects in MongoDB using Node.js

I am working on an application where I need to store an object for later execution of functions. This object essentially holds the data of a cron job. var cronJobObject = schedule.scheduleJob(new Date(2018, 0, 19, 15, 15, 0), function() { console.log( ...

Tips for minimizing the transfer time of large arrays using ajax

https://i.stack.imgur.com/IP0oe.pngDescription I am currently working on transferring a JSON object from the server to the client using PHP and JavaScript via AJAX. The JSON object contains a large array (200x200) of integers. The server is running on lo ...

Setting up CSS Flexbox so that the first child element is the same height as the

I am striving to ensure that when the layout switches to mobile, the image block matches the height of the title and content blocks. The layout is quite complex; it functions correctly in desktop view with the title block at the top full-width. I suspect ...

The search for 'partition' in 'rxjs' did not yield any results

Recently, I attempted to incorporate ng-http-loader into my Angular project. After successfully installing the ng-http-loader package, I encountered an error during compilation. The specific error message displayed was: export 'partition' was ...

Does setInterval consume a significant amount of CPU resources?

Recently, I came across an article stating that setInterval is considered to be CPU intensive. To verify this claim, I developed a script utilizing setInterval and closely monitored the CPU usage. Surprisingly, I did not observe any significant changes in ...

What specific element is being targeted when a directive injects a ViewContainerRef?

What specific element is associated with a ViewContainerRef when injected into a directive? Take this scenario, where we have the following template: template `<div><span vcdirective></span></div>` Now, if the constructor for the ...

Is it possible to prevent website backgrounds from duplicating?

When I visit my website and zoom in using CTRL +, the background image starts duplicating instead of just resizing. Other solutions I've found only stretch the image, which is not what I want. My website has a comments section that can make the length ...

What steps should I follow to effectively store this JSONB data in PostgreSQL by utilizing node-postgres (pg)?

After receiving information in the GET URL, I need to pass it into JSON format and save it with increasing IDs into a PostgreSQL database. However, the code I wrote does not seem to be saving anything without any errors: // Initializing Pg const { Client ...

Styles brought in from external sources do not get applied to components

My goal is to create a separate file specifically for storing styles targeted at IE 9-11. In order to achieve this, I have created a file named InternetExplorer.scss and imported it into my main file styles.scss: @import "scss/InternetExplorer.scss"; The ...

The Angular service/value is failing to retrieve the updated variable from the $(document).ready() function

Currently, I'm facing an issue with my Angular service/value. It seems to be grabbing the original variable instead of the new one that is supposed to be inside $(document).ready(). Here's the relevant code snippet: var app = angular.module("app ...

What is the best way to prioritize a non-submit button over a submit button in material-ui?

I am facing an issue with a form on my website. Whenever I press the enter key, the form is automatically submitted. Everything seems to be working fine so far. However, there is a specific scenario where if a user selects a certain option in the form, it ...

Querying the Collection for document counts is failing to display any data

Hey there, I am currently in the process of developing a social media app with the MEAN stack. One of the key features I'm working on is the ability to list the users that a person is following. However, I have encountered an issue as Collections.Find ...

How can JavaScript/jQuery be used to update LocalStorage Objects when editing a form?

Having trouble pinpointing an issue with my code. Despite making modifications, the values in localStorage are not updating as expected. Any suggestions on what may be causing this problem? Note: Changing const idx to const i resulted in only the final va ...

Managing the layout with React Native Flexbox to evenly distribute items

Check out this React Native Demo I put together featuring Santa images being added and removed in a Flexbox. Bunch of Santas I noticed that when there are more than 3 Santas, the layout shifts to the left. I'm curious about how to keep the Santas ce ...

As I go through the database, I notice that my div model functions correctly for the initial record but does not work for any subsequent ones

I came across a model on w3 schools that fits my requirements, but I am facing an issue where the model only works for the first result when looping through my database. It's likely related to the JavaScript code, but I lack experience in this area. C ...

Transmit JSON data from the client to the MarkLogic Server device

Hello everyone, hope you are all doing well. I am a beginner in Marklogic and recently managed to set up a rest api on my local machine. Following the given example, I used curl to send/create documents in the database. Now, my query is how can I access/ ...

Is it possible to style the parent CSS file using a query?

Is it feasible to achieve this, or are there alternative methods to accomplish something similar? In a CSS file, we have the ability to set queries for various screen resolutions, allowing CSS rules to apply only to specific screens. @media (max-width: 76 ...