2017-10-24 19 views
5

Pracujemy z Fabric JS, aby dodać obiekty tekstowe i obrazy do obszaru roboczego.Tkanina JS: Obszar wyboru obiektu tekstowego jest większy niż rzeczywisty rozmiar tekstu.

Po dodaniu dowolnego obiektu tekstowego i zaznaczeniu go, obszar zaznaczenia jest większy niż rzeczywisty rozmiar tekstu.

Please refer this link to see the screen-shot.

Używamy poniższy kod, żeby dodać obiekt tekstowy.

 
var text_object = new fabric.Text('00', { 
        fontSize: 192, 
        fontFamily: 'Times New Roman', 
        padding: 0 
        }); 
text_object.top = parseInt((canvas.height - text_object.height)/2); 
text_object.left = parseInt((canvas.width - text_object.width)/2); 
text_object.lockUniScaling = true; 
canvas.add(text_object); 
canvas.renderAll(); 
canvas.setActiveObject(text_object); 

Głównym problemem jest próba uzyskania szerokości i wysokości dodawanego obiektu tekstowego; daje nam szerokość i wysokość obszaru zaznaczenia obiektu tekstowego, a nie faktyczny rozmiar tekstu.

Jak możemy uczynić obszar zaznaczania obiektu tekstowego taki sam jak rzeczywisty rozmiar tekstu?

Albo w jaki sposób możemy uzyskać rzeczywisty rozmiar tekstu bez obszaru wyboru?

+0

Czy możesz utworzyć minimalny fragment kodu, podając swój problem? – Durga

+0

Dodałem fragment kodu, o którym mowa. Więc proszę sprawdź. –

Odpowiedz

3

Nie ma bezpośredniej drogi do osiągnięcia tego, co chcesz, to byłaby ramka graniczna ścieżek wektorowych tekstu.

Jeśli masz dobre przybliżone rozwiązanie, wyślij tekst do pustego płótna, użyj funkcji getImageData do sprawdzenia przezroczystości wszystkich pikseli i znajdź wartości max i min x oraz y, w których znajdują się wypełnione punkty. To daleki od doskonałości, ale nie dostaniesz lepszego rozwiązania.

Sądzę, że mogą istnieć rozwiązania po stronie serwera, ale nie znam żadnych.

Teoretycznie możliwe byłoby stworzenie własnego silnika renderującego czcionki w JS, a więc miałbyś idealne ramki ograniczające, ale z wyjątkiem prostych/zabawkowych przypadków, poważny układ tekstu zajmuje lata i lata do wdrożenia, więc domyślam się, że jest całkowicie poza zakresem.

Jeśli potrzebujesz pomocy z metodą aproksymacji, powiedz mi, a ja podam przykład.

Edited by podać przykład:

function getVisiblePixelsBoundingBox(canvas) { 
 
    const context = canvas.getContext("2d"); 
 
    const imageData = context.getImageData(0, 0, canvas.width, canvas.height).data; 
 
    let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity; 
 
    for (let y = 0; y < canvas.height; y++) { 
 
     for (let x = 0; x < canvas.width; x++) { 
 
      const alpha = imageData[(y * canvas.width + x) * 4 + 3]; 
 
      if (alpha > 0) { 
 
       minX = Math.min(minX, x); 
 
       minY = Math.min(minY, y); 
 
       maxX = Math.max(maxX, x); 
 
       maxY = Math.max(maxY, y); 
 
      } 
 
     } 
 
    } 
 
    return { 
 
     left: minX, 
 
     top: minY, 
 
     width: maxX - minX, 
 
     height: maxY - minY 
 
    }; 
 
} 
 

 
// you will need to create a new canvas 
 
var canvas = document.createElement("canvas"), 
 
    context = canvas.getContext("2d"); 
 

 
// and set the width and height the same as the canvas you want to draw the text 
 
// here I'm just adding some values for the example: 
 
canvas.width = 600; 
 
canvas.height = 400; 
 

 
// now I'm going to draw some text on it 
 
context.font = "120px serif"; 
 
context.fillText("Lipsum", 100, 200); 
 

 
let boundingBox = getVisiblePixelsBoundingBox(canvas); 
 

 
// now this is not needed in your case, but want to see the canvas and 
 
// I will draw a rectangle around the bounding box to see how it works: 
 
document.body.appendChild(canvas); 
 
context.strokeStyle = "red"; 
 
context.strokeRect(boundingBox.left, boundingBox.top, boundingBox.width, boundingBox.height);

OK, więc to wydaje się dobry, ale uważaj na zagadnieniach:

  • Precyzja jest ograniczona do pikseli, więc podczas rysowania obwiedni jest całkowicie ok, nie jest dobre dla operacji tha t wymagałoby znacznie większej precyzji, np. idealnie wyrównujących kształtów. Ponadto, ze względu na metodę pomiaru, jeśli część kształtu jest tak cienka, że ​​nie jest widoczna w ogóle, to nie zostanie zmierzona (prawdopodobnie nie jest to dla ciebie duży problem, ponieważ tak ekstremalnie cienkie kształty nie występują w czcionki).

  • Wykonanie go może być powolne, ponieważ wykonujemy iterację wszystkich pikseli, aby uzyskać wynik (a JS nie jest do tego specjalnie szybki). Wiedząc o tym, możesz ulec pokusie, by spróbować zmniejszyć rozmiar płótna i nie używać tego samego płótna docelowego płótna, ale radzę ci tego nie robić, ponieważ wprowadziłoby to nowe problemy związane z następnym punktem.

  • Jeśli dokonasz pomiaru z tekstem wychodzącym poza obszar roboczy, ramka ograniczająca zostanie ograniczona do widocznego obszaru (będzie przylegał do krawędzi). Możesz pomyśleć o zwiększeniu rozmiaru płótna, jeśli tak się stanie, by uzyskać rzeczywistą szerokość i wysokość, ale jeśli nie ograniczysz rozmiaru czcionki i ilości tekstu, możesz skończyć na kanwie tak dużej, że spowalnia przeglądarkę lub może nawet to rozbija ... Tak więc po prostu zaakceptowałbym, że ramka graniczna przylega do granic. Możesz pomyśleć, używając szerokości dostarczonej przez measureText może pomóc, ale niestety, aby uzyskać górę i wysokość trzeba zeskanować pełny obraz.

+1

Wygląda na to, że standard dla TextMetrics został zaktualizowany, ale żadna przeglądarka go nie obsługuje. https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics –

+0

Dzięki Roman. Proszę podać pomoc przy pomocy metody aproksymacji na przykładzie. Możemy to sprawdzić i wykorzystamy, jeśli zadziała dla nas. –

+0

Przykład podany, proszę sprawdzić –