In my React app, I want to be able to crop an image and embed it into a hexagonal SVG shape to use as an avatar. I've done the cropping part and made the SVG border, just one problem that I have is that the embedded picture overflows the border approximately to its half and I want that border to be fully visible.
Here is my code:
export const HexagonFrame = ({ logo }) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="63.191"
height="69.06"
viewBox="0 0 63.191 69.06"
>
<defs>
<clipPath id="shape">
<path
id="hex"
d="M4.2,34.351c.161-3.452.08-6.825.482-10.277A13.043,13.043,0,0,1,11.025,14.2c4.416-2.81,8.993-5.379,13.489-8.029,4.978-2.971,9.956-2.81,14.854.08C43.382,8.659,47.4,11.068,51.412,13.4c4.737,2.81,7.547,6.9,7.708,12.445.161,6.182.08,12.445-.241,18.627a12.05,12.05,0,0,1-5.54,9.474c-5.058,3.292-10.277,6.423-15.577,9.394a12.22,12.22,0,0,1-12.285-.08c-4.9-2.73-9.635-5.62-14.372-8.591-4.577-2.89-6.664-7.226-6.825-12.525-.08-2.569,0-5.138,0-7.788Z"
transform="translate(-0.01 0.042)"
fill="none"
stroke="#fff"
strokeMiterlimit="10"
strokeWidth="8"
strokeOpacity="1"
/>
</clipPath>
</defs>
<use xlinkHref="#hex" />
{logo && (
<image
width="63.191"
height="69.06"
clipPath="url(#shape)"
xlinkHref={logo}
id="logo"
/>
)}
</svg>
);
};
And screenshots of the hexagonal shape I'm working with. As you can see the border is overflown by the picture inside
You must position the stroke in front of the image.
SVG strokes are positioned onto the middle of the path they are defined with. So if you just change the order, part of the image will be obscured by the stroke. To avoid that, you need to reposition (by 4px, half the width of the stroke) and resize (by 8px, the full width of the stroke) the image. Like this:
export const HexagonFrame = ({ logo }) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="63.191"
height="69.06"
viewBox="0 0 63.191 69.06"
>
<defs>
<clipPath id="shape">
<path
id="hex"
d="M4.2,34.351c.161-3.452.08-6.825.482-10.277A13.043,13.043,0,0,1,11.025,14.2c4.416-2.81,8.993-5.379,13.489-8.029,4.978-2.971,9.956-2.81,14.854.08C43.382,8.659,47.4,11.068,51.412,13.4c4.737,2.81,7.547,6.9,7.708,12.445.161,6.182.08,12.445-.241,18.627a12.05,12.05,0,0,1-5.54,9.474c-5.058,3.292-10.277,6.423-15.577,9.394a12.22,12.22,0,0,1-12.285-.08c-4.9-2.73-9.635-5.62-14.372-8.591-4.577-2.89-6.664-7.226-6.825-12.525-.08-2.569,0-5.138,0-7.788Z"
transform="translate(-0.01 0.042)"
fill="none"
stroke="#fff"
strokeMiterlimit="10"
strokeWidth="8"
strokeOpacity="1"
/>
</clipPath>
</defs>
{logo && (
<image
x="4"
y="4"
width="55.191"
height="61.06"
clipPath="url(#shape)"
xlinkHref={logo}
id="logo"
/>
)}
<use xlinkHref="#hex" />
</svg>
);
};
Related
I'm using SVG in HTML to draw a bended word along a path. Now that I managed to do draw the text, I need to split the word in 2 colors along the path that the word sits on. You can see the effect I'm trying to make in the image. Does anyone know how can I split the word in such a way? (I'm not sure if this matters, but the word is constantly bended, stretched and moved by the user, by modifying the "d" attribute of the path.)
var path = document.getElementById("Path");
var textPath = document.getElementById("TextPath");
document.onmousemove = function(e){
path.setAttribute("d", `M 100 100 q ${e.x-100} ${e.y-100} 230 0`);
textPath.setAttribute("textLength", path.getTotalLength() + "px")
}
svg {
width: 500px;
height: 500px;
}
<svg>
<path id="Path" d="M 100 100 q 50 -100 230 0" stroke="#000000" stroke-width="1" fill="none"></path>
<text id="Text" fill="#000000" font-size="64px">
<textPath startOffset="0%" id="TextPath" alignment-baseline="middle" href="#Path" startOffset="0%" startOffset="0%">Example</textPath>
</text>
</svg>
Here's a simpler version of what I have now. What I want to happen, is to color everything above the curve with one color and everything below with another.
One way of doing it: you use the text twice: once filled with color A and once filled with color B. Next you clip the second text with the path.
<svg viewBox="0 0 260 200">
<defs>
<path id="pth" d="M70,150 C10,40 240,40 180,150" stroke="red" fill="none" />
<text id="txt" font-size="45" text-anchor="middle" dominant-baseline="central">
<textPath font-size="35" startOffset="50%" href="#pth">
SSSSSSSSSSSS
</textPath>
</text>
<clipPath id="cp">
<use href="#pth" />
</clipPath>
</defs>
<use href="#txt" fill="blue" />
<use href="#txt" fill="orange" clip-path="url(#cp)" />
</svg>
I'm drawing a simple US map with state borders drawn. Eventually there will be hover and click events. However, anywhere the states touch, the borders appear double thickness. On the assumption that there isn't something wrong with my shapes, how can I keep these lines from getting double thickness? Is there a CSS setting?
It's written in React, but I hope that's not relevant. In the end it's just path objects in a group in an svg.
export const USMap = (props: Props) => {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 959 593">
<title>Map of US States</title>
<g id="states">
{Object.entries(states).map(([abbreviation, state]) => (
<path key={abbreviation} d={state.dimensions} fill="#fff" stroke="#000" strokeWidth="1" />
))}
</g>
</svg>
);
};
I created an svg. And want to re-create it in React-Native. I use this npm package for it (https://www.npmjs.com/package/react-native-svg#image).
Here is the SVG
What i created is this
<TestApp
imageWidth={2300}
imageHeight={1438}
width={width}
url={'./url/to/picture'}
scale1={0.00100794}
scale2={0.000666667}
/>
const TestApp = ({
width,
overlayColor = 'black',
overlayOpacity = '0.3',
translate1,
translate2,
scale1,
scale2,
imageWidth,
imageHeight,
url,
}) => {
const height = (254 / 202) * width;
const translate = translate1
? `translate(${translate1} ${translate2 ? translate2 : ''})`
: '';
const scale = scale1 ? `scale(${scale1} ${scale2 ? scale2 : ''})` : '';
return (
<Svg
width={width}
height={height}
viewBox={`0 0 ${202} ${254}`}
fill="none"
>
<Mask
id="breathMask"
mask-type="alpha"
maskUnits="userSpaceOnUse"
x="0"
y="0"
width={width}
height={height}
>
<Path
d="M0 0H201.374V228.761C201.374 228.761 158.683 254 100.687 254C42.6913 254 0 228.761 0 228.761V0Z"
fill="#C4C4C4"
/>
</Mask>
<G mask="url(#breathMask)">
<Rect
x="1"
width={width}
height={(303 / 254) * height}
fill="url(#pattern0)"
/>
<Path
d="M0 0H201.374V228.761C201.374 228.761 158.683 254 100.687 254C42.6913 254 0 228.761 0 228.761V0Z"
fill={overlayColor}
fillOpacity={overlayOpacity}
/>
</G>
<Defs>
<Pattern
id="pattern0"
patternContentUnits="objectBoundingBox"
width="1"
height="1"
>
<Use href="#image0" transform={`${translate} ${scale}`} />
</Pattern>
<Image
id="image0"
widht={imageWidth}
height={imageHeight}
href="../path/to/url"
/>
</Defs>
</Svg>
);
};
Basically I copied the svg as it is.
The problem, the picture is not loading, even If I put a public url, such as this in it.
The svg with a grey background is not rendering. The picture will render in webview, though but not in ios or android.
You got any ideas how to fix it? Or a complete other way to achieve something like this?
Probably easiest way would be to just create a curved picture in photoshop, but thats not really dynamic.
Have you tried the using other parameters?
<Image
style={{ width: imageWidth, height: imageHeight }}
source={{
uri: '../path/to/url',
}}
/>
I am using svg icons for expanding and collapsing a component. They are rendering correctly as you can see in the following image:
but when I expand a component and perform an action the svgs begin to look like this:
I have verified there is absolutely no change in the svg component and they return to the correct view after I expand another component. This issue is occuring at multiple locations where I am using svg icons. I am using React and the svg icons are loaded as components. This only occurs on Safari and no other browser
Edit
The code for the svg is :
export const CollapseIcon = () => (<svg
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
width="24"
height="24"
viewBox="0 0 24 24">
<defs>
<path
id="gt4gdtq39a"
d="M7.146 9.146c.174-.173.443-.192.638-.057l.07.057L12 13.293l4.146-4.147c.174-.173.443-.192.638-.057l.07.057c.173.174.192.443.057.638l-.057.07-4.5 4.5c-.174.173-.443.192-.638.057l-.07-.057-4.5-4.5c-.195-.196-.195-.512 0-.708z"
/>
</defs>
<g fill="none" fillRule="evenodd">
<g>
<g transform="translate(-956 -290) translate(956 290)">
<mask id="reyuf8n5tb" fill="#fff">
<use xlinkHref="#gt4gdtq39a" />
</mask>
<use fill="#000" fillRule="nonzero" xlinkHref="#gt4gdtq39a" />
<g fill="#F7274A" mask="url(#reyuf8n5tb)">
<path d="M0 0H24V24H0z" />
</g>
</g>
</g>
</g>
);
and I am using it as a simple component like:
{expanded ? <CollapseIcon /> : <ExpandIcon />}
I am struggling with hexagon shape on react native can anyone have some idea about how does it work using svg in react native or any alternate way?
creating shapes using js
image cutout of hexagon
masking image[enter image description here][1]
I'm trying this below image.
https://i.stack.imgur.com/MLDFl.jpg
This is My code:
render() {
return (
<Svg
height="300"
width="300"
viewBox="0 0 860 860"
>
<Defs>
<ClipPath id="clip">
<Polygon
strokeWidth="2"
stroke="#979797"
strokeDasharray='8,8'
strokeLinecap='butt'
fill="rgba(0, 0, 0, 0.5)"
points="258.5,223.999 130.5,298 2.5,224 2.5,76 130.5,2 258.5,76 " />
</ClipPath>
</Defs>
<Image
x="0%"
y="0%"
width="100%"
height="100%"
preserveAspectRatio="xMidYMid slice"
opacity="0.5"
href={require('./assets/Image.jpg')}
clipPath="url(#clip)"
/>
</Svg>
);
}
This kind of image can be created with my react-native-image-filter-kit module:
import { Image } from 'react-native'
import { DstATopComposition } from 'react-native-image-filter-kit'
const style = { width: 320, height: 320 }
const masked = (
<DstATopComposition
dstImage={
<Image
style={style}
source={{ uri: 'https://i.stack.imgur.com/MLDFl.jpg' }}
/>
}
srcImage={
<Image
style={style}
source={{ uri: 'http://www.myiconfinder.com/uploads/iconsets/256-256-53d5151ca4f467ed9951f85024881c85.png' }}
/>
}
/>
)
Note that shape generation is not supported currently, so you need to use another image for masking.