Skip to content

Commit 56dc8b9

Browse files
authored
Merge pull request #297 from marcosmoura/improvement/mdIcon
add support for svg icons #99
2 parents b288937 + a2a4b7f commit 56dc8b9

File tree

5 files changed

+214
-10
lines changed

5 files changed

+214
-10
lines changed

docs/src/assets/icon-home.svg

Lines changed: 4 additions & 0 deletions
Loading

docs/src/assets/icon-menu.png

116 Bytes
Loading

docs/src/pages/components/Icon.vue

Lines changed: 106 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
<docs-component>
44
<div slot="description">
55
<p>A system icon, or UI icon, symbolizes a command, file, device, or directory. System icons are also used to represent common actions like trash, print, and save.</p>
6-
<p>You can see the full list of icons on the <a href="https://material.io/icons/" target="_blank" rel="noopener">Material Icons</a> website. Replace the spaces in the icon name by underscores (for example, <code>arrow back</code> becomes <code>arrow_back</code>)</p>
7-
6+
<p>You can see the full list of icons on the <a href="https://material.io/icons/" target="_blank" rel="noopener">Material Icons</a> website. Replace the spaces in the icon name by underscores (for example, <code>arrow back</code> becomes <code>arrow_back</code>).</p>
7+
<p>Alternatively you can use your PNG or SVG icons using the <code>md-src</code> property.</p>
8+
89
<p>The following classes can be applied to change the color palette:</p>
910
<ul class="md-body-2">
1011
<li><code>md-primary</code></li>
@@ -15,12 +16,44 @@
1516

1617
<div slot="api">
1718
<api-table name="md-icon">
18-
<p>No options available</p>
19+
<md-table slot="classes">
20+
<md-table-header>
21+
<md-table-row>
22+
<md-table-head>Name</md-table-head>
23+
<md-table-head>Description</md-table-head>
24+
</md-table-row>
25+
</md-table-header>
26+
27+
<md-table-body>
28+
<md-table-row>
29+
<md-table-cell>md-size-{type}</md-table-cell>
30+
<md-table-cell>Change the size of an icon. From 2x to 5x. Example: md-size-3x</md-table-cell>
31+
</md-table-row>
32+
</md-table-body>
33+
</md-table>
34+
35+
<md-table slot="properties">
36+
<md-table-header>
37+
<md-table-row>
38+
<md-table-head>Name</md-table-head>
39+
<md-table-head>Type</md-table-head>
40+
<md-table-head>Description</md-table-head>
41+
</md-table-row>
42+
</md-table-header>
43+
44+
<md-table-body>
45+
<md-table-row>
46+
<md-table-cell>md-src</md-table-cell>
47+
<md-table-cell><code>String</code></md-table-cell>
48+
<md-table-cell>The src of the image file. Can be SVG icons too!</md-table-cell>
49+
</md-table-row>
50+
</md-table-body>
51+
</md-table>
1952
</api-table>
2053
</div>
2154

2255
<div slot="example">
23-
<example-box card-title="Default">
56+
<example-box card-title="Google Font">
2457
<div slot="demo">
2558
<md-icon>home</md-icon>
2659
<md-icon class="md-primary">menu</md-icon>
@@ -38,6 +71,68 @@
3871
</div>
3972
</example-box>
4073

74+
<example-box card-title="Sizes">
75+
<div slot="demo">
76+
<md-icon>home</md-icon>
77+
<md-icon class="md-size-2x md-primary">home</md-icon>
78+
<md-icon class="md-size-3x md-accent">home</md-icon>
79+
<md-icon class="md-size-4x md-warn">home</md-icon>
80+
</div>
81+
82+
<div slot="code">
83+
<code-block lang="xml">
84+
&lt;md-icon&gt;home&lt;/md-icon&gt;
85+
&lt;md-icon class=&quot;md-size-2x md-primary&quot;&gt;home&lt;/md-icon&gt;
86+
&lt;md-icon class=&quot;md-size-3x md-accent&quot;&gt;home&lt;/md-icon&gt;
87+
&lt;md-icon class=&quot;md-size-4x md-warn&quot;&gt;home&lt;/md-icon&gt;
88+
</code-block>
89+
</div>
90+
</example-box>
91+
92+
<example-box card-title="Images">
93+
<div slot="demo">
94+
<md-layout :md-gutter="true">
95+
<md-layout>
96+
<strong class="md-body-2">SVG:</strong>
97+
<md-icon md-src="assets/icon-home.svg"></md-icon>
98+
<md-icon class="md-size-2x md-primary" md-src="assets/icon-home.svg"></md-icon>
99+
<md-icon class="md-size-3x md-accent" md-src="assets/icon-home.svg"></md-icon>
100+
<md-icon class="md-size-4x md-warn" md-src="assets/icon-home.svg"></md-icon>
101+
</md-layout>
102+
103+
<md-layout>
104+
<strong class="md-body-2">PNG:</strong>
105+
<md-icon md-src="assets/icon-menu.png">menu</md-icon>
106+
<md-icon class="md-size-2x" md-src="assets/icon-menu.png">menu</md-icon>
107+
<md-icon class="md-size-3x" md-src="assets/icon-menu.png">menu</md-icon>
108+
<md-icon class="md-size-4x" md-src="assets/icon-menu.png">menu</md-icon>
109+
</md-layout>
110+
</md-layout>
111+
</div>
112+
113+
<div slot="code">
114+
<code-block lang="xml">
115+
&lt;md-layout :md-gutter=&quot;true&quot;&gt;
116+
&lt;md-layout&gt;
117+
&lt;strong class=&quot;md-body-2&quot;&gt;SVG:&lt;/strong&gt;
118+
&lt;md-icon md-src=&quot;assets/icon-home.svg&quot;&gt;&lt;/md-icon&gt;
119+
&lt;md-icon class=&quot;md-size-2x md-primary&quot; md-src=&quot;assets/icon-home.svg&quot;&gt;&lt;/md-icon&gt;
120+
&lt;md-icon class=&quot;md-size-3x md-accent&quot; md-src=&quot;assets/icon-home.svg&quot;&gt;&lt;/md-icon&gt;
121+
&lt;md-icon class=&quot;md-size-4x md-warn&quot; md-src=&quot;assets/icon-home.svg&quot;&gt;&lt;/md-icon&gt;
122+
&lt;/md-layout&gt;
123+
124+
&lt;md-layout&gt;
125+
&lt;strong class=&quot;md-body-2&quot;&gt;PNG:&lt;/strong&gt;
126+
&lt;md-icon md-src=&quot;assets/icon-menu.png&quot;&gt;menu&lt;/md-icon&gt;
127+
&lt;md-icon class=&quot;md-size-2x&quot; md-src=&quot;assets/icon-menu.png&quot;&gt;menu&lt;/md-icon&gt;
128+
&lt;md-icon class=&quot;md-size-3x&quot; md-src=&quot;assets/icon-menu.png&quot;&gt;menu&lt;/md-icon&gt;
129+
&lt;md-icon class=&quot;md-size-4x&quot; md-src=&quot;assets/icon-menu.png&quot;&gt;menu&lt;/md-icon&gt;
130+
&lt;/md-layout&gt;
131+
&lt;/md-layout&gt;
132+
</code-block>
133+
</div>
134+
</example-box>
135+
41136
<example-box card-title="Themes">
42137
<div slot="demo">
43138
<md-icon md-theme="light-blue" class="md-primary">home</md-icon>
@@ -59,3 +154,10 @@
59154
</docs-component>
60155
</page-content>
61156
</template>
157+
158+
<style lang="scss" scoped>
159+
strong {
160+
margin: auto 16px auto 0;
161+
display: inline-block;
162+
}
163+
</style>

src/components/mdIcon/mdIcon.scss

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,46 @@
22

33
$icon-size: 24px;
44

5+
@mixin icon-size($size: $icon-size) {
6+
width: $size;
7+
min-width: $size;
8+
height: $size;
9+
min-height: $size;
10+
font-size: $size;
11+
}
12+
513
.md-icon {
6-
width: $icon-size;
7-
min-width: $icon-size;
8-
height: $icon-size;
9-
min-height: $icon-size;
14+
@include icon-size();
1015
margin: auto;
1116
display: inline-flex;
1217
align-items: center;
1318
fill: currentColor;
19+
text-rendering: optimizeLegibility;
1420
vertical-align: middle;
21+
22+
&.md-size-2x {
23+
@include icon-size($icon-size * 2);
24+
}
25+
26+
&.md-size-3x {
27+
@include icon-size($icon-size * 3);
28+
}
29+
30+
&.md-size-4x {
31+
@include icon-size($icon-size * 4);
32+
}
33+
34+
&.md-size-5x {
35+
@include icon-size($icon-size * 5);
36+
}
37+
38+
svg {
39+
width: 100%;
40+
height: 100%;
41+
}
42+
}
43+
44+
img.md-icon {
45+
user-select: none;
46+
-webkit-user-drag: none;
1547
}

src/components/mdIcon/mdIcon.vue

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
<template>
2-
<i class="md-icon material-icons" :class="[themeClass]">
2+
<i class="md-icon" :class="[themeClass]" v-html="svgContent" v-if="svgContent"></i>
3+
4+
<md-image class="md-icon" :class="[themeClass]" :md-src="imageSrc" v-else-if="imageSrc"></md-image>
5+
6+
<i class="md-icon material-icons" :class="[themeClass]" v-else>
37
<slot></slot>
48
</i>
59
</template>
@@ -10,6 +14,68 @@
1014
import theme from '../../core/components/mdTheme/mixin';
1115
1216
export default {
13-
mixins: [theme]
17+
props: {
18+
mdSrc: String
19+
},
20+
data: () => ({
21+
svgContent: null,
22+
imageSrc: null
23+
}),
24+
mixins: [theme],
25+
watch: {
26+
mdSrc() {
27+
this.svgContent = null;
28+
this.imageSrc = null;
29+
this.checkSrc();
30+
}
31+
},
32+
methods: {
33+
isImage(mimetype) {
34+
return mimetype.indexOf('image') >= 0;
35+
},
36+
isSVG(mimetype) {
37+
return mimetype.indexOf('svg') >= 0;
38+
},
39+
loadSVG() {
40+
const request = new XMLHttpRequest();
41+
const self = this;
42+
43+
request.open('GET', this.mdSrc, true);
44+
45+
request.onload = function() {
46+
const mimetype = this.getResponseHeader('content-type');
47+
48+
if (this.status >= 200 && this.status < 400 && self.isImage(mimetype)) {
49+
if (self.isSVG(mimetype)) {
50+
self.svgContent = this.response;
51+
window.setTimeout(() => {
52+
self.$el.children[0].removeAttribute('fill');
53+
}, 0);
54+
} else {
55+
this.loadImage();
56+
}
57+
} else {
58+
console.warn(`The file ${this.mdSrc} is not a valid image.`);
59+
}
60+
};
61+
62+
request.send();
63+
},
64+
loadImage() {
65+
this.imageSrc = this.mdSrc;
66+
},
67+
checkSrc() {
68+
if (this.mdSrc) {
69+
if (this.mdSrc.indexOf('.svg') >= 0) {
70+
this.loadSVG();
71+
} else {
72+
this.loadImage();
73+
}
74+
}
75+
}
76+
},
77+
mounted() {
78+
this.checkSrc();
79+
}
1480
};
1581
</script>

0 commit comments

Comments
 (0)