I have this little script.
How can I center the text vertically? In another words, I need to bring out a variable from the function "wrapText" in order to use it to calculate the position of the text. Thanks a lot!
<canvas id="myCanvas" width="900" height="600" style="display:none;"></canvas>
<img id="canvasImg">
<script>
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function()
{
context.drawImage(imageObj, 0, 0);
}
imageObj.src = "img/imagea.jpg";
var myForm = document.getElementById('myForm');
myForm.addEventListener('submit', function(e)
{
var text = document.getElementById('area1').value;
if(text.lenght == 0)
{
alert("you forgot to put something");
}
function wrapText(context, text, x, y, maxWidth, lineHeight) {
var convtext = text.replace(/\n/g, ' |br| ');
var words = convtext.split(' ');
var line = '';
for(var n = 0; n < words.length; n++) {
var newline = false;
if (words[n].indexOf("|br|") > -1) newline = true;
var metrics = maxWidth;
var testWidth = maxWidth;
var testLine = line + words[n] + ' ';
if (context.measureText) {
metrics = context.measureText(testLine);
testWidth = metrics.width;
}
if ((testWidth > maxWidth && n > 0) || newline) {
context.fillText(line, x, y);
if (!newline) line = words[n] + ' ';
if (newline) line = "";
y += lineHeight;
} else {
line = testLine;
}
}
context.fillText(line, x, y);
}
var maxWidth = 500;
var lineHeight = 40;
var x = 100;
var y = 100;
context.font = "30pt HelveticaNeue-Light";
wrapText(context, text, x, y, maxWidth, lineHeight);
context.fillStyle = "#009bdc";
context.fillText("try", 100, 500);
var dataURL = canvas.toDataURL();
document.getElementById('canvasImg').src = dataURL;
e.preventDefault();
});
</script>
Here's how:
Modify wrapText to return the ending height value (so you can calculate the paragraph height).
Modify wrapText to optionally not draw (==optionally, not do fillText)
Run wrapText once in the no-draw mode to get the height of the wrapped paragraph.
Calculate a starting y that will produce a vertically centered paragraph: var centeringY = maxHeight/2 - paragraphHeight/2
Run wrapText again in the yes-draw mode using centeringY.
Example code and a Demo:
A paragraph of wrapped text that's vertically centered...
var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var maxWidth = 150;
var lineHeight = 20;
var x = 100;
var y = 100;
var text='It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness.';
context.font='12px verdana';
var height=wrapTextVCentered(context,text,x,y,maxWidth,lineHeight,true);
var y=(canvas.height-height)/2;
wrapTextVCentered(context,text,x,y,maxWidth,lineHeight,false);
context.strokeStyle='green';
context.strokeRect(x,y,maxWidth,height);
function wrapTextVCentered(context,text,x,y,maxWidth,lineHeight,measureOnly){
var height=0;
var convtext = text.replace(/\n/g, ' |br| ');
var words = convtext.split(' ');
var line = '';
context.textBaseline='top';
for(var n = 0; n < words.length; n++){
var newline = false;
if (words[n].indexOf("|br|") > -1) newline = true;
var metrics = maxWidth;
var testWidth = maxWidth;
var testLine = line + words[n] + ' ';
if (context.measureText){
metrics = context.measureText(testLine);
testWidth = metrics.width;
}
if ((testWidth > maxWidth && n > 0) || newline){
if(!measureOnly){ context.fillText(line, x, y); }
if (!newline) line = words[n] + ' ';
if (newline) line = "";
y += lineHeight;
height += lineHeight;
} else {
line = testLine;
}
}
if(!measureOnly){ context.fillText(line, x, y); }
height += lineHeight;
return(height);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<h4>Vertically centered paragraph on canvas</h4>
<canvas id="canvas" width=350 height=350></canvas>
Related
I am trying to solving one problem , I have a textarea which works fine and exporting text to canvas , but I don't know how to achieve the same effect and add background image option to this, it could be a static background image from the beginning, here is script .When i was trying to set background image via html , i had background image behind the text , but when i was exporting i had only text in my png.
var canvas = $('#canvas');
var ctx = canvas.get(0).getContext('2d');
canvas.width = 600;
canvas.height = 400;
$('#submit').click(function (e) {
e.preventDefault();
var text = $('#text').val(),
fontSize = parseInt($('#font-size').val()),
width = parseInt($('#width').val()),
lines = [],
line = '',
lineTest = '',
words = text.split(' '),
currentY = 0;
ctx.font = fontSize + 'px Arial';
for (var i = 0, len = words.length; i < len; i++) {
lineTest = line + words[i] + ' ';
// Check total width of line or last word
if (ctx.measureText(lineTest).width > width) {
// Calculate the new height
currentY = lines.length * fontSize + fontSize;
// Record and reset the current line
lines.push({ text: line, height: currentY });
line = words[i] + ' ';
} else {
line = lineTest;
}
}
// Catch last line in-case something is left over
if (line.length > 0) {
currentY = lines.length * fontSize + fontSize;
lines.push({ text: line.trim(), height: currentY });
}
// Visually output text
ctx.clearRect(0, 0, 500, 500);
for (var i = 0, len = lines.length; i < len; i++) {
ctx.fillText(lines[i].text, 0, lines[i].height);
}
var canvasCtx = document.getElementById("canvas").getContext('2d');
var img = document.getElementById("yourimg");
canvasCtx.drawImage(img,x,y);
var img = new Image();
img.onload = function(){
canvasCtx.drawImage(img,x,y);
};
img.src = "https://i.stack.imgur.com/7Whkw.png";
});
i have solved it!
var canvas = $('#canvas');
var ctx = canvas.get(0).getContext('2d');
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var img = new Image();
var height = 600;
var width = 600;
img.onload = function() {
context.save();
context.rect(0, 0, 200, 200);//Здесь первый 0=X
context.drawImage(img,0, 0,width,height);//Первый 0=X
context.restore();
};
img.src = 'https://i.stack.imgur.com/5uvJN.png';
$('#submit').click(function (e) {
e.preventDefault();
var text = $('#text').val(),
fontSize = parseInt($('#font-size').val()),
width = parseInt($('#width').val()),
lines = [],
line = '',
lineTest = '',
words = text.split(' '),
currentY = 0;
ctx.font = fontSize + 'px Arial';
for (var i = 0, len = words.length; i < len; i++) {
lineTest = line + words[i] + ' ';
// Check total width of line or last word
if (ctx.measureText(lineTest).width > width) {
// Calculate the new height
currentY = lines.length * fontSize + fontSize;
// Record and reset the current line
lines.push({ text: line, height: currentY });
line = words[i] + ' ';
} else {
line = lineTest;
}
}
// Catch last line in-case something is left over
if (line.length > 0) {
currentY = lines.length * fontSize + fontSize;
lines.push({ text: line.trim(), height: currentY });
}
// Visually output text
ctx.clearRect(0, 500, 500, 500);
for (var i = 0, len = lines.length; i < len; i++) {
ctx.fillText(lines[i].text, 410, lines[i].height);
}
});
one more question how i can set padding top for textarea text on canvas?
I found that to get the base64 data from a HTML canvas, you had to do canvas.toDataURL();. The problem with this, is that when it gives you the base64, it is scaled to the generic 300 x 150 canvas size, but the actual canvas is 600 x 100. Is there a way to strech the image to be 600 x 100, or to export it in the base64 as such? Thanks in advance!
I had the width and height defined in CSS not HTML, so the document wasn't registering the widths and heights.
Here is the updated code below:
<body>
<script>
var granmoe = 0;
var hai = 5;
var runnin = 0;
while(runnin != hai){
var can = document.createElement("canvas");
can.id = "canvasite"
can.style = "width: 150px; height: 100px; display:none;"
document.body.appendChild(can);
c = document.getElementById('canvasite'),
ctx = c.getContext('2d');
var x = 0
if(runnin == 0){
var endheight = c.height/2
}
var y = endheight;
var widd = 0
while(widd != c.width){
ctx.fillStyle = "rgba("+0+","+255+","+0+","+(255/255)+")";
ctx.fillRect( x, y, 1, 1 );
var ychan = Math.floor((Math.random() * 6) + 1);
if(ychan == 1){
var y=y+2
}else if(ychan == 2){
var y=y+1
}else if(ychan == 3){
var y=y-1
}else if(ychan == 4){
var y=y-2
}else{
var y=y
}
var hig = y
while(hig != c.height){
ctx.fillStyle = "rgba("+0+","+255+","+0+","+(255/255)+")";
ctx.fillRect( x, hig, 1, 1 );
var hig = hig+1
}
var widd = widd+1
var x=x+1
}
{
var endheight = y
var runnin = runnin+1
document.getElementById('canvasite').setAttribute('id','nAn')
var imgm = document.createElement("img");
imgm.src = c.toDataURL();
imgm.id = "imageitem"
imgm.style = "display:none;"
document.body.appendChild(imgm)
var xid = granmoe*(300*(1/hai));
if(granmoe == 0){
var cansfoo = document.createElement("canvas")
cansfoo.id = "fullimage";
cansfoo.style = 'width: '+(hai*150)+'px; height: 100px; display:none;'
document.body.appendChild(cansfoo);
}
var ci=document.getElementById("fullimage");
var ctxi=ci.getContext("2d");
var imd=document.getElementById("imageitem");
ctxi.drawImage(imd,xid,0,(300*(1/hai)),180);
//end
var granmoe=granmoe+1
document.getElementById("imageitem").setAttribute('id','non');
}
}
var base64 = ci.toDataURL();
var bass = document.createElement("img");
bass.src = base64
bass.id = "resiz"
bass.style = "display:none;"
document.body.appendChild(bass);
{
var resize = document.createElement("canvas")
resize.id = "resize";
resize.width = (hai*150);
resize.height = 100;
resize.style = 'display:none;'
document.body.appendChild(resize);
var re=document.getElementById("resize");
var res=re.getContext("2d");
var imag=document.getElementById("resiz");
res.drawImage(imag,0,50,(hai*150),50);
document.write(resize.toDataURL());
}
</script>
</body>
In a JS canvas, how can I place a text within a "box", Ora have it stay in a rectangle? I mean, I can place a text at x, y coordinate, but I'd like it to lay in a surround box x0, y0, x1, y1, so to have line breaks when the text is about to go out of the box, I can center it within the rectangle and possibly have the text scaled to fit as much as the box as possible.
Is there such a library to do so?
hope this will help you
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
function wrapText(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.fillText(line, x, y);
line = words[n] + ' ';
y += lineHeight;
}
else {
line = testLine;
}
}
context.fillText(line, x, y);
}
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var maxWidth = 400;
var lineHeight = 25;
var x = (canvas.width - maxWidth) / 2;
var y = 60;
var text = 'All the world \'s a stage, and all the men and women merely players. They have their exits and their entrances; And one man in his time plays many parts.';
context.font = '16pt Calibri';
context.fillStyle = '#333';
wrapText(context, text, x, y, maxWidth, lineHeight);
</script>
</body>
</html>
I'm using the below code to wrap the input to a textarea in a small web-based application I'm working on.
I would like the positioning of an element further down the page to be dependent on the number of lines the text takes up.
Can anyone suggest a means of determining the number of lines the text takes up, and defining it as a variable?
Thanks.
JavaScript
function wrapText(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.fillText(line, x, y);
line = words[n] + ' ';
y += lineHeight;
}
else {
line = testLine;
}
}
context.fillText(line, x, y);
}
var size = document.getElementById("bgSize").value;
var maxWidth = (canvas.width * (size / 100)) - (canvas.width * ((size / 100) * 0.15));
var alignment = document.getElementById("bgAlign").value;
if(alignment > 0){
var x = 1280-(size * 6.4);
}else{
var x = size * 6.4;
}
var y = 160;
var textContent = document.getElementById("textContent").value;
var text = textContent;
var colourInput = document.getElementById("bgColour").value;
if(colourInput > 0){
var textColour = '#fff';
}else{
var textColour = '#415055';
}
var fontSizeInput = 40;
var maxFontSize = 60;
var fontSize = fontSizeInput;
context.font = ''+fontSize+'pt gillsans';
context.fillStyle = textColour;
context.textAlign = "center";
var lineFactor = 1.35;
var lineHeight = fontSize * lineFactor;
wrapText(context, text, x, y, maxWidth, lineHeight);
I have a dom editor which a user can insert textbox and images. One of my requirements involve saving a snapshot of what is in the editor into an image. I did some research and there are some solutions, but they don't seem 100% foolproof. I've tried implementing a solution myself, clobbering code here and there:
function measureText(text, size, font) {
var lDiv = document.createElement('lDiv');
document.body.appendChild(lDiv);
lDiv.style.fontSize = size;
lDiv.style.fontFamily = font;
lDiv.style.position = "absolute";
lDiv.style.left = -1000;
lDiv.style.top = -1000;
lDiv.innerHTML = text;
var metrics = font.measureText(text, size.slice(0, size.length - 2));
var lResult = {
width: lDiv.clientWidth,
height: metrics.height + lDiv.clientHeight
};
document.body.removeChild(lDiv);
lDiv = null;
return lResult;
}
function wrapText(context, item) {
var words = item.text.split(' ');
var line = '';
var x = parseInt(item.x);
var y = parseInt(item.y);
var width = parseInt(item.width.slice(0, item.width.length - 2));
var height = parseInt(item.height.slice(0, item.height.length - 2));
var fontsize = parseInt(item.size.slice(0, item.size.length - 2));
var font = new Font();
font.onload = function () {
context.save();
context.beginPath();
context.rect(x, y, width, height);
context.clip();
context.font = item.size + " " + item.font;
context.textBaseline = "top";
for (var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = measureText(testLine, item.size, font);
var testWidth = metrics.width;
if (testWidth > width && n > 0) {
console.log("Drawing '" + line + "' to " + x + " " + y);
context.fillText(line, x, y);
line = words[n] + ' ';
y += metrics.height
}
else {
line = testLine;
}
}
context.fillText(line, x, y);
context.restore();
}
font.fontFamily = item.font;
font.src = font.fontFamily;
}
this.toImage = function () {
console.log("testing");
var canvas = document.getElementById("testcanvas");
canvas.width = 400;
canvas.height = 400;
var ctx = canvas.getContext("2d");
var imageObj = new Image();
var thisService = this;
imageObj.onload = function () {
ctx.drawImage(imageObj, 0, 0, 400, 400);
for (var i = 0; i < thisService.canvasItems.length; i++) {
var component = thisService.canvasItems[i];
if (component.type == "textbox") {
var x = component.x.slice(0, component.x.length - 2);
var y = component.y.slice(0, component.y.length - 2);
var w = component.width.slice(0, component.width.length - 2);
var h = component.height.slice(0, component.height.length - 2);
wrapText(ctx, component);
}
}
};
imageObj.src = this.base.front_image;
}
Somehow I believe I almost made it, however from the ,
There seems to be some positioning/font placement issues, just a few pixels lower. The top 1 a div with no padding, (its model can be seem on the panel on the left), while the bottom one is the canvas.
I wish to have a 1 to 1 accurate mapping here, can anyone enlighten what might be the problem?
As far as I know its not possible to draw HTML into a canvas with 100% accuracy due to the obvious "security" reasons.
You can still get pretty close using the rasterizeHTML.js library.
It uses a SVG image containing the content you want to render. To draw HTML content, you'd use a element containing the HTML, then draw that SVG image into your canvas.