mirror of
https://github.com/iconify/iconify.git
synced 2025-01-07 07:34:22 +00:00
Render icons as background in SVG framework
This commit is contained in:
parent
7700ea1808
commit
f5bc7b4ea2
@ -45,12 +45,14 @@
|
||||
<body>
|
||||
<p>This is a simple HTML page with few icons.</p>
|
||||
<p>
|
||||
Icon that behaves like an image:
|
||||
Icons that behave like images:
|
||||
<span class="iconify" data-icon="bi:house-door"></span>
|
||||
<i class="iconify" data-icon="cif:ee"></i>
|
||||
</p>
|
||||
<p>
|
||||
Icon that behaves like an glyph (aligned to bottom of this text):
|
||||
<span class="iconify-inline" data-icon="bi:house-door"></span>
|
||||
<i class="iconify-inline" data-icon="cif:ee"></i>
|
||||
</p>
|
||||
<p>
|
||||
Changing icon color:
|
||||
|
119
packages/iconify/src/render/bg.ts
Normal file
119
packages/iconify/src/render/bg.ts
Normal file
@ -0,0 +1,119 @@
|
||||
import type { FullIconifyIcon } from '@iconify/utils/lib/icon';
|
||||
import { iconToSVG } from '@iconify/utils/lib/svg/build';
|
||||
import {
|
||||
elementDataProperty,
|
||||
IconifyElement,
|
||||
IconifyElementProps,
|
||||
IconifyElementData,
|
||||
} from '../scanner/config';
|
||||
import { applyClasses } from './classes';
|
||||
import { applyStyle } from './style';
|
||||
|
||||
const commonProps: Record<string, string> = {
|
||||
display: 'inline-block',
|
||||
};
|
||||
|
||||
const monotoneProps: Record<string, string> = {
|
||||
'-webkit-mask-image': 'var(--svg)',
|
||||
'-webkit-mask-repeat': 'no-repeat',
|
||||
'-webkit-mask-size': '100% 100%',
|
||||
'mask-image': 'var(--svg)',
|
||||
'mask-repeat': 'no-repeat',
|
||||
'mask-size': '100% 100%',
|
||||
'background-color': 'currentColor',
|
||||
};
|
||||
|
||||
const coloredProps: Record<string, string> = {
|
||||
'background-image': 'var(--svg)',
|
||||
'background-repeat': 'no-repeat',
|
||||
'background-size': '100% 100%',
|
||||
'background-color': 'transparent',
|
||||
};
|
||||
|
||||
/**
|
||||
* Render icon as inline SVG
|
||||
*/
|
||||
export function renderBackground(
|
||||
element: IconifyElement,
|
||||
props: IconifyElementProps,
|
||||
iconData: FullIconifyIcon
|
||||
): IconifyElement {
|
||||
// Generate data to render
|
||||
const renderData = iconToSVG(iconData, {
|
||||
...props.customisations,
|
||||
});
|
||||
|
||||
// Get old data
|
||||
const oldData = element[elementDataProperty];
|
||||
|
||||
// Generate SVG
|
||||
const renderAttribs = renderData.attributes;
|
||||
let renderAttribsHTML = '';
|
||||
for (const attr in renderAttribs) {
|
||||
const value = (
|
||||
iconData[attr] !== void 0 ? iconData[attr] : renderAttribs[attr]
|
||||
) as string;
|
||||
renderAttribsHTML += ' ' + attr + '="' + value + '"';
|
||||
}
|
||||
const html =
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"' +
|
||||
renderAttribsHTML +
|
||||
'>' +
|
||||
renderData.body +
|
||||
'</svg>';
|
||||
|
||||
// Add classes
|
||||
const classesToAdd: Set<string> = new Set(['iconify']);
|
||||
const iconName = props.icon;
|
||||
['provider', 'prefix'].forEach((attr: keyof typeof iconName) => {
|
||||
if (iconName[attr]) {
|
||||
classesToAdd.add('iconify--' + iconName[attr]);
|
||||
}
|
||||
});
|
||||
const addedClasses = applyClasses(
|
||||
element,
|
||||
classesToAdd,
|
||||
new Set(oldData && oldData.addedClasses)
|
||||
);
|
||||
|
||||
// Update style
|
||||
const isMonotone = renderData.body.indexOf('currentColor') !== -1;
|
||||
const url =
|
||||
'url("data:image/svg+xml,' +
|
||||
html
|
||||
.replace(/"/g, "'")
|
||||
.replace(/%/g, '%25')
|
||||
.replace(/#/g, '%23')
|
||||
.replace(/{/g, '%7B')
|
||||
.replace(/}/g, '%7D')
|
||||
.replace(/</g, '%3C')
|
||||
.replace(/>/g, '%3E') +
|
||||
'")';
|
||||
const newStyles: Record<string, string> = {
|
||||
'--svg': url,
|
||||
'width': renderAttribs.width,
|
||||
'height': renderAttribs.height,
|
||||
...commonProps,
|
||||
...(isMonotone ? monotoneProps : coloredProps),
|
||||
};
|
||||
if (renderData.inline) {
|
||||
newStyles['vertical-align'] = '-0.125em';
|
||||
}
|
||||
|
||||
const addedStyles = applyStyle(
|
||||
element,
|
||||
newStyles,
|
||||
oldData && oldData.addedStyles
|
||||
);
|
||||
|
||||
// Add data to element
|
||||
const newData: IconifyElementData = {
|
||||
...props,
|
||||
status: 'loaded',
|
||||
addedClasses,
|
||||
addedStyles,
|
||||
};
|
||||
element[elementDataProperty] = newData;
|
||||
|
||||
return element;
|
||||
}
|
@ -22,6 +22,7 @@ import {
|
||||
resumeObservingNode,
|
||||
stopObserving,
|
||||
} from '../observer';
|
||||
import { renderBackground } from '../render/bg';
|
||||
|
||||
/**
|
||||
* Flag to avoid scanning DOM too often
|
||||
@ -121,7 +122,8 @@ export function scanDOM(rootNode?: ObservedNode, addTempNode = false): void {
|
||||
paused = true;
|
||||
pauseObservingNode(observedNode);
|
||||
}
|
||||
renderInlineSVG(element, props, iconData);
|
||||
// renderInlineSVG(element, props, iconData);
|
||||
renderBackground(element, props, iconData);
|
||||
}
|
||||
|
||||
// Find all elements
|
||||
|
Loading…
Reference in New Issue
Block a user