I am trying to change the default font style of the canvas text to Press Start 2P
I have imported the url into a css file like so
#import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
.canvasClass{
font-family: 'Press Start 2P';
}
<Box className='canvasClass'>
<Canvas2/>
</Box>
and im trying to draw some text like this:
context.fillStyle = 'rgba(194,213,219,0.8)'
context.font = "42px Press Start 2P";
context.textAlign = 'center'
I can confirm that the font is being applied to the parent div, however I cannot apply my desired font to the canvas that is inside that div. Why would I have trouble applying the font to the canvas if it works with other text components in the same div?
EDIT:
I would like to add that I change font to Roboto (I'm assuming another Google font)
You need to wrap the font family name in quotes like you did in your CSS declaration.
context.fillStyle = 'rgba(194,213,219,0.8)'
context.font = "42px 'Press Start 2P'";
context.textAlign = 'center'
Also, wait for document.fonts.ready to be sure the external font has been loaded before you use it in your canvas.
(async () => {
await document.fonts.ready;
const canvas = document.querySelector("canvas");
const context = canvas.getContext("2d");
context.fillStyle = 'rgba(194,213,219,0.8)'
context.font = "42px 'Press Start 2P'";
context.textAlign = 'center';
context.textBaseline = 'middle';
context.fillText('Hello world', canvas.width/2, canvas.height/2);
})().catch(console.error);
#import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
.canvasClass{
font-family: 'Press Start 2P';
}
<div class=canvasClass>
<canvas width=500 height=150></canvas>
</div>
Related
I'm programmatically creating a very simple HTML Canvas on which I'm writing some text and then drawing an imported PNG Image.
I now want to "flatten" this canvas and export it out as a new Image.
It's working - but not 100%.
The issue is that while the text and background colors DO show up in the newly created and exported PNG, the image that was imported and drawn on the original canvas is NOT showing up.
Here's my code:
var newCanvas = document.createElement("canvas");
var context = newCanvas.getContext("2d");
// 1. Filling Canvas with Background Color:
context.fillStyle = "blue";
context.fillRect(0, 0, newCanvas.width, newCanvas.height);
// 2. Writing Text on the Canvas:
context.font = "30px Comic Sans MS";
context.fillStyle = "yellow";
context.textAlign = "center";
context.fillText("Hello World", newCanvas.width/2, newCanvas.height/2);
// 3. Adding a PNG to the Canvas:
let bgdImage = new Image();
bgdImage.src = "images/TilePattern1.png";
bgdImage.onload = function(){
context.drawImage(bgdImage, 0, 0, bgdImage.width, bgdImage.height);
}
// 4. Now I create a NEW Image object and set its contents to be
// all those elements I drew on my Canvas:
let finalImage = new Image();
finalImage.src = newCanvas.toDataURL();
So the resulting finalImage created by this code DOES have both the Background color and the Text I wrote - but it does NOT have the "TilePattern1.png" IMAGE I imported and drew on the canvas using .drawImage
What do I need to do to fix this?
(NOTE: the imported "TilePattern1.png" image DOES show up in the canvas drawn on the webpage; but it does NOT show up on the Image exported from the Canvas.)
My guess is that you have an error situation:
MDN
SecurityError
The canvas's bitmap is not origin clean; at least some of its contents
have or may have been loaded from a site other than the one from which
the document itself was loaded.
UPDATE: I have now run your code fully and the first problem is that you are not waiting for the image to be loaded before creating the base64 from the canvas so it doesn't have the image in it. The second problem is that if you wait for the image to be loaded and then attempt to create the base64 you will see something like this error:
Uncaught DOMException: Failed to execute 'toDataURL' on
'HTMLCanvasElement': Tainted canvases may not be exported.
Here's the code which waits for the image to load so you can try for yourself:
<body>
<img />
<script>
var newCanvas = document.createElement("canvas");
var context = newCanvas.getContext("2d");
// 1. Filling Canvas with Background Color:
context.fillStyle = "blue";
context.fillRect(0, 0, newCanvas.width, newCanvas.height);
// 2. Writing Text on the Canvas:
context.font = "30px Comic Sans MS";
context.fillStyle = "yellow";
context.textAlign = "center";
context.fillText("Hello World", newCanvas.width/2, newCanvas.height/2);
// 3. Adding a PNG to the Canvas:
let bgdImage = new Image();
bgdImage.src = "images/TilePattern1.png";
bgdImage.onload = function(){
context.drawImage(bgdImage, 0, 0, bgdImage.width, bgdImage.height);
// 4. Now I create a NEW Image object and set its contents to be
// all those elements I drew on my Canvas:
let finalImage = new Image();
finalImage.src = newCanvas.toDataURL();
// below added so we can see the canvas and the final image (if you comment out the above line)
document.body.appendChild(finalImage);
document.body.appendChild(newCanvas);
}
</script>
</body>
I want to be able to:
Get the Font Awesome 5 unicode character for any given Font Awesome class name (fas fa-check-circle, etc...)
Draw that unicode character to an html5 canvas
How would I go about doing this?
To get the correct unicode character and other important data for a Font Awesome 5 icon class and draw it onto an html5 canvas:
// create an icon with the Font Awesome class name you want
const i = document.createElement('i');
i.setAttribute('class', 'fas fa-check-circle');
document.body.appendChild(i);
// get the styles for the icon you just made
const iStyles = window.getComputedStyle(i);
const iBeforeStyles = window.getComputedStyle(i, ':before');
const fontFamily = iStyles.getPropertyValue('font-family');
const fontWeight = iStyles.getPropertyValue('font-weight');
const fontSize = '40px'; // just to make things a little bigger...
const canvasFont = `${fontWeight} ${fontSize} ${fontFamily}`; // should be something like: '900 40px "Font Awesome 5 Pro"'
const icon = String.fromCodePoint(iBeforeStyles.getPropertyValue('content').codePointAt(1)); // codePointAt(1) because the first character is a double quote
const ctx = myCanvas.getContext('2d');
ctx.font = canvasFont;
ctx.fillStyle = 'red';
ctx.textAlign = 'center';
ctx.fillText(icon, myCanvas.width / 2, myCanvas.height / 2);
When you do this, make sure the Font Awesome 5 font has actually loaded when you do the drawing. I made the mistake of only drawing once when I was testing and it resulted in only a box showing up. When the icon has loaded it should appear like this:
I am new to javascript and need to condense text drawn into a canvas using java script. w3schools suggests this can be done.
JavaScript syntax: object.style.fontStretch="expanded"
I noticed in css syntax however that neither font-stretch: condensed nor font-stretch: expanded appear to work and a comment in the example in w3schools also states no browsers support the font-stretch property. I am also aware this property will not work on just any font.
var can = document.getElementById("textCanvas");
var ctx = can.getContext("2d");
ctx.font = "120px Arial Bold Italic";
ctx.font.fontStretch="ultra-condensed"; //condensed”; // expanded”;
ctx.fillStyle = "red";
ctx.textAlign = "center";
ctx.fillText("NAME", 100, 100);
<canvas id="textCanvas" width="200" height="200" style="border: 1px solid black"></canvas>
Using font-stretch made no difference. I also tried font-kerning and font-size-adjust. How do I condense the font ?
ctx.font is a string. Setting fontStretch or anything else on it won't change it.
Now, the correct syntax is the same as CSS font property:
ctx.font = "[ [ <'font-style'> || <font-variant-css2> || <'font-weight'> || <font-stretch-css3> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | caption | icon | menu | message-box | small-caption | status-bar"`
So for setting only the font-stretch, the minimal is
ctx.font = "<font-stretch-css3> <'font-size'> <'font-family'>"
For example ctx.font = "ultra-condensed 18px LeagueMonoVariable"; would do.
However you'll face the same limitations as with CSS: browser support is limited, only a few fonts can be used, and in Chrome you need to define the font-stretch in the font-face declaration.
// This example seems to work only on Chrome, as does the MDN's example
const font = '18px "LeagueMonoVariable"';
document.fonts.load(font)
.then(() => {
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d');
['ultra-condensed', 'condensed', 'expanded', 'ultra-expanded'].forEach((stretch, i) => {
ctx.font = stretch + ' ' + font;
ctx.fillText('Hello ' + stretch + ' World', 10, i * 30 + 30);
});
});
/* borrowed from https://developer.mozilla.org/en-US/docs/Web/CSS/font-stretch */
/*
This example uses the League Mono Variable font, developed by
Tyler Finck (https://www.tylerfinck.com/) and used here under
the terms of the SIL Open Font License, Version 1.1:
http://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web
*/
#font-face {
src: url('https://tylerfinck.com/leaguemonovariable/LeagueMonoVariable.ttf');
font-family: 'LeagueMonoVariable';
font-style: normal;
font-stretch: 1% 500%;
}
<canvas id="canvas" width="500"></canvas>
Chrome output for the ones using an other browser.
Also note that apparently the percentage notation (n% font-size font-family) is not supported in Chrome from context's font.
Given all these limitations, it might be worth considering an alternative solution, and the best alternative is probably to have the variant font as a separate font-face and use it as simply as possible.
Promise.all([
document.fonts.load("18px Roboto"),
document.fonts.load("18px 'Roboto Condensed'")
])
.then(() => {
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d');
ctx.font = "18px Roboto";
ctx.fillText('Hello World', 10, 30);
ctx.font = "18px 'Roboto Condensed'";
ctx.fillText('Hello condensed World', 10, 60);
});
<link href="https://fonts.googleapis.com/css?family=Roboto|Roboto+Condensed&display=swap" rel="stylesheet">
<canvas id="canvas" width="500"></canvas>
I want to clear a stroked rectangle in certain canvas area. My initial thought was that I just need to call context.strokeRect function again with same parameters, with changing strokeStyle to transparent before. However it isn't working. Why and how can I fix it? Note that I want to only clear stroke (border) of rectangle, not everything inside.
Edit: I want to clear only border, not everything inside, so I can't use clearRect() method. Also I can't clear whole canvas and repaint it, because canvas contains animations.
JS fiddle: https://jsfiddle.net/47okok8s/
Example below has two canvas. The background just has some text. Then I fill the foreground canvas with "red" and use globalCompositeOperation "destination-out" to remove pixels. I also set alpha to 0.5 and half remove some pixels.
const ctxB = background.getContext("2d");
const ctxF = foreground.getContext("2d");
ctxB.textAlign = "center";
ctxB.textBaseline = "middle";
ctxB.font ="20px arial";
ctxB.fillText("Some Background text",150,25);
ctxB.fillText("Some Background text",150,75);
ctxB.fillText("Some Background text",150,125);
ctxF.lineJoin = "round";
ctxF.fillStyle = "red";
ctxF.fillRect(0,0,300,150);
ctxF.lineWidth = 8;
ctxF.globalCompositeOperation = "destination-out";
ctxF.strokeRect(25,25,250,100);
ctxF.fillRect(75,50,150,50);
ctxF.globalAlpha = 0.5;
ctxF.fillRect(65,40,170,70);
ctxF.globalCompositeOperation = "source-over";
canvas {
position : absolute;
top : 0px;
left: 0px;
}
<canvas id = "background"></canvas>
<canvas id = "foreground"></canvas>
I'm trying to recreate a Snapchat "snap" with HTML5 Canvas. The part that has me stumped is getting the font to look the same. The font Snapchat uses seems to be Helvetica, but I can't get my text to look the same as that of a real snap.
Here's my attempt of matching the font. I've drawn my text on top of an actual screenshot of a snap so it's easy to compare. You can edit the JavaScript variables to try to match the text (JSFiddle: http://jsfiddle.net/9RB88/1/).
HTML:
<img src='http://i.imgur.com/tivQ8xJ.jpg'>
<canvas width='640' height='1136'></canvas>
CSS:
img {display:none}
JavaScript:
//--- EDIT THESE ----------------
// text styles...
var fontFamily = 'Helvetica';
var fontSize = '35px';
var fontWeight = 'normal';
// http://css-tricks.com/almanac/properties/f/font-weight/
var onTop = false;
// set this to "true" to place our text on top of the real text (for more precise comparing)
var differentColours = false;
// draw our text/background different colours, making it easier to compare (use when "onTop" is "true")
// tweak where the text is drawn
var horOffset = 2;
var vertOffset = 0;
//-------------------------------
var can = document.getElementsByTagName('canvas')[0];
var c = can.getContext('2d');
c.fillStyle = 'white';
c.fillRect(0, 0, can.width, can.height);
var img = document.getElementsByTagName('img')[0];
c.drawImage(img, 0, 0);
var top;
if(onTop) top = 531;
else top = 450;
if(differentColours) c.fillStyle = 'orange';
else c.fillStyle = 'black';
c.globalAlpha = 0.6;
c.fillRect(0, top, can.width, 74);
c.globalAlpha = 1;
var text = 'Template example thingy $&#?! 123';
if(differentColours) c.fillStyle = 'red';
else c.fillStyle = 'white';
c.textAlign = 'center';
c.font = fontWeight + ' ' + fontSize + ' ' + fontFamily;
c.fillText(text, can.width/2 + horOffset, top + 50 + vertOffset);
JSFiddle: http://jsfiddle.net/9RB88/1/
It seems like one of the issues is letter spacing, but that's not possible to change in HTML5 Canvas.
What can I do?
Snapchat may embed a very specific variant or similar font to Helvetica. That doesn't mean the user loading the page (incl. on your own machine) will have that font installed on the system.
If the user doesn't have the font installed the browser will look for similar fonts, for example, it will use Arial on Windows and if that is not available use another sans-serif font. On Mac and Linux the same thing. This mean it will perhaps closely match but will not be the same font. If they don't use a web font the snap could have been taken on a different OS then you are using resulting in a different font being rendered.
Or in other words - when you specify "Helvetica" as font family the system will try to find a font in that family but it isn't given that Helvetica is the font you'll get. The browser will try to find the closest matching font available on the system in use.
You have to embed the very same font they are using as a web font otherwise there is no guarantee that the font will be the same.
To find out which font they are using (if any) open the stylesheets they're using.
My 2 cents..