Skip to content
Sasha Boginsky edited this page Sep 2, 2020 · 12 revisions

About

This wiki serves as a step by step guide for using our workflow, which is based on the Material Design documentation page for creating SVG Sprites.

Most of our icons are from the Material Design library, but since we store individual icons locally, they are not limited to it. Feel free to source icons from any library, while preferring Material Design for effortless consistency.

Adding an SVG Icon

Sourcing the Icon

The collection of Material Design icons can be found at material.io/tools/icons

  1. To use an icon, download it as SVG from their website. Presently, we keep our toolbar icons at 18px, so you should download the 24px version at 48dp.

  2. Drag the file into the assets/icons/svg directory.

  3. Rename the file if necessary: the name of the svg file will become the id attribute of the outputted svg code, so following these naming conventions will ensure consistency with the rest of our workflow: lowercase, snake_case, keep it short.

    • ex., Material Design's delete forever icon will download with the filename baseline-delete_forever-24px.svg. We renamed this to be delete_forever.svg.

    • Don't worry about adding or removing any attributes to the SVG code, as the next step will handle this for you.

Minifying and Compiling

We use the grunt-svgmin and grunt-svg-sprite plugins to minify the SVG files for the web and compile them into an SVG Sprite.

  1. Once you add your icon to the svg folder, run the following to have Grunt minify it (outputs a minified version to the assets/icons/svg-min folder) and re-compile the sprite sheet to include it (outputted as assets/icons/symbol/sprite.symbol.svg):
grunt icons
  • Grunt will also recompile an example HTML file assets/icons/symbol/sprite.symbol.html.

    • If you open it in your browser, you will find a visual overview of the icons in it.

    • For the next part, we will use the <svg> block filled with nested <symbol> elements in the "Inline <symbol> SVG sprite" section towards the top of this file.

Rendering the Icon

Injecting the <symbol> ref

  1. Copy the icon's <symbol> element from sprite.symbol.html and paste it into the chunk of <symbol>s in src/edit/tools/IconSet.js.
addSymbols: function() {
  this._svg +=
    '<symbol viewBox="0 0 18 18" id="border_clear"><path d="M5.25 3.75h1.5v-1.5h-1.5v1.5zm0 6h1.5v-1.5h-1.5v1.5zm0 6h1.5v-1.5h-1.5v1.5zm3-3h1.5v-1.5h-1.5v1.5zm0 3h1.5v-1.5h-1.5v1.5zm-6 0h1.5v-1.5h-1.5v1.5zm0-3h1.5v-1.5h-1.5v1.5zm0-3h1.5v-1.5h-1.5v1.5zm0-3h1.5v-1.5h-1.5v1.5zm0-3h1.5v-1.5h-1.5v1.5zm6 6h1.5v-1.5h-1.5v1.5zm6 3h1.5v-1.5h-1.5v1.5zm0-3h1.5v-1.5h-1.5v1.5zm0 6h1.5v-1.5h-1.5v1.5zm0-9h1.5v-1.5h-1.5v1.5zm-6 0h1.5v-1.5h-1.5v1.5zm6-4.5v1.5h1.5v-1.5h-1.5zm-6 1.5h1.5v-1.5h-1.5v1.5zm3 12h1.5v-1.5h-1.5v1.5zm0-6h1.5v-1.5h-1.5v1.5zm0-6h1.5v-1.5h-1.5v1.5z"/></symbol>' +
    '<symbol viewBox="0 0 18 18" id="border_outer"><path d="M9.75 5.25h-1.5v1.5h1.5v-1.5zm0 3h-1.5v1.5h1.5v-1.5zm3 0h-1.5v1.5h1.5v-1.5zm-10.5-6v13.5h13.5V2.25H2.25zm12 12H3.75V3.75h10.5v10.5zm-4.5-3h-1.5v1.5h1.5v-1.5zm-3-3h-1.5v1.5h1.5v-1.5z"/></symbol>' +
    '<symbol viewBox="0 0 18 18" id="crop_rotate"><path d="M5.603 16.117C3.15 14.947 1.394 12.57 1.125 9.75H0C.383 14.37 4.245 18 8.963 18c.172 0 .33-.015.495-.023L6.6 15.113l-.997 1.005zM9.037 0c-.172 0-.33.015-.495.03L11.4 2.888l.998-.998a7.876 7.876 0 0 1 4.477 6.36H18C17.617 3.63 13.755 0 9.037 0zM12 10.5h1.5V6A1.5 1.5 0 0 0 12 4.5H7.5V6H12v4.5zM6 12V3H4.5v1.5H3V6h1.5v6A1.5 1.5 0 0 0 6 13.5h6V15h1.5v-1.5H15V12H6z"/></symbol>' +
    '<symbol viewBox="0 0 18 18" id="delete_forever"><path d="M4.5 14.25c0 .825.675 1.5 1.5 1.5h6c.825 0 1.5-.675 1.5-1.5v-9h-9v9zm1.845-5.34l1.058-1.058L9 9.443l1.59-1.59 1.058 1.058-1.59 1.59 1.59 1.59-1.058 1.058L9 11.558l-1.59 1.59-1.058-1.058 1.59-1.59-1.597-1.59zM11.625 3l-.75-.75h-3.75l-.75.75H3.75v1.5h10.5V3h-2.625z"/></symbol>' +
    '<symbol ..... >' // your symbol element here
  ;
}

/* The '<symbol>'s in this set will later be injected via JavaScript during runtime. They serve as
   references and won't actually render until they are referenced with a corresponding '<use>' tag. */

Rendering the <symbol>

  1. To render the <symbol> as an icon, in the file where you're defining the tool (Leaflet.DistortableImage.ControlBar.js or Leaflet.DistortableImage.PopupBar.js),

    i. pass an additional svg: true option to options.toolbarIcon

    ii. pass the id attribute from the <symbol> element to the html option. For example:

var Deletes = L.EditAction.extend({
    initialize: function(map, overlay, options) {
      var use = 'delete_forever';

      options = options || {};
      options.toolbarIcon = {
        svg: true,      // passing this option allows you to pass an '{id}' to 'html', telling
        html: use,      // it to format it into valid svg code
        tooltip: 'Delete Images'
      };

// ... rest of action initialization code...

});

/* The API is still the same as the one specified by [Leaflet.toolbar](https://github.com/Leaflet/Leaflet.toolbar), 
   just extended with an `svg: true` option to include support for easy '<svg><use></use></svg>' element creation */

This will result in:

<li class="">
  <a class="leaflet-toolbar-icon" href="#" title="Delete Image">
    <svg class="ldi-icon ldi-delete_forever" role="img" focusable="false"> <!-- class="ldi-icon ldi-{id}" -->
      <use xlink:href="#delete_forever">                                   <!-- xlink:href="#{id}" -->
        #shadow-root (closed)  <!-- contents of the svg element rendered by the `<use>` referencing it -->
      </use>
    </svg>
  </a>
</li>

Styling

  1. Each icon's <svg> container will have the class ldi-icon, allowing us to easily set some default CSS properties on all our icons at once:
.ldi-icon {
  width: 18px;
  height: 18px;
  vertical-align: middle;
  fill: #0078A8;  /* the light blue-ish color that most of our toolbar icons are set in. */
}
  1. Each icon's <svg> container will also have the sub-class ldi-{id}, allowing us to easily override any properties set via the broader .ldi-icon declaration, or add new ones, for an individual icon:
.ldi-icon.ldi-delete_forever {
  fill: #c10d0d;  /* making our delete icon red */
}

Note that you cannot override any attributes present in the original svg file using CSS. In case we didn't remove one during the minify step that you would like to override, remove it from the original svg file and recompile before updating it in css.