Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Vuetify custom icons #409

Merged
merged 3 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
- [Map Layers](map-layer-configuration.md)
- [Module Configuration](module-configuration.md)
- [Reusable Components](reusable-components.md)
- [Language packs](language-packs.md)
- [Language Packs](language-packs.md)
- [Custom Icons](custom-icons.md)
- [QGIS2Wegue](qgis_plugin.md)


Expand Down
34 changes: 34 additions & 0 deletions docs/custom-icons.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Custom icons

Wegue allows to inject custom icons inside Vuetify. Each icon to be injected must be defined in a separate file in the `app/icons` folder.

Those files should be standard `.js` files containing a default export of an `SVG` path definition. The name of the file, without the `.js` extension will be used to reference the icon afterwards.
To use a custom icon inside a component or a configuration file, you have to name it as `$vuetify.icons.myIconName`.

To integrate nicely inside Vuetify and keep the visual coherence of the whole framework, path coordinates should stay in the [0, 24] range in both horizontal and vertical directions.

## Example

Below is an example of an icon file which defines a W letter:


```js
export default 'M 23.16738,3.1894921 18.478314,20.810508 H 16.232499 L 12.802077,9.2605987 Q 12.579963,8.5695784 12.382529,7.8538789 12.209775,7.1134999 12.061699,6.5705557 11.938302,6.002932 11.913624,5.780818 11.888911,6.1016475 11.64215,7.1628586 11.395358,8.1993891 11.074526,9.3346366 L 7.7428218,20.810508 H 5.497006 L 0.83261985,3.1894921 H 3.1524731 L 5.8918748,13.949664 q 0.2961515,1.135248 0.4935859,2.196457 0.2221136,1.06121 0.3455113,1.999023 0.1233977,-0.962492 0.3701893,-2.09774 0.2467916,-1.135247 0.5676237,-2.221136 l 3.10959,-10.6367759 h 2.295174 l 3.232988,10.7108139 q 0.345511,1.135247 0.592302,2.270495 0.246792,1.135247 0.37019,1.974343 0.09872,-0.913134 0.320829,-1.974343 0.246792,-1.085889 0.542945,-2.245816 L 20.847525,3.1894921 Z'
```

If this icon file is named `app/icons/WLetter.js`, it can used inside a configuration file like this:

```json
"sample-module": {
"target": "toolbar",
"win": "floating",
"icon": "$vuetify.icons.WLetter"
}
```

And to use the same icon inside of a Vue component:


```vue
<v-icon color="teal darken-2">$vuetify.icons.WLetter</v-icon>
```
16 changes: 9 additions & 7 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
// (runtime-only or standalone) has been set in vue.config.js with runtimeCompiler.
import Vue from 'vue';
import Vuetify from 'vuetify/lib/framework';
import PortalVue from 'portal-vue'
import 'roboto-fontface/css/roboto/roboto-fontface.css'
import '@mdi/font/css/materialdesignicons.css'
import 'material-icons/iconfont/material-icons.css'
import '../node_modules/ol/ol.css';
import PortalVue from 'portal-vue';
import 'roboto-fontface/css/roboto/roboto-fontface.css';
import '@mdi/font/css/materialdesignicons.css';
import 'material-icons/iconfont/material-icons.css';
import 'ol/ol.css';
import WguApp from '../app/WguApp';
import UrlUtil from './util/Url';
import IconUtil from './util/Icon';
import LocaleUtil from './util/Locale';
import ObjectUtil from './util/Object';
import ColorThemeUtil from './util/ColorTheme'
import ColorThemeUtil from './util/ColorTheme';
import axios from 'axios';

Vue.use(Vuetify);
Expand Down Expand Up @@ -50,7 +51,8 @@ const createVuetify = function (appConfig) {
const preset = {
theme: ColorThemeUtil.buildTheme(appConfig.colorTheme),
icons: {
iconfont: 'mdiSvg'
iconfont: 'mdiSvg',
values: IconUtil.importIcons()
},
lang: {
current: LocaleUtil.getPreferredLanguage(appConfig),
Expand Down
56 changes: 56 additions & 0 deletions src/util/Icon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import ObjectUtil from './Object.js';

/**
* Icon related utility methods.
*/
const IconUtil = {

/**
* Import custom icons from 'app/icons'. Those icons will be included in an
* object ready to be injected inside Vuetify configuration options object under
* the icons['values'] property.
*
* @returns {Object} An object containing the imported icons.
* Key is the icon name, value contains the icon.
*/
importIcons () {
const icons = {};

try {
const pathIcons = IconUtil.importPathIcons();
ObjectUtil.mergeDeep(icons, pathIcons);
} catch (e) {
sronveaux marked this conversation as resolved.
Show resolved Hide resolved
}

return icons;
},

/**
* Import custom icons from 'app/icons/*.js'. Those icons will be included in an
* object ready to be injected inside Vuetify configuration options object under
* the icons['values'] property.
* The icons must be .js files with a default export which contains an SVG path.
*
* @returns {Object} An object containing icon SVG paths.
* Key is the icon name, value contains the path.
*/
importPathIcons () {
const moduleDefaultExtractor = (i) => i.default;
const testExp = /icons\/(?:.+\/)*([a-z0-9_-]+).js$/i;

const context = require.context(
'../../app',
true,
/icons\/(?:(?:.+)\/)*([a-z0-9_-]+).js$/i
);
const pathIcons = {};
for (const key of context.keys()) {
const iconName = key.match(testExp)[1];
pathIcons[iconName] = moduleDefaultExtractor(context(key));
}

return pathIcons;
}
}

export default IconUtil;
Loading