Автоматически узнать ширину у canvas

107
15 января 2021, 13:30

Есть скрипт, который формирует кнопку canvas. Внутри кнопки пишется текст, как узнать ширину текста что бы правильно оцентровать кнопку? Проблема такая если в canvas написать "Буквы" то все хорошо, а если "Буквиница" то символы вылезают за пределы границ. вот код

let c = canvas.getContext('2d'), w = canvas.width, h = canvas.height   
 
let i = c.getImageData(0, 0, w, h) 
for(var x = 0; x < w; x++) { 
for(var y = 0; y < h; y++) { 
    let v = px(x, y) 
    let o = (y*w + x)*4     
    i.data[o++] = v[0]*255 
    i.data[o++] = v[1]*255 
    i.data[o++] = v[2]*255 
    i.data[o++] = v[3]*255 
}} 
c.putImageData(i, 0, 0); 
c.font = "30px Arial"; 
c.textAlign = "center"; 
c.textBaseline = "middle";  
c.fillStyle = 'hsl(250,55%,55%)'  
c.fillText(canvas.getAttribute('data-word'), w/4, h/4) 
 
function sdRoundBox(x, y, sx, sy, r) { 
  x = Math.abs(x) - sx; 
  y = Math.abs(y) - sy; 
  sx = Math.max(x, 0);  
  sy = Math.max(y, 0); 
  return Math.min(Math.max(x, y), 0) + Math.sqrt(sx*sx + sy*sy) - r; 
} 
 
function px(x, y) { 
  let d = Math.abs(sdRoundBox(4*x-w, 4*y-h, 150, 0, 100)); 
  if (d>16) return [0, 0, 0, 0] 
  let c = Math.min(d/32 + 0.4, d/8); 
  return [0.4+(x/w+1-y/h)*0.3, c, 1, 1-c]; 
}
canvas{ 
  margin:10px 
}
<body> 
<canvas width="300" height="150" id="canvas" data-word="Буквы"/> 
</body>

Answer 1

Надо наверное сделать не так, нужно канву поставить как border-image

let canvas = document.createElement('canvas'); 
let c = canvas.getContext('2d'); 
let w = canvas.width = 100; 
let h = canvas.height = 50;   
let i = c.getImageData(0, 0, w, h) 
for(var x = 0; x < w; x++) { 
for(var y = 0; y < h; y++) { 
    let v = px(x, y) 
    let o = (y*w + x)*4     
    i.data[o++] = v[0]*255 
    i.data[o++] = v[1]*255 
    i.data[o++] = v[2]*255 
    i.data[o++] = v[3]*255 
}} 
c.putImageData(i, 0, 0); 
let style = document.createElement('style'); 
style.innerHTML = `.example{border-image-source:url(${canvas.toDataURL()})}`; 
document.head.append(style) 
 
 
function sdRoundBox(x, y, sx, sy, r) { 
  x = Math.abs(x) - sx; 
  y = Math.abs(y) - sy; 
  sx = Math.max(x, 0);  
  sy = Math.max(y, 0); 
  return Math.min(Math.max(x, y), 0) + Math.sqrt(sx*sx + sy*sy) - r; 
} 
 
function px(x, y) { 
  let d = Math.abs(sdRoundBox(2*x-w, 2*y-h, 45, 0, 35)); 
  if (d>16) return [0, 0, 0, 0] 
  let c = Math.min(d/32 + 0.4, d/8); 
  return [0.4+(x/w+1-y/h)*0.3, c, 1, 1-c]; 
}
.example { 
  border: 45px solid transparent; 
  border-top:22px solid transparent; 
  border-bottom:22px solid transparent; 
  border-image-slice: 45%; 
  display: inline-block; 
}
<div class="example">Буквы</div> 
<div class="example">БуквыБуквыБуквы</div>

Answer 2

Попробуй ctx.measureText(). Он возвращает объект с свойством width, которое содержит ширину текста.

READ ALSO
Отменить действие e.preventDefault();

Отменить действие e.preventDefault();

Есть input checkboxНеобходимо ставить галочку только если была нажата клавиша Shift хотя бы один раз

92
Как правильно setState написать?

Как правильно setState написать?

Не получается изменить значение инпутаКак правильно это сделать?

107
IntersectionObserver

IntersectionObserver

Как можно отловить появление выдвигающейся панели при помощи IntersectionObserver?

103