Manual:ResourceLoaderImageModule.php

From MediaWiki.org
(Redirected from ResourceLoader/Images)
Jump to navigation Jump to search

Embedded images[edit]

When you reference images in CSS or LESS files, you can indicate that ResourceLoader should automatically create inline data URIs for them. See @embed documentation.

Generating icons from SVG files[edit]

SVG (Scalable Vector Graphics) files are preferable to raster images because they are resolution-independent. However, browser support for them varies, so you need to provide a raster image as a fallback.

ResourceLoaderImageModule:

  • abstracts the implementation of SVG and fallback images in CSS
  • generates the fallback image on-the-fly from the SVG
  • intelligently chooses the appropriate image for right-to-left and different languages according to your specification
  • generates multiple colored images from a single SVG according to your specification.

To use it, in your module definition (in extension.json or skin.json or the old PHP entry point), you specify at a minimum:

  • class: "ResourceLoaderImageModule"
  • images: a set of "name": "path/to/icon.svg" file mappings
  • a specification for the name of the CSS rule for each image, either
    • a prefix to put in front of each name as .prefix-name, or
    • selector, a CSS selector name which includes the placeholder {name}

ResourceLoader generates a CSS class rule for each image that specifies the icon as the background-image property for a selector and includes a fallback raster image.

For example, the Gather extension's extension.json includes

        "ext.gather.menu.icon": {
            "position": "top",
            "class": "ResourceLoaderImageModule",
            "selector": ".mw-ui-icon-{name}:before",
            "images": {
                "collections-icon": "resources/ext.gather.menu.icon/plus.svg"
            }           
        },

When you request or depend on the ext.gather.menu.icon ResourceLoader module, it generates a CSS file that specifies the SVG as the background-image for the selector .mw-ui-icon-collections-icon:before. In other words the response to https://en.wikipedia.org/w/load.php?modules=ext.gather.menu.icon&only=styles (reformatted for clarity) is:

.mw-ui-icon-collections-icon:before {
    background-image: url(https://en.wikipedia.org/w/load.php?modules=ext.gather.menu.icon&image=collections-icon&format=rasterized&lang=en);
    background-image: linear-gradient(transparent,transparent),url(data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22...);
    background-image: -o-linear-gradient(transparent,transparent),url(https://en.wikipedia.org/w/load.php?modules=ext.gather.menu.icon&image=collections-icon&format=rasterized&lang=en)
}

Recent browsers will use the SVG embedded as a data URI, and others will fall back to requesting the rasterized background image, which ResourceLoader generates on-the-fly by converting the SVG to a PNG.

SVG conversion to raster[edit]

To convert the SVG original to a PNG raster image, ResourceLoader uses the same $wgSVGConverter that you configure to create raster images of SVG files uploaded to the wiki (as in File:Example.svg). On Wikimedia wikis this is rsvg, which has some extra optimizations, but any converter will work.

Identifying different icons[edit]

If you need to use a different icon for right-to-left languages,, you can specify different icons in the images key. Instead of a simple "name": "path/to/icon.svg" mapping for each icon name, for each name you provide a file key with different icons for ltr and rtl. ResourceLoader determines the text direction according to the lang parameter to the load request, and uses the appropriate icon. For example (in PHP):

    'mobile.swipe.images' => array(
        'prefix' => 'mw-ui',
        'images' => array(
            'previous' => array(
                'file' => array(
                    'ltr' => 'images/icons/move-rtl.svg',
                    'rtl' => 'images/icons/move-ltr.svg',
                ),
            ),
            ...
        ),

the CSS rule for .mw-ui-previous will use the appropriate SVG as the background image according to the direction of lang.

Similarly, if the icon is different in different languages (such as 'B' for Bold becomes 'G' in French), you can specify in the file key a default icon and then icons for particular languages. For example (in JSON):

        "bold": { "file": {
            "default": "images/icons/bold-a.svg",
            "lang": {
                "ar": "images/icons/bold-arab-ain.svg",
                "be": "images/icons/bold-cyrl-te.svg",
                "cs,en,he,ml,pl": "images/icons/bold-b.svg",
                "da,de,hu,ksh,nn,no,sv": "images/icons/bold-f.svg",
                "es,gl,pt": "images/icons/bold-n.svg",
                "eu,fi": "images/icons/bold-l.svg",
                "fa": "images/icons/bold-arab-dad.svg",
                "fr,it": "images/icons/bold-g.svg",
                ...
        } },

Variants[edit]

The MediaWiki theme uses color to convey meaning, for example "destructive" operations appear red, and "progressive" operations that are part of a sequence of steps appear blue. See Intention colors in the Living style guide. Or you may want to define a gray variant, or an inverted white-on-black icon.

Instead of creating a set of nearly-identical icons for each color, ResourceLoader can generate these different icons as variants, as both SVG and raster images, from a single source SVG,


The way you indicate what variants to provide is by specifying a variants key and for each variant, give its color. Then rather than a simple selector key, you specify selectorWithVariant which has a {variant} placeholder as well as a {name} placeholder; you can also provide a selectorWithoutVariant key. ResourceLoaderImageModule creates a CSS rule for each variant of each name, and applies the color of the variant to the SVG. (To do so the ResourceLoaderImage class wraps the SVG with a new group and sets the fill color.)

In order to make a given image available in a given variant, either the variant must be defined as global, or the image definition must specify allowed variants. Since each variant requires some additional data to be sent to user's browser, variants shouldn't be made global unless you actually use each of the images in each of the variants.

For example, the MobileFrontend defines the following module, using global variants:

"skins.minerva.icons.images.variants": {
	"selectorWithoutVariant": ".mw-ui-icon-{name}:before",
	"selectorWithVariant": ".mw-ui-icon-{name}-{variant}:before",
	"class": "ResourceLoaderImageModule",
	"prefix": "mw-ui",
	"variants": {
		"gray": {
			"color": "#BBB",
			"global": true
		},
		"invert": {
			"color": "#FFF",
			"global": true
		}
	},
	"images": {
		"clock": "resources/skins.minerva.icons.images.variants/clock.svg",
		"arrow": "resources/skins.minerva.icons.images.variants/arrow.svg"
	}
},

The above is equivalent to the following, without global variants:

"skins.minerva.icons.images.variants": {
	"selectorWithoutVariant": ".mw-ui-icon-{name}:before",
	"selectorWithVariant": ".mw-ui-icon-{name}-{variant}:before",
	"class": "ResourceLoaderImageModule",
	"prefix": "mw-ui",
	"variants": {
		"gray": {
			"color": "#BBB"
		},
		"invert": {
			"color": "#FFF"
		}
	},
	"images": {
		"clock": {
		    "file": "resources/skins.minerva.icons.images.variants/clock.svg",
		    "variants": [ "gray", "invert" ]
		},
		"arrow": {
		    "file": "resources/skins.minerva.icons.images.variants/arrow.svg",
		    "variants": [ "gray", "invert" ]
		},
	}
},

Note: if you only need one color of an icon that is different from the variant you can use the defaultColor.

"skins.minerva.icons.images.variants": {
	"selector": ".mw-ui-icon-{name}:before",
	"class": "ResourceLoaderImageModule",
	"defaultColor": "#FFF",
	"images": {
		"clock": "resources/skins.minerva.icons.images.variants/clock.svg"
	}
},

Loading data from separate JSON file[edit]

ResourceLoaderImageModule can also load the module definition (all options except the required "class": "ResourceLoaderImageModule") from a separate JSON file, which can be convenient if the list gets too long. Any options in the module definition override options from the JSON file.

extension.json icons/badgeicons.json
"ext.echo.badgeicons": {
	"class": "ResourceLoaderImageModule",
	"data": "icons/badgeicons.json",
	"selector": ".mw-echo-icon-{name}"
}
{
	"images": {
		"bell": {
			"file": "icons/bell.svg"
		},
		"tray": {
			"file": "icons/tray.svg"
		}
	}
}

Note that the paths to images in the separate JSON file must be the same as if they were in extension.json – they are not relative to that file.

SVG coding conventions and best practices[edit]

  • SVGs need to be optimized to reduce their size and thus the size of ResourceLoader responses, just as you optimize raster images.
  • In order for ResourceLoader variant color generation to work, the SVG should not set the color explicitly (f.e. via fill or style for any shape, otherwise that color won't change.

OOUI images[edit]

The MediaWiki theme of OOUI defines dozens of icons: see icons in the OOUI Demos and Iconography in the Living style guide. When clients request OOUI support with $out->enableOOUI(), it adds ResourceLoader resources such as 'oojs-ui.styles.icons' to the page. Since phab:T92551 MediaWiki generates the CSS definition of these icons from SVG. To further reduce boilerplate code, it generates sets of icons from JSON files containing the icon information, using a specialized class ResourceLoaderOOUIImageModule.

Using OOUI images[edit]

If you want to use one of these icons in your own code,

  1. find the icon you want in the demos or style guide above, e.g. the "block" icon
  2. see if it has a variant with the intention color you want, if any, e.g. destructive block. (If the icon is not available in the color you want, you have to access the SVGs and create your own ResourceLoaderImageModule.)
  3. find the image set that contains it; in this case it's in the "moderation" set.
  4. express a dependency on the ResourceLoader module for the image set 'oojs-ui.styles.icons-setname'; in this case it's 'oojs-ui.styles.icons-moderation'

Now that the necessary styles will be loaded, you can use the icon:

  1. apply the classes mw-ui-icon and one of mw-ui-icon-element or mw-ui-icon-before to the div or span where you want icons
  2. apply the class mw-ui-icon-name or mw-ui-icon-name-variant to choose the icon to use; in this case it's mw-ui-icon-block-destructive.

The icons can also be shown using OOUI widgets:

  1. load OOUI: see OOUI/Using OOUI in MediaWiki
  2. display an IconWidget:
    • PHP:
      $this->getOutput()->addHTML( new OOUI\IconWidget( [
          'icon' => 'block',
          'flags' => 'destructive',
      ] ) );
      
    • JavaScript:
      $( 'body' ).append( new OO.ui.IconWidget( {
          icon: 'block',
          flags: 'destructive'
      } ).$element );
      

See also[edit]

  • Design/WikiFont packages similar icons as a font. This is used by the Android and iOS Wikipedia applications, which can rely on well-defined operating system support for per-application fonts.