How to use a local font in Phaser 3? - phaser-framework

I have a font in a fonts/ directory. How do I load this into the game, then use it on a text object in my game? I haven't been able to find anything on using fonts in Phaser 3.

First use css to load your font(#fontface):
<style media='screen' type='text/css'>
#font-face {
font-family: font1;
src: url('media/yourfont.ttf');
font-weight:400;
font-weight:normal;
}
</style>
And then use a div to load your font:
<div style="font-family:font1; position:absolute; left:-1000px; visibility:hidden;">.</div>
Now you can put it in add it in your game:
this.add.text(190, 136, 'text', {
fontFamily: 'font1',
});

Pure JS Solution:
Here's a small function I made, which only requires the font name and url:
function loadFont(name, url) {
var newFont = new FontFace(name, `url(${url})`);
newFont.load().then(function (loaded) {
document.fonts.add(loaded);
}).catch(function (error) {
return error;
});
}
And use it like:
loadFont("mixolydian", "assets/fonts/mixolydian.ttf");
That's it! You can now use your custom font in Phaser. All you have to do is change the fontFamily value to your new font name (i.e. mixolydian).

Related

Empty Div Preventing Interaction with amCharts5 MapChart on Vue3

I decided to dip my toes in Vue and have had an idea for a website for a while which I'd like to use amCharts5 for.
I had some issues initially as all the info I could find was related to Vue2, but I think I've somewhat wrapped my head around Vue3 and its composition API.
The MapChart is created, however there is always a div slapped on top of it which prevent any interaction. If I delete this element via DevTools, the MapChart becomes interactive.
I've tried debugging this and commenting sections of the code out, regardless this div is always created. And I simply can't figure out if it's injected by Vue or if amCharts 5 is the culprit.
The highlighted element is the one I must delete for it to become interactive.
Here's how the component is setup;
<template>
<div class="testClass" ref="chartdiv">
</div>
</template>
<script setup lang="ts">
import * as am5 from "#amcharts/amcharts5";
import * as am5map from "#amcharts/amcharts5/map";
import am5geodata_worldLow from "#amcharts/amcharts5-geodata/worldLow";
import am5themes_Animated from '#amcharts/amcharts5/themes/Animated';
import { ref, onMounted, onUnmounted } from "vue";
const chartdiv = ref<HTMLElement | null>()
var root!: am5.Root;
onMounted(() => {
if (chartdiv.value) {
// Create the Root
var root = am5.Root.new(chartdiv.value);
// Setup the MapChart
var chart = root.container.children.push(
am5map.MapChart.new(root, {
panX: "rotateX",
panY: "rotateY",
projection: am5map.geoOrthographic(),
centerMapOnZoomOut: false
})
);
// Setup Animations
root.setThemes([
am5themes_Animated.new(root)
]);
// Create MapPolygons
var polygonSeries = chart.series.push(
am5map.MapPolygonSeries.new(root, {
geoJSON: am5geodata_worldLow
})
);
// Setup MapPolygon Styling
polygonSeries.mapPolygons.template.setAll({
tooltipText: "{name}",
fill: am5.color("#909090")
});
// Setup MapPolygon Hover Styling
polygonSeries.mapPolygons.template.states.create("hover", {
fill: am5.color("#FF0000"),
stroke: am5.color("#00FF00"),
strokeWidth: 2
});
polygonSeries.mapPolygons.template.events.on("click", function(event) {
//console.log("Clicked: {0}", event.target);
});
// Setup Background
var backgroundSeries = chart.series.unshift(
am5map.MapPolygonSeries.new(root, {})
);
backgroundSeries.mapPolygons.template.setAll({
fill: am5.color(0x2c84d0),
stroke: am5.color(0x2c84d0)
});
backgroundSeries.data.push({
geometry: am5map.getGeoRectangle(90, 180, -90, -180)
});
}
});
onUnmounted(() => {
if (root) {
root.dispose();
}
});
</script>
<style scoped>
.testClass {
width: 50vw;
height: 50vh;
}
</style>
When you create a Vite-powered Vue project, it automatically creates a bunch of CSS files for you. One of those is base.css.
Inside this file, you'll find these lines which causes all the headache;
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
position: relative;
font-weight: normal;
}
Removing those lines will fix the issue.

How to change static css file on API response in ReactJS

In my project i want to change the background-color and font of text. Both the properties are written in css file.
Project structure is:
|-myProject
|--public
|--src
|--package.json
All my css is written in public directory, and i have an api which give response of background-color and font. Now i want to change the properties background-color and font in css files according to api response.
Instead of trying to modify the base stylesheets, why not set these particular properties using the elements’ style attributes:
const divStyle = {
backgroundColor: /* Some color */,
fontFamily: /* Some font stack */,
};
function HelloWorldComponent() {
return <div style={ divStyle }>Hello World!</div>;
}
(adapted from the React docs)
I think the best way to do this would be to use inline style on the elements you want to change.
On api response -> set
const yourVar={
backgroundColor:##,
fontFamily:##
};
I believe that the answer from MTCoster is the best approach. depending on the structure of your app you could use the new Context API to make some sort of theme provider, so that you could pass custom styles that could be stored on your application state and that is loaded from your backend API. there are some tools that could help you integrate this feature more easily, like Styled-Components.
with Styled components you culd write something like:
import styled from 'styled-components'
import { YourComponentJSX } from '../somewhere'
// Wrap the component where you need your custom styles
const YourStyledComponent = styled(YourComponentJSX)`
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border-radius: 3px;
/* Color the border and text with theme.main */
// using the short-if to add a default color in case it is not connected to the ThemeProvider
color: ${props => props.theme.main ? props.theme.main : "palevioletred"};
border: 2px solid ${props => props.theme.main ? props.theme.main : "palevioletred"};
`;
// Define what props.theme will look like
const theme = {
main: "mediumseagreen"
};
render(
<div>
<ThemeProvider theme={theme}>
<App>
<YourStyledComponent>Themed</YourStyledComponent>
</App>
</ThemeProvider>
</div>
);
This way you could wrap your whole app and use custom styles saved on the app state that have been loaded from the backend and use them on really deeply nested ui components
*The code is a modification from the styled-component docs

MathJax is suddenly breaking lines

I'm using MathJax in Anki to make notes. When I use "Cloze" note type and put some MathJax in cloze deletion, the lines are suddenly broken, but outside cloze deletion MathJax renders as expected. Here is an example 1.
My front template:
{{cloze:Text}}
<script type="text/x-mathjax-config">
MathJax.Hub.processSectionDelay = 0;
MathJax.Hub.Config({
messageStyle: 'none',
showProcessingMessages: false,
tex2jax: {
inlineMath: [['$', '$']],
displayMath: [['$$', '$$']],
processEscapes: true
},
SVG: {
scale: (!!navigator.userAgent.match(/(mac)|(mobile)/i) ? 100 : 180)
}
});
</script>
<script type="text/javascript">
(function() {
if (window.MathJax != null) {
var card = document.querySelector('.card');
MathJax.Hub.Queue(['Typeset', MathJax.Hub, card]);
return;
}
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_SVG';
document.body.appendChild(script);
})();
</script>
And styling:
.card {
font-family: calibri;
font-size: 20px;
text-align: center;
color: black;
background-color: lightgray;
}
.cloze {
font-weight: bold;
color: blue;
}
How to fix this problem?
If you are using a WebKit-based browser (e.g., Safari or Chrome), then recent changes in WebKit may be the cause of your issue. The way MathJax checked for the available width for the math now causes unwanted line breaks in WebKit. (See this issue in the MathJax issue tracker.)
This was fixed in version 2.7.5, so you should upgrade to that. You are currently using 2.7.1, so changing
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_SVG';
to
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_SVG';
will do it. Changing it to
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-MML-AM_SVG';
will make sure you have the most current (2.x) version automatically (i.e., even though you are calling from 2.7.5, if there is an update to 2.7.6, you will be switched to that automatically).

Isolated styled-components with #font-face

I'm using https://github.com/styled-components/styled-components.
I'm trying to work out the best strategy for components that require #font-face. I want to make sure each component is independent of its context, so I'm defining font-family styles on each them. But if I use injectGlobal in multiple components, I get multiple #font-face rules for the same font.
Should I just define the #font-face rules in my ThemeProvider entry-point component and live with the fact that the desired font might not be loaded by the browser?
That's exactly why we made injectGlobal. If you take a look at our docs they say:
We do not encourage the use of this. Use once per app at most, contained in a single file. This is an escape hatch. Only use it for the rare #font-face definition or body styling.
So what I'd do is create a JS file called global-styles.js which contains this code:
// global-styles.js
import { injectGlobal } from 'styled-components';
injectGlobal`
#font-face {
font-family: 'My custom family';
src: url('my-source.ttf');
}
`
As you can see, all we do here is inject some global styling-in this case #font-face. The last thing necessary to make this work is to import this file in your main entry point:
// index.js
import './global-styles.js'
// More stuff here like ReactDOM.render(...)
This will mean your font-face is only injected once, but still all of your components have access to it with font-family: 'My custom family'!
Doing it this way will give you a flash-of-invisible-text (FOIT), but that has nothing to do with styled-components-it'd be the same if you were using vanilla CSS. To get rid of the FOIT requires a more advanced font loading strategy rather than just #font-faceing.
Since this has nothing to do with styled-components, I highly recommend watching these two Front End Center episodes to learn more about how to best do this: "Crafting Web Font Fallbacks" and "The Fastest Webfont Loader in the West"!
And on the other side of the same coin in Chrome:
do not use #font-face inside injectGlobal if using e.g. react-router.
You will get re-paint of all of you app on each newly loaded route.
And this is why:
Same font-files downloaded on each new route.
As soon as you include font-face in a separate .css file - problem solves as stated in the last comment in this github issue.
injectGlobal is deprecated. Use createGlobalStyle
import { createGlobalStyle } from 'styled-components'
export const GlobalStyle = createGlobalStyle`
body {
font-family: 'Muli', sans-serif;
h1 {
font-weight: 800;
font-size: 36px;
p {
font-size: 18px;
}
}
`;
Then you can use it in your App.js:
import { GlobalStyle } from './styles/global'
class App extends Component {
render() {
return (
<ThemeProvider theme={theme}>
<>
<GlobalStyle/>
<Container/>
</>
</ThemeProvider>
)
}
}
I agree
I get reloaded with
import { createGlobalStyle } from 'styled-components';
import { silver } from 'shared-components/themes/colors';
export default createGlobalStyle`
#font-face {
font-family: "Proxima Nova";
font-style: normal;
font-weight: 300;
font-display: swap;
src: url("/static/media/fonts/proxima_nova/ProximaNova_300.otf");
}
and react create app

Prevent Fancybox text from wrapping

I'm using Fancybox 2.1.3 to display some text when the page loads. The problem is that it's wrapping it onto two lines when I want it to all be on one line. I've tried the width, autoSize, and fitToView properties, and none of them are doing anything.
I'd prefer not to modify the fancybox css files, since I'm also using fancybox to display some images, and those are working properly.
Javascript
<script type='text/javascript'>
$(document).ready(function(){
// Activate fancyBox
$('.text').fancybox({
padding : 0,
closeBtn : false,
topRatio : 0.75,
helpers : {
overlay: {
css: {'background' : 'rgba(0, 0, 0, 0.0)'}
} // overlay
} // helpers
});
// Launch fancyBox on first element
$('.text').eq(0).trigger('click');
// Close automatically
setTimeout('parent.$.fancybox.close();', 10000);
});
HTML
<a href='#textid' class='text'></a>
<div style='display: none'>
<div id='textid'>The display text goes here.</div>
</div>
CSS
#textid
{
font-size: 40px;
color: red;
}
#textid {
font-size: 40px;
color: red;
white-space: nowrap;
}

Resources