How do I make text gradient in canvas?

时间:2015-05-24 21:24:37

标签: javascript html5 canvas

I want to fill my text with a top from bottom gradient. I've followed four or five different tutorials on how to achieve this but it doesn't work.

I have two different dynamic text sources, something like this:

<div id="first-name" contentEditable="true">Olaf</div>
<div id="last-name" contentEditable="true">Smith</div>

I want to draw whatever the user writes on the canvas (after a button press). I know how to fetch the values, so let's ignore that part and focus on two things:

1) How to know how wide the content is to fill with a gradient.

2) How to fill anything with a gradient to begin with...

They say this is how you should do it:

var d_canvas = document.getElementById('canvas')
var context = d_canvas.getContext('2d')

var firstNameGradient = context.createLinearGradient(6,38,6,70) //no idea what values I should use

firstNameGradient.colorStop(0, '#eede85')
firstNameGradient.colorStop(1, '#fea700')

context.fillStyle = firstNameGradient

context.font = "bold 26px Tahoma"
context.fillText(firstName, 6, 38)

context.font = "bold 36px Tahoma"
context.fillText(lastName, whereFirstNameEnds, 38)

However, whatever values I try to fill with it doesn't work. In, fact nothing gets drawn in at all.

So I have no idea how to solve either 1) or 2). Does anyone know?

Edit: Just noticed an error:

TypeError: firstNameGradient.colorStop is not a function

3 个答案:

答案 0 :(得分:1)

context.createLinearGradient(6,38,6,70) //no idea what values I should use

This is defining a line from (x1, y1) to (x2, y2) which in turn describes the angle of the gradient. Seems OK here, might need some fine tuning.

Change these:

firstNameGradient.colorStop(0, '#eede85')
firstNameGradient.colorStop(1, '#fea700')

to use addColorStop() instead

firstNameGradient.addColorStop(0, '#eede85')
firstNameGradient.addColorStop(1, '#fea700')

To find the width (in pixels) you can use measureText() and the property width of the returned object:

var tw = firstNameGradient.measureText(firstName).width;

Text is by default drawn with y representing the baseline. You can change this by setting text-baseline to top - this makes it easier to provide the gradient line:

firstNameGradient.textBaseline = "top";

The specs do provide a way to get the height of a font as well, but no browers has yet implemented this part so you need to either guess or use a DOM element to measure height.

答案 1 :(得分:1)

You can use ctx.measureText(txt) to get the right width for the canvas. Here's an example that works as required:

var context = document
    .querySelector('canvas')
    .getContext('2d');
var pos = {x: 50, y: 50};
var txt = 'Hello!';
var txtHeight = 50; 

context.font = txtHeight + 'px Verdana';
var txtWidth = context.measureText(txt).width; 
var gradient = context.createLinearGradient(
    pos.x, pos.y, txtWidth, txtHeight);

gradient.addColorStop(0,"red");
gradient.addColorStop(1,"blue");
context.fillStyle = gradient;

context.fillText(txt,pos.x,pos.y);

And here's the demo on JSFiddle

答案 2 :(得分:0)

Sorry for being so naive as to use w3Schools, but If you reverse engineer this snippet you should get the job done:

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");

ctx.font="20px Georgia";
ctx.fillText("Hello World!",10,50);

ctx.font="30px Verdana";
// Create gradient
var gradient=ctx.createLinearGradient(0,0,c.width,0);
gradient.addColorStop("0","magenta");
gradient.addColorStop("0.5","blue");
gradient.addColorStop("1.0","red");
// Fill with gradient
ctx.fillStyle=gradient;
ctx.fillText("Big smile!",10,90);

Should you need any more advice check it out here


NOTE: Please, for the love of all things holy, don't use w3Schools, please try to use MDN

NOTE 2: I have no experience with canvas, so if I am making myself out to be an idiot, I am very sorry.