A feature like text box is common in whiteboard applications. When I tried to implement this feature, I found it’s hard to align the text area and the canvas. Usually the text on canvas fades and the text area over it shows for editing the content when a user clicks on the text box.
In the following example, I purposely make them overlap to demonstrate the offset they have in y axis.
import { useEffect, useRef } from 'react';
import './App.css';
const WIDTH = 300;
const HEIGHT = 300;
const FONT_SIZE = 80;
function App() {
const canvasRef = useRef()
useEffect(() => {
const canvas = canvasRef.current
canvas.width = WIDTH * devicePixelRatio
canvas.height = HEIGHT * devicePixelRatio
canvas.style.width = `${WIDTH}px`
canvas.style.height = `${HEIGHT}px`
const context = canvas.getContext('2d')
context.fillStyle = 'red'
context.font = `${FONT_SIZE * devicePixelRatio}px sans-serif`
const metrics = context.measureText('M')
context.clearRect(0, 0, WIDTH * devicePixelRatio, HEIGHT * devicePixelRatio)
context.fillText('Hello', 0, metrics.fontBoundingBoxAscent)
context.fillText('World', 0, metrics.fontBoundingBoxAscent + FONT_SIZE * devicePixelRatio)
}, [])
return (
<div className="App">
<div className="container">
<canvas ref={canvasRef} />
<textarea value="Hello World" style={{ width: `${WIDTH}px`, height: `${HEIGHT}px` }}/>
</div>
</div>
);
}
export default App;
.App {
text-align: center;
}
.container {
width: 300px;
height: 300px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
textarea {
position: absolute;
inset: 0;
outline: none;
border: none;
resize: none;
padding: 0;
line-height: 1;
width: 300px;
height: 300px;
font-size: 80px;
background-color: transparent;
font-family: sans-serif;
}
}
Does anyone know what makes the difference between the text positioning?