How to mask user image in SVG hexagon shape on react native - javascript

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.

Related

React Native SVG Image not loading

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',
}}
/>

Image overflows stroke inside SVG shape

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>
);
};

What should I use to show live icons in React OR Javascript? Like how much coffee is filled in a mug?

I want to create dashboard with lots of live icons. Live icons means icons content will change dynamically.
For example:- Let say i have an icon of a coffee cup, based upon number of coffee sold the coffee level in cup goes up.
I tried solving it using SVG & CSS. Below is the live code-sandbox DEMO example. (same code I am posting below)
https://codesandbox.io/s/fill-coffee-to-svg-1sfb0
what exactly I am doing is on top of SVG component i using div node and applying css on the div tag.
Issue is that, It is very difficult to manage path/points dynamically in SVG, also for different screen version it will be difficult.
Can anyone suggest any better approach for this.
import ReactDOM from "react-dom";
import React, { Component } from "react";
class Todo extends Component {
state = { height: 4 };
setHeight = (e, fillType) => {
e.preventDefault();
console.log(this.state.height);
if (this.state.height < 100) {
if (fillType === "fill") {
this.setState({
height: this.state.height + 2
});
}
}
if (this.state.height >= 2) {
if (fillType === "drink") {
this.setState({
height: this.state.height - 2
});
}
}
};
render() {
return (
<div>
<svg width="255" height="224" xmlns="http://www.w3.org/2000/svg">
<g>
<rect
fill="#fff"
id="canvas_background"
height="226"
width="257"
y="-1"
x="-1"
/>
<g
display="none"
overflow="visible"
y="0"
x="0"
height="100%"
width="100%"
id="canvasGrid"
>
<rect
fill="url(#gridpattern)"
stroke-width="0"
y="0"
x="0"
height="100%"
width="100%"
/>
</g>
</g>
<g>
<title>Layer 1</title>
<path
stroke="#000"
id="svg_1"
d="m78.82963,176.75921l97.93778,0c14.11708,-0.03733 23.74788,-17.00704 23.70086,-34.46505l0,-11.73873c27.94999,-0.03136 48.22814,-30.02253 48.21769,-64.99381c0.01045,-35.59398 -19.86965,-64.83701 -43.00946,-64.81162l-150.95938,0l0,141.54714c0.02194,19.22158 11.60543,34.42772 24.1125,34.46207zm121.63551,-149.38391l0,0l5.20823,0c19.14875,-0.04331 25.29102,25.83983 25.19908,38.38045c0.01881,20.24897 -10.47393,39.66916 -30.40731,37.78463l0,-76.16508zm-199.71514,158.00316c0.01776,26.16387 13.9729,38.29683 25.20535,38.37149l202.59351,0c13.39827,-0.07466 25.14161,-15.13147 25.20117,-38.37149l-253.00002,0z"
stroke-width="1.5"
fill="#fff"
/>
</g>
</svg>
<div
style={{
position: "absolute",
left: "63px",
top: "9px",
height: "175px",
width: "145px",
borderBottomLeftRadius: "25px",
borderBottomRightRadius: "25px",
overflow: "auto"
}}
>
<div
style={{
height: this.state.height + "%",
width: "100%",
position: "absolute",
bottom: "0",
zIndex: 1000,
background: "green",
transition: "all .4s"
}}
/>
</div>
<button onClick={e => this.setHeight(e, "fill")}>
fill more cofee +
</button>
<button onClick={e => this.setHeight(e, "drink")}>drink cofee -</button>
</div>
);
}
}
ReactDOM.render(<Todo />, document.getElementById("root"));
Have you tried using the react-spring library?
In the basics section of react-spring documentation (can be found here - https://www.react-spring.io/docs/hooks/basics) this code snippet is given:
const props = useSpring({ x: 100, from: { x: 0 } })
return (
<animated.svg strokeDashoffset={props.x}>
<path d="..." />
</animated.svg>
)
Using your example of your coffee mug, if you would render your mug separate to the coffee filling the mug, with the coffee stroke being upwards, then you could use this technique to animate the coffee height.
Edit:
As you are using a class component you will want to use the render props API for this - https://www.react-spring.io/docs/props/spring
<Spring
from={{ x: 100 }}
to={{ x: 0 }}>
{props => (
<svg strokeDashoffset={props.x}>
<path d="..." />
</svg>
)}
</Spring>

G-SVG doesnt show my Image inside it - react-native

I'm using react-native-svg. I want to show my image inside it but G doesnt show it:
<G x={endCoord2.x-widthHeight} y={endCoord2.y-widthHeight}>
<Image resizeMode='stretch' style={{width:50,height:50,margin:4}} source={{uri: 'https://javacupcake.com/wp-content/uploads/2017/07/IceCreamConeCupcakes_0307.jpg'}} />
</G>
but below code show a white circle:
<G x={endCoord2.x-widthHeight} y={endCoord2.y-widthHeight}>
<Circle r={widthHeight}
cx={widthHeight}
cy={widthHeight}
fill="#fff"
{...this._panResponderShops.panHandlers}
/>
</G>
where is my wrong?
solved:
you should import Image from react-native-svg:
<Image
x="5%"
y="5%"
width={widthHeight+20}
height={widthHeight+20}
preserveAspectRatio="xMidYMid slice"
opacity="0.5"
href={require('../../../images/ics/ic_blue_logo.png')}
clipPath="url(#clip)"
/>
https://github.com/react-native-community/react-native-svg/blob/master/README.md#image

SVG Knockout text styling issue: unexplained cropped bottom

I've tried to build a react component for knockout text and I run into a styling issue I can't explain to myself.
Here is my attempt.
const styles = {
container: {
backgroundSize: "cover",
backgroundImage: "url(http://brokensquare.com/Code/assets/landscape.jpg)",
padding: "20% 20%"
},
knockout: {
borderRadius: 200,
overflow: "hidden"
}
};
const Knockout = ({ text, style }) => {
const s = style || {};
return (
<div style={styles.knockout}>
<svg viewBox="0 0 200 25">
<rect
fill={s.backgroundColor || "rgba(0,0,0,0.6)"}
x="0"
y="0"
width="100%"
height="100%"
mask="url(#knockout-text)"
/>
<mask id="knockout-text">
<rect fill="#fff" x="0" y="0" width="100%" height="100%" />
<text y="70%" fill="#000" textAnchor="middle" x="50%">
{text}
</text>
</mask>
</svg>
</div>
);
};
const App = Radium(() => (
<div>
<div style={styles.container}>
<Knockout style={{}} text={"VERY INSPIRATION"} />
</div>
</div>
));
As you can see the bottom is cropped for some reason, instead of having the side completely rounded, drawing half a circle. Can anyone here see why and how I could fix this ? Thanks.
add this css, it will work
svg {
display: block
}
you can check below codesandbox
https://codesandbox.io/s/71qxyx6m86
I added styles as below
render(
<div>
<App />
<Style
rules={{
"*": {
margin: 0,
padding: 0,
boxSizing: "border-box"
},
svg: {
display: "block"
}
}}
/>
</div>,
document.getElementById("root")

Categories

Resources