Module not found on SVG files in react - html

I have this line of html in my react that keeps giving me this error
GET http://localhost:3000/icons.svg 404 (Not Found)
<svg className="olymp-menu-icon">
<use xlinkHref="./icons.svg#olymp-menu-icon" />
</svg>
And my directory is setup as follows
HTML Pages (Main directory)
Login.js (Currently working on this component)
icons.svg (Inside same directory as Login.js)
And here is a snippet from my icons.svg
<symbol id="olymp-menu-icon" viewBox="0 0 41 32">
<title>menu-icon</title>
<path d="M4.571 0h-4.571v4.571h4.571v-4.571zM9.143 0v4.571h32v-4.571h-32zM13.714 13.714h-13.714v4.571h13.714v-4.571zM18.286 13.714v4.571h4.571v-4.571h-4.571zM27.429 18.286h13.714v-4.571h-13.714v4.571zM0 32h32v-4.569h-32v4.569zM36.571 32h4.571v-4.569h-4.571v4.569z"></path>
</symbol>

You can do this.
create-react-app example: https://github.com/facebook/create-react-app/blob/26f701fd60cece427d0e6c5a0ae98a5c79993640/packages/react-scripts/fixtures/kitchensink/src/features/webpack/SvgComponent.js
// in Login.js
import { MenuIcon } from './icons.svg';
// use
<MenuIcon id="icon" />
you apply this.
https://github.com/FWeinb/babel-plugin-named-asset-import
https://github.com/facebook/create-react-app/blob/4a87838f527a00be6af42099546ff5d3adf63a6a/packages/react-scripts/config/webpack.config.dev.js#L238-L249

Related

Store html expression in variable (Angular)

I am trying to save space coding and I have 8 images that are derived from html markup
(i.e: <svg></svg>)
I can use *ngIf based on my value I am correlating each of these images with but this solution seems inefficient. I can't seem to find another solution online. Ideally I would like to save these html expressions in variables in a service, call the service, and inject the html expression into my html file.
Any ideas?
EDIT: You can actually just create an icon file (i.e. https://icoconvert.com/)and avoid the lengthy code.
If your goal is simply to save space in your component's html file, one solution is to use the Angular Material mat-icon component, which supports SVGs. This would allow you to inject a specific SVG into a component by simply adding mat-icon with the appropriate svgIcon input variable (e.g. <mat-icon svgIcon="left-arrow">) as well as change the displayed SVG icon by simply updating the svgIcon input variable.
edit: angular 8 also supports using a .svg file as a component's template
Another option would be for you to create a new component for each SVG.
e.g.
import { Component } from '#angular/core';
#Component({
selector: 'app-custom-svg',
template: `
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="64" height="64" viewBox="0 0 224 224" style=" fill:#000000;"><g fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M0,224v-224h224v224z" fill="none"></path><g id="Layer_1"><g><g fill="#ff5576"><g><g><path d="M145.425,109.375l34.3,-17.15c-9.275,-40.25 -46.55,-70 -90.3,-67.55c-43.75,2.45 -79.275,37.625 -82.25,81.2c-1.4,21.35 4.725,41.125 16.1,57.05c3.85,5.425 10.15,8.575 16.975,8.575h85.75v-30.8c0,-13.3 7.525,-25.375 19.425,-31.325z"></path></g></g></g><g fill="#ffffff"><g><g><circle cx="13" cy="48" transform="scale(1.75,1.75)" r="3"></circle></g></g></g><g fill="#ff5576"><g><g><path d="M121.45,123.2c-0.875,0 -1.75,-0.175 -2.625,-0.7c-2.45,-1.4 -3.325,-4.725 -1.925,-7.175c4.9,-8.575 12.25,-15.575 21.35,-20.125l36.05,-17.675c2.625,-1.225 5.775,-0.175 7,2.45c1.225,2.625 0.175,5.775 -2.45,7l-35.875,17.675c-7.175,3.5 -12.95,9.1 -16.8,15.925c-1.05,1.575 -2.8,2.625 -4.725,2.625z"></path></g></g></g><g fill="#ffffff"><g><g><circle cx="54" cy="98" transform="scale(1.75,1.75)" r="18"></circle></g></g></g><g fill="#ffffff"><g><g><path d="M32.9,71.05c-1.05,0 -2.275,-0.35 -3.15,-1.05c-2.275,-1.75 -2.8,-5.075 -1.05,-7.35c14.525,-19.425 36.925,-31.5 61.075,-32.725c2.8,-0.175 5.425,2.1 5.6,4.9c0.175,2.975 -2.1,5.425 -4.9,5.6c-21.175,1.225 -40.6,11.55 -53.375,28.7c-1.05,1.225 -2.625,1.925 -4.2,1.925z"></path></g></g></g><path d="M149.975,106.925c-1.225,-2.625 -4.375,-3.675 -7,-2.275c-13.65,6.825 -22.225,20.65 -22.225,36.05v5.25c-6.65,-6.825 -15.925,-11.025 -26.25,-11.025c-10.85,0 -21,4.725 -28,12.95c-1.925,2.275 -1.575,5.6 0.525,7.35c1.05,0.875 2.275,1.225 3.325,1.225c1.4,0 2.975,-0.7 4.025,-1.925c5.075,-5.95 12.25,-9.275 19.95,-9.275c14.525,0 26.25,11.725 26.25,26.25c0,2.975 2.275,5.25 5.25,5.25c2.975,0 5.25,-2.275 5.25,-5.25c0,-1.75 0,-30.8 0,-30.8c0,-11.375 6.3,-21.525 16.45,-26.6c2.8,-1.4 3.85,-4.55 2.45,-7.175z" fill="#ff5576"></path><path d="M213.5,144.025c-2.275,-1.575 -5.075,-2.275 -7.7,-2.275v0c-9.275,0 -22.75,0 -34.825,0l-25.55,-26.425c0.7,-0.525 1.575,-0.875 2.275,-1.4l34.3,-17.15c2.1,-1.05 3.325,-3.5 2.8,-5.95c-10.15,-43.925 -50.4,-74.025 -95.725,-71.4c-46.55,2.625 -84,39.725 -87.15,86.1c-1.4,21.875 4.375,42.7 17.15,60.375c4.9,6.65 12.6,10.675 21,10.85c2.625,0 4.9,-1.75 5.425,-4.375c0.525,-3.325 -1.925,-6.125 -5.25,-6.125c-5.075,0 -9.8,-2.45 -12.6,-6.475c-11.2,-15.575 -16.45,-34.125 -15.225,-53.55c2.8,-41.3 36.05,-74.025 77.35,-76.475c38.675,-2.1 73.325,22.575 83.825,59.5l-30.625,15.225c-10.85,5.425 -18.55,15.225 -21.175,27.125c-0.7,2.8 0.875,5.775 3.675,6.475c2.975,0.7 5.775,-1.05 6.475,-4.025c1.05,-4.375 2.975,-8.575 5.6,-12.075l18.9,19.775c-2.975,0 -5.6,0 -7.7,0c-2.975,0 -5.25,2.275 -5.25,5.25c0,2.975 2.275,5.25 5.25,5.25c4.2,0 10.675,0 17.85,0l13.65,14h-85.575c-2.625,0 -4.9,1.75 -5.425,4.2c-0.7,3.325 1.925,6.3 5.075,6.3h25.725c-2.45,11.9 -13.125,21 -25.725,21c-14.525,0 -26.25,-11.725 -26.25,-26.25c0,-2.975 -2.275,-5.25 -5.25,-5.25c-2.975,0 -5.25,2.275 -5.25,5.25c0,20.3 16.45,36.75 36.75,36.75c18.55,0 33.775,-13.65 36.4,-31.5h24.85l-3.5,13.3c-1.05,4.2 -0.525,8.75 1.925,12.25c2.625,3.675 6.825,5.95 11.375,5.95h37.625c2.45,0 4.55,-1.575 5.075,-4.025l11.2,-45.15c1.575,-5.6 -0.7,-11.55 -5.775,-15.05zM209.125,156.625l-10.325,41.125h-33.425c-1.575,0 -2.45,-0.875 -2.8,-1.4c-0.35,-0.525 -1.05,-1.575 -0.525,-2.975l4.375,-16.625h25.375c0.175,0 0.175,0 0.35,0c0.175,0 0.175,0 0.35,0c1.4,0 2.625,-0.525 3.675,-1.4c2.1,-2.1 2.1,-5.425 0.175,-7.35l-15.05,-15.575c8.925,0 17.85,0 24.675,0v0c1.4,0 2.275,0.875 2.8,1.4c0.175,0.175 0.7,1.225 0.35,2.8z" fill="#444b54"></path></g></g></g></svg>
`,
})
export class AnSVGComponent {}
Then you can use these SVG's by simply calling the appropriate custom component.
e.g.
<app-custom-svg></app-custom-svg>

All svg change their color to red when I use a specific svg in my code

I've got some SVG icons, which I use in my web app. They all have specific colors. Regardless of the color, all SVG icons have one color, instead of one, which has two colors (gray and red).
I have an angular component to set my icons in my web app. The directive of my component looks like this:
import {constants} from '../../../index.constants';
export class MyIcon{
public icon: string;
public iconsPath: string = constants.PATH_TO_ICONS;
public fileExtension: string = '.svg';
static options: ng.IComponentOptions = {
template: '<div ng-include="ctrl.iconsPath + ctrl.icon + ctrl.fileExtension"></div>',
controllerAs: 'ctrl',
controller: MyIcon,
bindings: {
icon: '#'
}
};
}
I can use my component in my code and with a binding named icon, I can set the name of the icon I'd like to use:
<my-icon icon="pencil"></my-icon>
In the attachment you can find the icon with the two colors. When I use this in my component, the colors of all other icons turn to red and their shape changes.
When I remove the faulty icon, all other icons have their specific color and look like they have to look. I have no idea why this happens, perhaps because the faulty icon has two colors?
I noticed, that the red of the faulty icon is the same like the red from all other icons, when they change their color.
Example: Icons from my navigation with their specific colors and without the faulty icon in my code:
Example with error: The icons in my navigation and all other icons in my web app look like this (red and ugly shape), when I use the faulty icon in my code:
FAULTY SVG ICON:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.62 15.62"><defs><style>.cls-1,.cls-4{fill:none;stroke-miterlimit:10;}.cls-1{stroke:#e30613;stroke-width:2px;}.cls-2{fill:#fff;}.cls-3{fill:#8b8c8d;}.cls-4{stroke:#fff;}</style></defs><title>Asset 7</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><circle class="cls-1" cx="7.5" cy="8.12" r="6.5"/><polygon class="cls-2" points="1.9 10.19 11.38 0.71 14.91 4.24 5.43 13.72 0.72 14.9 1.9 10.19"/><path class="cls-3" d="M11.38,1.41l2.83,2.83-9,9-3.77.94.94-3.77,9-9m0-1.41L1.45,9.93,0,15.59l5.66-1.41,9.93-9.93L11.38,0Z"/><polygon class="cls-3" points="0.03 15.59 3.43 14.74 0.88 12.19 0.03 15.59"/><rect class="cls-3" x="1.51" y="4.09" width="14.04" height="6" transform="translate(-2.51 8.11) rotate(-45)"/><line class="cls-4" x1="9.96" y1="1.41" x2="14.21" y2="5.66"/><line class="cls-1" x1="2.9" y1="3.52" x2="12.1" y2="12.72"/></g></g></svg>
OTHER SVG:
<svg id="iArrowIcon" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 7.06 12.71"><defs><style>#iArrowIcon .cls-1{fill:none;stroke-miterlimit:10;fill-rule:evenodd;}</style></defs><title>arrow</title><path id="_Compound_Path_" data-name="<Compound Path>" class="cls-1" d="M4904.11,1058.78l6,6-6,6" transform="translate(-4903.76 -1058.42)"/></svg>
Any ideas?
Your svg's have same class and the svg that is causing problem is overriding css properties defined in other svgs.
What you can do is, add a parent class or id to the faulty icon, and use it to separate it's css from others.
Something like this.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>SVG ICONS</title>
</head>
<body>
<svg id="iStopIcon" class="iStopIcon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.62 15.62"><defs><style>
#iStopIcon .cls-1,#iStopIcon .cls-4{fill:none;stroke-miterlimit:10}#iStopIcon .cls-1{stroke:#e30613;stroke-width:2px}.cls-2{fill:#fff}.cls-3{fill:#8b8c8d}.cls-4{stroke:#fff}
</style></defs><title>Asset 7</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><circle class="cls-1" cx="7.5" cy="8.12" r="6.5"/><polygon class="cls-2" points="1.9 10.19 11.38 0.71 14.91 4.24 5.43 13.72 0.72 14.9 1.9 10.19"/><path class="cls-3" d="M11.38,1.41l2.83,2.83-9,9-3.77.94.94-3.77,9-9m0-1.41L1.45,9.93,0,15.59l5.66-1.41,9.93-9.93L11.38,0Z"/><polygon class="cls-3" points="0.03 15.59 3.43 14.74 0.88 12.19 0.03 15.59"/><rect class="cls-3" x="1.51" y="4.09" width="14.04" height="6" transform="translate(-2.51 8.11) rotate(-45)"/><line class="cls-4" x1="9.96" y1="1.41" x2="14.21" y2="5.66"/><line class="cls-1" x1="2.9" y1="3.52" x2="12.1" y2="12.72"/></g></g></svg>
<svg id="iArrowIcon" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 7.06 12.71"><defs><style>
#iArrowIcon .cls-1, .cls-4{fill:#ccc;stroke-miterlimit:10;fill-rule:evenodd;}</style></defs><title>arrow</title><path id="_Compound_Path_" data-name="<Compound Path>" class="cls-1" d="M4904.11,1058.78l6,6-6,6" transform="translate(-4903.76 -1058.42)"/></svg>
</body>
</html>
Here I am using Id, you can use class instead if you prefer.
Your svg use their own style and take the same class.
When you load the last icon, css of this icon rewrite rule of color for other on the class .cls-1
Try to modify your svg with other class or fill the 1 color svg via css like this :
.myIcon{
fill: grey;
}

Template rendering .svg file from public directory

This Meteor template failed to render the public/calender.svg file but instead it renders a standard placeholder image.
How can I get it to show the content of the calender.svg file? Thanks
<img src="/{{image}}.svg"/>
The content of the file is:
'<svg height="24px" version="1.1" viewBox="0 0 24 24" width="24px"><g fill="none" fill-rule="evenodd" id="miu" stroke="none" stroke-width="1"><g id="Artboard-1" transform="translate(-792.000000, -335.000000)"><g id="slice" transform="translate(215.000000, 119.000000)"/><path d="M805.920365,339 ... " fill="#000000"/></g></g></svg>'
edit
If I change the file to .png then it works.

SVG sprite not work in Safari

Safari is not better than IE for a web developer. Here is the issue I saw in Safari.
I am trying to use an SVG sprite to load product icon in my web page.
HTML code:
<img src="https://www.abc123.com/icon_sprite.svg#amex">
SVG Sprite Code:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="276" height="224" viewBox="0 0 276 224" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<view id="affiliate-programs" viewBox="148 0 32 32"/>
<svg width="32" height="32" viewBox="0 0 32 32" x="148"><path .../></svg>
<view id="alipay" viewBox="0 64 49 32"/>
<svg width="49" height="32" viewBox="0 0 49 32" y="64"><path .../></svg>
<view id="amex" viewBox="50 0 49 32"/>
<svg width="49" height="32" viewBox="0 0 49 32" x="50"><path .../></svg>
<view id="auction" viewBox="148 64 32 32"/>
<svg width="32" height="32" viewBox="0 0 32 32" x="148" y="64"><path .../></svg>
<view id="backorder-domain-service" viewBox="180 128 32 32"/>
<svg width="32" height="32" viewBox="0 0 32 32" x="180" y="128"><path .../></svg>
...
...
</svg>
The <img> in HTML locate the <svg> by appending "#" + id of <view> in the sprite url. This way works in Chrome, Firefox, and even IE, but not in Safari.
How it looks like in Chrome:
And how it looks like in Safari 5 and Safari 9:
So it basically means the appended #viewId in <img> can't recognize the view by ID, which is unacceptable.
I am wondering if anyone has seen similar cases and could help me out.
By the way, I also tried another solution.
<object data="https://www.abc123.com/icon_sprite.svg#amex" type="image/svg+xml"></object>
This solution display the correct svg of the sprite, however it will first disappear and then re-appear during AJAX calls, which is not good user experience either.
I answered most of my own questions here by myself. I don't know it is a happy thing or upsetting thing.
I figured out how to fix this issue in the next day after I posted it here.
According to https://www.broken-links.com/2012/08/14/better-svg-sprites-with-fragment-identifiers/, Safari only supports the fragment identifier like xxx.svg#<viewboxId> in Version 7, but not other versions, which I've confirmed in Sauce Labs. It is an even worse browser than IE.
Well, no more complaint. Let's talk about the solution, which is the most important thing.
It is true the fragment identifier xxx.svg#<viewboxId> does not work in most of Safaris. It happens in <img>, but not in <embed>. So for Safari, we can use <embed> to load fragment identifier.
How to differentiate browser:
function isSafari() {
if (navigator && navigator.userAgent) {
var userAgent = navigator.userAgent;
var isChrome = userAgent.indexOf('Chrome') > -1;
var isSafari = userAgent.indexOf('Safari') > -1;
if ((isChrome) && (isSafari)) {
isSafari = false;
}
return isSafari;
}
return false;
}
In Safari:
<embed id="embedSvg" class="pi_svg" src="https://www.abc123.com/icon_sprite.svg#amex" type="image/svg+xml"></embed>
In non-Safari:
<img class="pi_svg" src="https://www.abc123.com/icon_sprite.svg#amex">

Embed one image of a SVG sprite in HTML

I have an automatically generated SVG spritemap (grunt-svg-sprite) which looks like this file:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="116" height="69" viewBox="0 0 116 69">
<svg width="116" height="25" viewBox="0 0 116 25" id="block1" y="0">
<path fill="#fff" stroke="#FF51D4" stroke-miterlimit="10" d="M0 0h116v25H0z"/>
<path fill="#D5FF54" stroke="#FF51D4" stroke-miterlimit="10" d="M0 0h116v25H0z"/>
</svg>
<svg width="20" height="20" viewBox="0 0 20 20" id="block2" y="25">
<path fill="#FF001A" d="M.5.5h19v19H.5z"/>
<path fill="#1D1D1B" d="M19 1v18H1V1h18m1-1H0v20h20V0z"/>
</svg>
<svg width="27" height="24" viewBox="0 0 27 24" id="block3" y="45">
<path d="M.5.5h26v23H.5z"/>
<path fill="#6BFF4E" d="M26 1v22H1V1h25m1-1H0v24h27V0z"/>
</svg>
</svg>
This SVG consists of three "images" which have the IDs "block1", "block2" and "block3".
I want to display only "block1" on my web page, so that the dimensions of this image should be scalable. I want to set the width to 10rem and the height should be automatically adjusted. I did it this way:
<img src="https://cdn.mediacru.sh/ahw4Jhv0r6GG.svg#block1" style="width:10rem;"/>
And here I created a JSFiddle. The problem is, that the web browser displays all three blocks instead of only "block1". How can I do this with an <img>? I have to support the latest versions of web browsers and only IE11, previous versions would be great, but is not a must.
(I can not use the object HTML tag, because I am limited in my IE11 support - I can not see the objects on this page, I see the images of "iframe", "img" and "CSS background" but "object": three times: "Active content removed").
The easiest way to solve your problem is to add some CSS directly to your SVG file:
<style><![CDATA[ svg svg { display: none; } svg svg:target { display: inline; }]]></style>
This simple CSS prevents all the blocks from display and shows only the one you're targeting to.
Here is your SVG file with added CSS and JSFiddle demo.
While you use Grunt you can automatize it using e.g. grunt-string-replace task (running it on SVG file after processing with grunt-svg-sprite). The task should look more or less like this:
'string-replace': {
dist: {
files: {
'./src/preprocessedSVG.svg': './build/sprite.svg'
},
options: {
replacements: [{
pattern: '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="116" height="69" viewBox="0 0 116 69">',
replacement: '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="116" height="69" viewBox="0 0 116 69"><style><![CDATA[ svg svg { display: none; } svg svg:target { display: inline; }]]></style>'
}]
}
}
You can add some variables or RegExps to pattern to make it more robust and bulletproof.
--
The other solution is to switch to inline SVG nicely described by Chris Coyer (http:// css-tricks.com/svg-sprites-use-better-icon-fonts/). There is also Grunt task for that - [grunt-svgstore] (https:// github.com/FWeinb/grunt-svgstore).
P.S. You need to copy those links and remove space after "https://" cause I am new to StackOverflow and can not post more than 2 links...