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

Img: what's the best way to change image on hover? #14034

Closed
ZhenWang-Jen opened this issue May 14, 2019 · 7 comments
Closed

Img: what's the best way to change image on hover? #14034

ZhenWang-Jen opened this issue May 14, 2019 · 7 comments
Labels
stale? Issue that may be closed soon due to the original author not responding any more.

Comments

@ZhenWang-Jen
Copy link

Summary

When I use gatsby image component , I have a hard time of changing image when hovering on it. I find the official doc doesn't support props like regular react onMouseEnter or onMouseOut. So how would I achieve this or it's not currently supported?

Motivation

Overall, I want to show a gif image when hovering on a jpg/png image using gatsby image, so that I can keep it optimized rather than using normal dom.

@ZhenWang-Jen
Copy link
Author

Additional: even not sure if Gatsby supports gif format when I look at another issue.

@jonniebigodes
Copy link

@ZhenWang-Jen if you continue to read the document and you reach here , you get the answer to your question

@gillkyle
Copy link
Contributor

Correct that gatsby-image doesn't support gifs, but you can still use gifs inside of normal <img /> tags!

A possible solution could be loading an optimized jpg/png and just swapping the element that is displayed on hover.

@marcysutton
Copy link
Contributor

marcysutton commented May 14, 2019

To make the interaction keyboard accessible, you could add a button element that wraps the image and swap the source on click or something. It should probably indicate in text what the interaction is for, too (like "click for animated image")

@gatsbot
Copy link

gatsbot bot commented Jun 4, 2019

Hiya!

This issue has gone quiet. Spooky quiet. 👻

We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contributefor more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! 💪💜

@gatsbot gatsbot bot added the stale? Issue that may be closed soon due to the original author not responding any more. label Jun 4, 2019
@gatsbot
Copy link

gatsbot bot commented Jun 15, 2019

Hey again!

It’s been 30 days since anything happened on this issue, so our friendly neighborhood robot (that’s me!) is going to close it.

Please keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m HUMAN_EMOTION_SORRY. Please feel free to reopen this issue or create a new one if you need anything else.

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks again for being part of the Gatsby community!

@gatsbot gatsbot bot closed this as completed Jun 15, 2019
@eyalroth
Copy link
Contributor

eyalroth commented Jul 4, 2019

@ZhenWang-Jen I just encountered this problem when I wanted to implement a feature where I have two images -- one overlaying the other -- and a mouse move would change the size of the top image, so that basically the mouse move controls the overlay between the two images.

I found a rather simple solution to this, which is creating a div element next (sibling) to the images which will be "monitoring" the mouse events. This solution also has 2 major advantages over setting the "monitoring" on the images themselves:

  1. The area of the mouse events could be extended beyond the dimensions of the image. In my case this is crucial, since I want to let the user mouse over the (width) edges of my images and still affect the layout.
  2. What about mobile? In mobile realm, there is no mouse; however, there is touch, albeit it's a different event (both its type and its structure). You could add a div per event type and make each one appear only on relevant devices using CSS breakpoints (display: none for the div that doesn't fit the device size).

Here's how I used it in order to create a "profile image" component:

import React from "react"
import { StaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"
import './style.scss'

export const squareImage = graphql`
  fragment squareImage on File {
    childImageSharp {
        fluid(maxWidth: 145, maxHeight: 145, quality: 100) {
            ...GatsbyImageSharpFluid_noBase64
        }
    }
  }
`

class ProfileImg extends React.Component {
    constructor(props) {
        super(props)
        this.state = {backWidth: 0}
    }

    setBackWidth(newWidth) {
        this.setState({backWidth: newWidth})
    }


    render() {
        return (
        <StaticQuery
            query={graphql`
                query ProfileImgQuery {
                    front: file(relativePath: { eq: "icon2.png" }) {
                        ...squareImage
                    }
                    
                    back: file(relativePath: { eq: "icon.png" }) {
                        ...squareImage
                    }
                }
            `}
            render={data => this.renderWithQueryData(data)}
        />)
    }

    renderWithQueryData(data) {
        const { className, author } = this.props
        const _this = this

        function setupMove(div, eventType, extractCoordinates) {
            if (div) {
                div.addEventListener(eventType, (event) => {
                    const container = div.parentElement
                    const { x } = extractCoordinates(event)
                    const { left } = container.getBoundingClientRect()
                    const newWidth = x - left
                    _this.setBackWidth(Math.max(newWidth, 0))
                }, {once: true})
            }
        }
        
        function setupMouseMove(div) {
            setupMove(div, 'mousemove', (event) => {
                const { clientX: x, clientY: y } = event
                return {x, y}
            })
        }

        function setupTouchMove(div) {
            setupMove(div, 'touchmove', (event) => {
                const { clientX: x, clientY: y } = event.changedTouches[0]
                return {x, y}
            })
        }

        return (
            <div className={className}>
                    <div 
                        className="profile-img-container"
                        style={{
                            position: "relative",
                            height: "inherit"
                        }}
                    >
                        <div 
                            ref={setupMouseMove}
                            className="profile-img-mousemove"
                            style={{
                                width: "130%",
                                height: "100%",
                                left: "-15%",
                                position: "absolute",
                                zIndex: 1
                            }}
                        />
                        <div 
                            ref={setupTouchMove}
                            className="profile-img-touchmove"
                            style={{
                                width: "130%",
                                height: "100%",
                                left: "-15%",
                                position: "absolute",
                                zIndex: 1
                            }}
                        />
                        <Img
                            className="profile-img-front"
                            fluid={data.front.childImageSharp.fluid}
                            title={author}
                            alt={author}
                        />
                        <Img 
                            className="profile-img-back"
                            fluid={data.back.childImageSharp.fluid}
                            title={author}
                            alt={author}
                            style={{
                                position: "absolute",
                                width: "100%",
                                height: "100%",
                                top: 0,
                            }}
                            imgStyle={{
                                width: `${this.state.backWidth}px`,
                                objectPosition: "left",
                            }}
                        />
                    </div>
                </div>
        )
    }
}

export default ProfileImg

./style.scss:

@import "../../assets/scss/variables";
@import "../../assets/scss/mixins";

.profile-img {
    &-mousemove {
        display: none;
    }
}

@include breakpoint-sm {
    .profile-img {
        &-mousemove {
            display: unset;
        }
        &-touchmove {
            display: none;
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale? Issue that may be closed soon due to the original author not responding any more.
Projects
None yet
Development

No branches or pull requests

5 participants