Multiline / Wrap Text Support
Opened this issue · 2 comments
Rebsos commented
To get multiline support, add this:
MapLabel.prototype.wrapText = function(context, text, x, y, maxWidth, lineHeight) {
var words = text.split(' ');
var line = '';
for(var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = context.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
context.strokeText(line, x, y);
context.fillText(line, x, y);
line = words[n] + ' ';
y += lineHeight;
}
else {
line = testLine;
}
}
context.strokeText(line, x, y);
context.fillText(line, x, y);
};
In drawCanvas_, change
if (strokeWeight) {
ctx.lineWidth = strokeWeight;
ctx.strokeText(text, strokeWeight, strokeWeight);
}
ctx.fillText(text, strokeWeight, strokeWeight);
to
if (strokeWeight) {
ctx.lineWidth = strokeWeight;
}
this.wrapText(ctx, text, strokeWeight, strokeWeight, *ADD MAX WIDTH*, *ADD LINEHEIGHT*);
//e.g. this.wrapText(ctx, text, strokeWeight, strokeWeight, 200, 14);
This code is an extension of:
http://www.html5canvastutorials.com/tutorials/html5-canvas-wrap-text-tutorial/
patrickjaja commented
I had to implement this with \n for newline.
Replace:
if (strokeWeight) {
ctx.lineWidth = strokeWeight;
ctx.strokeText(text, strokeWeight, strokeWeight);
}
ctx.fillText(text, strokeWeight, strokeWeight);
with
if (strokeWeight) {
ctx.lineWidth = strokeWeight;
// ctx.strokeText(text, strokeWeight, strokeWeight);
}
// ctx.fillText(text, strokeWeight, strokeWeight);
var lineheight = 15;
var lines = text.split('\n');
for (var i = 0; i<lines.length; i++) {
ctx.fillText(lines[i], strokeWeight, strokeWeight + (i * lineheight));
if (strokeWeight) {
ctx.lineWidth = strokeWeight;
ctx.strokeText(lines[i], strokeWeight, strokeWeight + (i * lineheight));
}
}
a6o commented
modified from @patrickjaja
replace whole function with this
MapLabel.prototype.drawCanvas_ = function() {
var canvas = this.canvas_;
if (!canvas) return;
var style = canvas.style;
style.zIndex = /** @type number */ (this.get('zIndex'));
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = this.get('strokeColor');
ctx.fillStyle = this.get('fontColor');
ctx.font = this.get('fontSize') + 'px ' + this.get('fontFamily');
var strokeWeight = Number(this.get('strokeWeight'));
var text = this.get('text');
if (text) {
if (strokeWeight) {
ctx.lineWidth = strokeWeight;
}
var lineheight = this.get('fontSize');
var lines = text.split('\n');
maxText = "";
for (var i = 0; i < lines.length; i++) {
if(lines[i].length>maxText.length){
maxText = lines[i];
}
if (strokeWeight) {
ctx.lineWidth = strokeWeight;
ctx.strokeText(lines[i], strokeWeight, strokeWeight + (i * lineheight));
}
ctx.fillText(lines[i], strokeWeight, strokeWeight + (i * lineheight));
}
text = maxText;
var textMeasure = ctx.measureText(text);
var textWidth = textMeasure.width + strokeWeight;
style.marginLeft = this.getMarginLeft_(textWidth) + 'px';
// Bring actual text top in line with desired latitude.
// Cheaper than calculating height of text.
style.marginTop = '-'+lines.length*lineheight/2+"px";
}
};
whats different is
- line height adjusted with font size
- always vertical center
- horizontal center now possible (depending on the option)
- stroketext first, (or else actual text goes behind)