Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image url #347

Closed
hle50 opened this issue May 27, 2017 · 17 comments
Closed

Image url #347

hle50 opened this issue May 27, 2017 · 17 comments

Comments

@hle50
Copy link

hle50 commented May 27, 2017

Currently I want to load image from url not from local, and this is the code I use and it is not working, please help me to resolve this

        <Svg
          width= {Layout.window.width}
          height={Layout.window.height/2}
        >
          <Circle
            cx={data.xAxis}
            cy={data.yAxis}
            r="10"
            fill={data.departmentColorCode}
          />
          <Image
                    width="100%"
                    height="100%"
                    preserveAspectRatio="xMidYMid slice"
                    opacity={0.5}
                 href={{uri:data.floorImage}}/>
        </Svg>
      </View>
@hle50
Copy link
Author

hle50 commented Jun 1, 2017

I had solution by using react-native-fetch-blob

@hle50 hle50 closed this as completed Jun 1, 2017
@fendorio
Copy link

fendorio commented Jun 3, 2017

@hle50 Care to share any code, seems like i've hit the same problem as you. I'm working with react-native-fetch-blob but can't seem to get the SVG element to display..

I've currently got a function which goes and fetches a remote image:

fetchURL (url = "https://scontent.flhr1-1.fna.fbcdn.net/v/t1.0-1/p50x50/18485800_10154852885050892_1932698345727514435_n.jpg?oh=ec06614c8f2e3e672f4729d7c46c3f25&oe=59A313B2") {
    
    return new Promise((resolve, reject) => {

        RNFetchBlob
            .config({
                // add this option that makes response data to be stored as a file,
                // this is much more performant.
                fileCache : true
            })
            .fetch('GET', url, {
                //some headers .. 
            })
            .then((res) => {
                // the temp file path
                //TODO - this does not not automatically get cleared up.
    
                 //Hardcoded to jpeg atm, this will be worked out dynamically
                return resolve('data:jpeg;base64,' + res.base64()); 
            })
            .catch((err) => {
                return reject(err);
            });
    }); 
}

I've then got a function which generates a set of avatars, essentially a collection of elements inside a element

generateAvatars () {
        const friends = [
            {
                name: "Lee"
            },
            {
                name: "Simone"
            },
            {
                name: "Mark"
            },
            {
                name: "Ian"
            }
        ];
        return (
            <G>
                {
                    friends.map((f, i) => {
                        const r = 24;
                        const pos = r * i;
                        return (
                            <G>
                       
                                <Image
                                    x={24}
                                    y={24}
                                    width={100}
                                    height={100}
                                    href={this.fetchURL()}
                                />

                            </G>
                        ); 
                    })
                }

            </G>
        );
    }

My render function then outputs the result of generateAvatars(). This works, if I replace the element with a , it shows.

The code above is purely conceptual, so anything outside of what i've explained isn't worth pointing out :)

Any help would be appriciated!

@nadude
Copy link

nadude commented Jun 18, 2017

This seems to work for me href={{ uri: '<remote-image-url', __packager_asset:true }} . Good luck! @hle50 @ @fendorio @magicismight

@fendorio
Copy link

Thanks @nadude i'll test this tomorrow and let the thread know how it went!

@ggomaeng
Copy link

Any solution to this yet?

@sibelius
Copy link

@hle50 can u post ur solution?

@msand
Copy link
Collaborator

msand commented Feb 27, 2018

@sibelius Check here https://snack.expo.io/@msand/image-from-uri-inside-svg

@ricklancee
Copy link

ricklancee commented Feb 27, 2018

hi @msand does this only work for apps via expo and not when importing Image from react-native-svg? Just tried this in a plain react native project i get the error:

JSON value '{
    uri = "https://avatars2.githubusercontent.com/u/1131362?s=460&v=4";
}' of type NSMutableDictionary cannot be converted to an image. Only local files or data URIs are supported.

Do we have to convert the image to a data uri before passing it into the href?

Edit: Using react-native-fetch-blob and using it as a temp file uri works.

import React from 'react'
import RNFetchBlob from 'react-native-fetch-blob'

import Svg, {
    Image,
} from 'react-native-svg'

import { View } from 'react-native'

class SvgImage extends React.Component {

    state = {
        uri: undefined,
    }

    async componentWillMount() {
        const res = await RNFetchBlob
           .config({
              // add this option that makes response data to be stored as a file,
              // this is much more performant.
              fileCache : true,
              // by adding this option, the temp files will have a file extension
             appendExt : 'jpg',
           })
          .fetch('GET', 'https://avatars2.githubusercontent.com/u/1131362?s=460&v=4')
       
        this.setState({
            uri: `file://${res.path()}`,
        })
    }

   render() {
        const { uri } = this.state

        return (
            <View>
                <Svg
                    height="100"
                    width="100"
                    viewBox="0 0 100 100"
                >
                    <Image
                        x="0"
                        y="0"
                        width="100%"
                        height="100%"
                        preserveAspectRatio="xMidYMid slice"
                        href={!uri ? require('./placeholder.png') : { uri }}
                    />
                </Svg>
            </View>
        )
    }
}

@msand
Copy link
Collaborator

msand commented Feb 27, 2018

@ricklancee Oh, I didn't try in plain RN or iOS, just a Snack and Android. Having a filecache certainly seems like a great idea! Thanks for the example!

@sanealytics
Copy link

sanealytics commented Mar 9, 2018

@ricklancee that seems like a good solution.

However, I am having trouble loading RNFetchBlob. It says undefined is not an object (evaluating 'RNFetchBlob.DocumentDir').

Can you post your package.json so that I can make sure I'm trying with the same set of files? I even started a new project to make sure it wasn't something else.

Regards,

@ricklancee
Copy link

@sanealytics i pasted the code from a typescript project so it might not be 100% working. Maybe check the RNFetchBlob docs if you installed it correctly https://github.com/wkh237/react-native-fetch-blob

im using versions:

    "react": "16.2.0",
    "react-native": "0.53.0",
    "react-native-svg": "^6.2.2",
    "react-native-fetch-blob": "^0.10.8",

@msand
Copy link
Collaborator

msand commented Mar 9, 2018

RN 0.54 now has Blob support and Expo will probably get in the next version later this month expo/expo#123
If you're trying this on expo, it won't work because it's a native dependency and requires linking.

@sanealytics
Copy link

ah, that's what it is... thanks.

@sanealytics
Copy link

sanealytics commented Mar 13, 2018

OK, I am where you are (I think) after ejecting and hooking things up to the Android simulator (on ubuntu). I am also matching your version numbers.

The good news is that it works. Unfortunately, it is unstable.

When I start the app, no image show up initially, upon refresh, fallback image shows up. But it never changes to the fetched image.

I then added am SVG text component to show the base uri.
Now on start, fallback image flashes and then fetched image shows up. This is the correct behavior.
However, if I refresh again, I either get a blank, base image or the correct image intermittently.

Here is the modestly modified code. I am using an android simulator now.

import React from 'react'
import { View } from 'react-native'
import RNFetchBlob from 'react-native-fetch-blob'
import { Svg, Image, Text } from 'react-native-svg'

export default class SVGImage extends React.Component {

    state = { uri: undefined }

    async componentWillMount() {
        const { targetURI } = this.props

        try {
            const res = await RNFetchBlob
               .config({
                  // add this option that makes response data to be stored as a file,
                  // this performs better
                  fileCache : true,
                  // by adding this option, the temp files will have a file extension
                   appendExt : 'jpg',
               })
              .fetch('GET', targetURI)

            this.setState({
                uri: `file://${res.path()}`,
            })
        } catch (error) {
            console.error(error)
        }
    }

   render() {
        const { uri } = this.state
        return (
            <Svg
                height="200"
                width="400"
                viewBox="0 0 100 100"
            >
                <Image
                    x="50%"
                    y="0"
                    width="25%"
                    height="100%"
                    preserveAspectRatio="xMidYMid slice"
                    href={!uri ? require('./image.jpg') : { uri }}
                />
                <Text
                    x="0"
                    y="100"
                    fontSize="5"
                    fill="black"
                    stroke="purple"
                    textAnchor="middle"
                >
                    { uri }
                </Text>
            </Svg>
        )
    }
}

You use the above component like so from the main app

            <SVGImage
                targetURI="https://i.imgur.com/nZXbSbh.jpg"
            />

I guess that having to show the <Text> to make it work is a clue, but don't know enough to see what it means.

Should there be a delay of some sort?

Regards

@ricklancee
Copy link

@sanealytics I had the same issue on android where the image would not get switched out once loaded. This was my work around: switching the image component out for a new one:
I don't know if this is a bug caused by react-native-svg or something else.

{!uri ? (
    <Image
        x="50%"
        y="0"
        width="25%"
        height="100%"
        preserveAspectRatio="xMidYMid slice"
        href={require('./image.jpg')}
    />
) : (
    <Image
        x="50%"
        y="0"
        width="25%"
        height="100%"
        preserveAspectRatio="xMidYMid slice"
        href={{ uri }}
    />
)}

@sanealytics
Copy link

hmm, unfortunately, I have the same behavior as before 😢

@nadude
Copy link

nadude commented Mar 15, 2018

#630

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants