How to make copied SVGs as clear as they are displayed? - svg

I'm displaying SVGs in <img> tags. With viewBox these images could be scaled without losing clarity. However, when I copy these images (and paste them into PowerPoint, etc.), they won't be as clear as they are displayed.
How could I make copied images clear? And could this be done without using a canvas?
Example SVG markup:
<svg id="mol-638318-0540814976"
xmlns="http://www.w3.org/2000/svg" width="84" height="40" viewBox="0 0 84 40">
<style>
#mol-638318-0540814976 text {
dominant-baseline: central;
text-anchor: middle;
font-size: 16px;
font-family: serif;
fill: black;
}
#mol-638318-0540814976 line {
stroke: black;
}
</style>
<text x="26" y="20">C</text>
<text x="58" y="20">C</text>
<line x1="32" y1="20" x2="52" y2="20"></line>
</svg>
Thanks!

Related

Mask Image with SVG Shape and add a Border

Not sure this is possible, so I have a back-up plan (use a background image and :after to mask one of 3x transarent PNGs with the border in the image and use nth-child to change them).
Here's what I'm trying to accomplish. I know clip-path will give me the image mask, but I need the curved edges and the border color, too. Which I don't think is possible in pure CSS.
<!DOCTYPE html>
<html>
<style>
img {
max-width: 100%;
display: block;
}
.container {
width: 300px;
height: 300px;
margin: 1em auto;
}
.frame-border {
stroke: #10c020;
stroke-width: 4;
}
</style>
<body>
<div class="container">
<svg viewBox="-10 -10 120 120">
<defs>
<mask id="mask">
<rect fill="#000000" x="0" y="0" width="300" height="300"></rect>
<path id="Path_611" data-name="Path 611" d="M1,38a12.225,12.225,0,0,1,2.558-3.025L41.351,13.462A21.12,21.12,0,0,1,46.733,12.4a14.319,14.319,0,0,1,4.81.765L89.2,34.814A7.333,7.333,0,0,1,92,37a7.273,7.273,0,0,1,1,3.4v45.3A6.741,6.741,0,0,1,92,89a12.9,12.9,0,0,1-3.015,2.945L50.42,110.628a8.953,8.953,0,0,1-3.688.786,13.383,13.383,0,0,1-4.153-.992L4.2,92.012A12.105,12.105,0,0,1,1,89a7.112,7.112,0,0,1-1-3.581V41.534A9.569,9.569,0,0,1,1,38Z" transform="translate(1.502 -10.892)" fill="#FFFFFF"/>
</mask>
</defs>
<image mask="url(#mask)"
xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://randomuser.me/api/portraits/women/47.jpg" width="100" height="100">
</image>
<g class="frame-border" fill="none">
<path id="Path_611" data-name="Path 611" d="M1,38a12.225,12.225,0,0,1,2.558-3.025L41.351,13.462A21.12,21.12,0,0,1,46.733,12.4a14.319,14.319,0,0,1,4.81.765L89.2,34.814A7.333,7.333,0,0,1,92,37a7.273,7.273,0,0,1,1,3.4v45.3A6.741,6.741,0,0,1,92,89a12.9,12.9,0,0,1-3.015,2.945L50.42,110.628a8.953,8.953,0,0,1-3.688.786,13.383,13.383,0,0,1-4.153-.992L4.2,92.012A12.105,12.105,0,0,1,1,89a7.112,7.112,0,0,1-1-3.581V41.534A9.569,9.569,0,0,1,1,38Z" transform="translate(1.502 -10.892)" stroke-linecap="round" />
</g>
</svg>
</div>
</body>
</html>

Use svg with external font in GIMP

I have created this svg with an external font, that part of the SVG looks like this:
<defs>
<style type="text/css">#import url(https://fonts.googleapis.com/css?family=Cairo|Gloria+Hallelujah|Rokkitt|Shadows+Into+Light|Signika></style>
</defs>
In Chrome this works nice, but when I try to load the svg into GIMP the font is missing. Is there a way for GIMP to render the google fonts?
Complete test svg:
<?xml version="1.0"?>
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<defs>
<style type="text/css">#import url(https://fonts.googleapis.com/css?family=Cairo|Gloria+Hallelujah|Rokkitt|Shadows+Into+Light|Signika></style>
</defs>
<style>
text {
font-size: 30px;
font-family: Shadows Into Light;
}
</style>
<text x="20" y="35"><tspan>Test</tspan></text>
</svg>
Update: For the SVG to work in Gimp or Inkscape:
<?xml version="1.0"?>
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<defs>
<style type="text/css">
<![CDATA[
#font-face {
font-family: 'Shadows Into Light';
font-style: normal;
font-weight: normal;
src: local('Shadows Into Light'), local('ShadowsIntoLight'), url('http://themes.googleusercontent.com/static/fonts/shadowsintolight/v3/clhLqOv7MXn459PTh0gXYHW1xglZCgocDnD_teV2lMU.woff') format('woff');
}
text {
font-size: 30px;
font-family: Shadows Into Light;
}
]]>
</style>
</defs>
<text x="20" y="35"><tspan>Test</tspan></text>
</svg>
The problem goes further than external Google fonts:
1) Gimp (or whatever SVG parser it uses) is picky about the syntax (normally the style should be in CDATA)
2) Even with the CDATA fix (that at least stop nasty messages in the Gimp console), Gimp won't abide to the font-family style, even for fonts installed system-wide.

Hover on svg text not working

Creating a svg from adobe xd and trying to create a hover effect for the svg can change fill: colors on hover.
# Heres the svg code #
<svg xmlns="http://www.w3.org/2000/svg" viewBox="1563 3492 45 45">
<defs>
<style>
.cls-1 {
fill: #79bf73;
font-size: 45px;
font-family: SegoeMDL2Assets, Segoe MDL2 Assets;
}
</style>
</defs>
<text id="E1CC" class="cls-1" transform="translate(1563 3537)"><tspan x="0" y="0"></tspan></text>
</svg>
# Heres the html code #
<div class="play">
<img src="http:localhost/mockup3/images/E101.svg" height="42" width="42">
</div>
# Heres the css code #
svg text #E101:hover{
fill: #003565;
}
SVGs inserted as img can't have interaction, they behave as images. To fix this, simply put the full SVG code inline. Cleaned up the code a bit, as these tools often produce ugly code.
HTML
<div class="play">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="1563 3492 45 45" width="42" height="42">
<text id="E1CC" class="cls-1" transform="translate(1563 3537)"><tspan x="0" y="0"></tspan></text>
</svg>
</div>
CSS
svg text {
fill: #79bf73;
font-size: 45px;
font-family: SegoeMDL2Assets, Segoe MDL2 Assets;
}
svg text:hover{
fill: #003565;
}
Keep in mind the icon will only be visible with the font Segoe MDL2 Assets installed.

Safari trouble positioning SVG feSpotlight filter

I want to use a spotlight effect but it only seems to work in Chrome, looks "just ok" in Firefox, but will not position (x,y,z) in Safari. (Other browsers not tested)
I've tried different filter and primitive units, and while this makes a difference, Safari still cannot seem to position the lighting effect in any case.
In pursuit of understanding what is going on, I've tried lots of workarounds including different userSpaceOnUse/objectBoundingBox combos, and different svg structure but have never been able to find one that works on Safari.
Examples
Default filter/primitive units:
https://jsfiddle.net/localnerve/y470d52v/
objectBoundingBox units:
https://jsfiddle.net/localnerve/uyc7o52k/
A picture is also worth a 1000 words (Safari, Chrome, FF). The spotlight on Safari is rendered off-canvas to the right and bleeds in from the right.
To show the spotlight positions on Safari are "out of whack", here's me nudging them in web inspector so I can see the spotlight render at all:
Here is the code using objectBoundingBox filter and primitive units:
<style>
body {
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 16px;
color: #fff;
}
* {
transform-origin: 50% 50% 0;
}
.scene-container {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
}
.scene-container.content {
position: relative;
width: 100%;
height: 150vh;
background-image: linear-gradient(hsla(240, 90%, 8%, 1) 0%, 99%, hsla(217,24%,71%,0) 100%);
box-shadow: 0px -10px 20px hsl(240, 90%, 8%);
}
.spot {
height: 100%;
width: 100%;
}
</style>
<body>
<div class="scene-container content">
<h2>Here's a spotlight.</h2>
<svg class="spot" viewBox="0 0 2000 3000" preserveAspectRatio="xMidYMid">
<defs>
<filter x="-0.2" y="-0.2" width="1.4" height="1.4" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox" id="spotlight">
<feGaussianBlur in="SourceAlpha" stdDeviation="8" result="blur1"></feGaussianBlur>
<feSpecularLighting result="specOut" in="blur1" specularConstant="1.8" specularExponent="5" lighting-color="#ffffff">
<feSpotLight x="0.5" y="-0.4" z="0.03" pointsAtX="0.5" pointsAtY="0.8" pointsAtZ="0" limitingConeAngle="13.7"></feSpotLight>
</feSpecularLighting>
<feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="0" k2="1" k3="1" k4="0"></feComposite>
</filter>
<clipPath id="spot-clip">
<rect x="-50" y="2840" width="2200" height="200"></rect>
</clipPath>
<filter id="spot-blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="15">
</feGaussianBlur>
</filter>
</defs>
<g transform="translate(0, -175)" filter="url(#spotlight)">
<ellipse cx="50%" cy="95.333%" rx="27%" ry="130" fill="#fff" clip-path="url(#spot-clip)" filter="url(#spot-blur)"></ellipse>
<rect x="25%" y="43.667%" width="50%" height="50%" stroke="peru" stroke-width="3%" stroke-linejoin="round" fill="#000"></rect>
</g>
</svg>
</div>
</body>
Any insight you can give is greatly appreciated.
There are known bugs in webkit/Safari for light source positioning wrt transforms and oBB units. After the webkit/blink engine schism, no-one at Apple picked these bugs up from the Chrome team.
https://bugs.webkit.org/show_bug.cgi?id=88877
https://bugs.webkit.org/show_bug.cgi?id=113059
The workaround is not to use transforms and oBB units (do any dynamic positioning or sizing via JavaScript)

SVG backgrounds are getting cut off in IE11 when zooming

We are trying to display SVG backgrounds in internet explorer. Our images are always getting cut off when a zoom other than 100% is used. This can be reproduced using the following code:
with this svg
<svg xmlns="http://www.w3.org/2000/svg" height="100" width="100" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="48" stroke="black" stroke-width="3" fill="red" />
</svg>
div {
width: 14px;
height: 14px;
background-size: 14px 14px;
background-repeat: no-repeat;
background-image: url("data:image/svg+xml;charset=utf-8,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' height='100' width='100' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='48' stroke='black' stroke-width='3' fill='red'%3E%3C/circle%3E%3C/svg%3E");
}
<div></div>
The result looks like this:
In all other browsers it renders fine. Has anyone else ever experienced this bug? Is there a workaround?
I have found one workaround which requires very little work:
Make the SVG image 2X size of the actual content (this would make the circle look like this:
<svg xmlns="http://www.w3.org/2000/svg" height="200" width="200" viewBox="0 0 200 200">
<circle cx="50" cy="50" r="48" stroke="black" stroke-width="3" fill="red" />
</svg>
Then use the :after pseudo element to create an inside element with 2x the desired size. So the html would be
<div class="circle"></div>
And the css would be
.circle {
width: 14px;
height: 14px;
position:relative;
}
.circle:after {
position: absolute;
top: 0;
left: 0;
content: ' ';
width: 28px;
height: 28px;
background-size: 28px 28px;
background-repeat: no-repeat;
background-image: url('circle.svg');
}
The extra space in the :after pseoudoelement gives IE spare canvas to draw on, but both the visible icon and the space occupied by the original container remain the same.

Resources