2012-04-11 34 views
12

Tôi đang vẽ văn bản trong canvas HTML5 phía trên hình ảnh (trình tạo meme). Tôi muốn tính toán kích thước phông chữ sao cho chuỗi sẽ kéo dài toàn bộ chiều rộng của canvas. Vì vậy, về cơ bản, có cách nào trong JavaScript để xác định kích thước phông chữ nào tôi nên sử dụng cho một số chuỗi của một phông chữ nhất định cho chiều rộng nhất định không? Không.Xác định chiều rộng của chuỗi trong canvas HTML5

Trả lời

26

Phương thức fillText() có đối số thứ tư tùy chọn, là chiều rộng tối đa tối đa để hiển thị chuỗi.

Tài liệu MDN cho biết ...

maxWidth

bắt buộc; chiều rộng tối đa cần vẽ. Nếu được chỉ định và chuỗi là được tính để rộng hơn chiều rộng này, phông chữ được điều chỉnh để sử dụng phông chữ có độ ngang theo chiều ngang hơn (nếu có sẵn hoặc nếu có một cách hợp lý có thể đọc được bằng cách mở rộng phông chữ hiện tại theo chiều ngang) hoặc phông chữ nhỏ hơn.

Tuy nhiên, tại thời điểm viết, đối số này không được hỗ trợ tốt qua trình duyệt, dẫn đến giải pháp thứ hai sử dụng measureText() để xác định kích thước của chuỗi mà không hiển thị.

var width = ctx.measureText(text).width; 

Dưới đây là làm thế nào tôi có thể làm điều đó ...

var canvas = document.getElementById('canvas'), 
    ctx = canvas.getContext('2d'); 

// Font sizes must be in descending order. You may need to use `sort()` 
// if you can't guarantee this, e.g. user input. 
var fontSizes = [72, 36, 28, 14, 12, 10, 5, 2], 
    text = 'Measure me!'; 

// Default styles. 
ctx.textBaseline = 'top'; 
ctx.fillStyle = 'blue'; 

var textDimensions, 
    i = 0; 

do { 
    ctx.font = fontSizes[i++] + 'px Arial'; 
    textDimensions = ctx.measureText(text);   
} while (textDimensions.width >= canvas.width); 

ctx.fillText(text, (canvas.width - textDimensions.width)/2, 10);​ 

jsFiddle.

Tôi có danh sách các kích thước phông chữ theo thứ tự giảm dần và tôi lặp qua danh sách, xác định xem văn bản được hiển thị có vừa với kích thước canvas hay không.

Nếu có, tôi sẽ căn chỉnh giữa văn bản. Nếu bạn phải có đệm ở bên trái và bên phải của văn bản (trông đẹp hơn), hãy thêm giá trị đệm vào textDimensions.width khi tính toán nếu văn bản phù hợp.

Nếu bạn có danh sách dài các kích thước phông chữ để thử, bạn nên sử dụng một số binary search algorithm. Tuy nhiên, điều này sẽ làm tăng tính phức tạp của mã của bạn.

Ví dụ: nếu bạn có 200 kích thước phông chữ, phép lặp tuyến tính thông qua các phần tử mảng sẽ là O (n).

Chẻ nhị phân phải là O (log n).

Dưới đây là ruột của hàm.

var textWidth = (function me(fontSizes, min, max) { 

    var index = Math.floor((min + max)/2); 

    ctx.font = fontSizes[index] + 'px Arial'; 

    var textWidth = ctx.measureText(text).width; 

    if (min > max) { 
     return textWidth; 
    } 

    if (textWidth > canvas.width) { 
     return me(fontSizes, min, index - 1); 
    } else { 
     return me(fontSizes, index + 1, max); 
    } 

})(fontSizes, 0, fontSizes.length - 1); 

jsFiddle.

+1

Liên kết tới tài liệu và/hoặc mã ví dụ có thể đẹp. – Phrogz

+0

@Phrogz Kiểm tra câu trả lời cập nhật. :) – alex

+0

Tôi nên biết bạn không nhận được 90k + rep bằng cách không theo dõi. :) Rất đẹp. – Phrogz

0

Tôi có mã tiếp theo và nó hoạt động hoàn hảo cho tôi. Có thể có một lỗi nhỏ nhưng tôi không cần phải có danh sách các kích thước phông chữ.Tôi chỉ nhận được chiều rộng với kích thước phông chữ và nếu nó quá lớn, tôi tính toán kích thước tỷ lệ tùy thuộc vào chiều rộng và chiều rộng của vải (50)

ctx.font = FONT_SIZE+"pt Verdana"; 
var textWidth = ctx.measureText(markText).width; 
if(textWidth > canvas.width - 50) { 
    ctx.font = parseInt(FONT_SIZE*(canvas.width-50)/textWidth)+"pt Verdana"; 
    textWidth = ctx.measureText(markText).width; 
} 
ctx.textBaseline = "middle"; 
ctx.fillStyle = "rgba(255,255,255,0.5)"; 
ctx.strokeStyle = "rgba(0,0,0,0.5)"; 
var xT = image.width/2 - textWidth/2; 
var yT = image.height/2; 
ctx.fillText(markText, xT, yT); 
ctx.strokeText(markText, xT, yT); 
Các vấn đề liên quan