Simple Responsive Gallery Scale View using ReactJs

Simple Responsive Gallery Scale View using React.JS
Project: React Gallery v2
Author: Alex Boffey
Edit Online: View on CodePen
License: MIT

This ReactJS code project helps you to create a simple responsive gallery with a scale view. It fetches data from a JSON file, displays it in a gallery, and allows the user to view a larger version of each image when clicked.

How to Create Simple Responsive Gallery Scale View using ReactJs

First of all, load the Normalize CSS by adding the following CDN link into the head tag of your HTML document.

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">

Now, create a div element with an id attribute “app” in the HTML:

<div id="app"></div>

Style the image gallery using the following CSS styles:

@import 'https://fonts.googleapis.com/css?family=Oswald:300|Slabo+27px';
body, html, #app {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

:root {
  font-family: "Slabo 27px";
  font-size: 14px;
  color: #333333;
}

@media screen and (min-width: 768px) {
  :root {
    font-size: 16px;
  }
}
@media screen and (min-width: 1024px) {
  :root {
    font-size: 18px;
  }
}
@media screen and (min-width: 1440px) {
  :root {
    font-size: 23px;
  }
}
.gallery {
  display: flex;
  flex-flow: row wrap;
  justify-content: center;
  padding: 34px;
}

.gallery-tile {
  min-width: 200px;
  max-width: 28vw;
  margin: 0.25em;
  overflow: hidden;
  position: relative;
  cursor: pointer;
}
.gallery-tile img {
  width: 100%;
  height: 100%;
  transition: transform 300ms ease-in-out, filter 300ms ease-in-out;
}
.gallery-tile .picture-info {
  position: absolute;
  z-index: 1;
  color: #ffffff;
  width: 100%;
  height: 100%;
  display: flex;
  flex-flow: column nowrap;
  justify-content: center;
  align-items: flex-start;
  opacity: 0;
  transition: opacity 300ms ease-in-out, filter 300ms ease-in-out;
}
.gallery-tile .picture-info > * {
  margin: 0.5rem 1.25rem;
}
.gallery-tile .picture-info h2 {
  font-family: "Oswald";
  font-size: 2.5rem;
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
.gallery-tile:hover img {
  transform: scale(1.1);
  filter: brightness(80%);
}
.gallery-tile:hover .picture-info {
  opacity: 1;
}

.imageview-wrapper {
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.imageview {
  display: flex;
  justify-content: center;
}

.imageview > * {
  margin: 3em;
}

.imageview-image {
  width: 25em;
  height: 25em;
  box-shadow: 0 20px 40px -5px rgba(66, 66, 66, 0.7);
}

.imageview-info {
  max-width: 260px;
  text-align: right;
  position: relative;
}
.imageview-info button {
  font-family: "Oswald";
  font-size: 1.5rem;
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: #e74c3c;
  cursor: pointer;
  border: none;
  background: none;
  outline: none;
  margin: 0;
  padding: 0;
  position: absolute;
  top: -2em;
  right: -1em;
}
.imageview-info button:hover {
  -webkit-animation: swell 300ms ease-in-out;
          animation: swell 300ms ease-in-out;
}
.imageview-info h2 {
  font-family: "Oswald";
  font-size: 2.5rem;
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-top: 0;
}
.imageview-info h3 {
  font-family: "Oswald";
  font-size: 1.5rem;
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
.imageview-info ul {
  list-style: none;
}

.fadeIn {
  -webkit-animation: fade 300ms ease-in-out forwards;
          animation: fade 300ms ease-in-out forwards;
}

@-webkit-keyframes fade {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

@keyframes fade {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
@-webkit-keyframes swell {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.3);
  }
  100% {
    transform: scale(1);
  }
}
@keyframes swell {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.3);
  }
  100% {
    transform: scale(1);
  }
}

Load the React JS by adding the following CDN Links by adding before closing the body tag:

<script src='https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js'></script>

Finally, add the following React JavaScript function to your project:

function _extends() {_extends = Object.assign || function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;};return _extends.apply(this, arguments);}class App extends React.Component {
  constructor() {
    super();
    this.state = {
      data: [],
      activeID: 0,
      imageView: false };

  }
  componentWillMount() {
    this._loadData('https://s3-us-west-2.amazonaws.com/s.cdpn.io/735173/rpg-2-data.json');
  }
  componentWillUnmount() {
    this._loadData.abort();
  }
  // Fetch data, then clone it to state using destructuring
  // XHR Fallback
  _loadData(url) {
    fetch(url, {
      method: 'GET' }).

    then(response => response.json()).
    then(json => this.setState({
      data: [...json.gallery] })).

    catch(err => {
      console.log(err.message);
      try {
        const xhr = new XMLHttpRequest();
        xhr.open('GET', url);
        xhr.responseType = 'json';

        xhr.onload = () => {
          let json = xhr.response;
          this.setState({
            data: [...json.gallery] });

        };

        xhr.onerror = () => {
          throw new Error('XMLHttpRequest Failed...');
        };

        xhr.send();
      } catch (e) {
        console.log(e.message);
      }
    });
  }
  _openImageView(id) {
    this.setState({
      activeID: id,
      imageView: true });

  }
  _closeImageView() {
    this.setState({
      imageView: false });

  }
  render() {
    return /*#__PURE__*/(
      React.createElement("div", { className: "wrapper" },

      this.state.imageView ? /*#__PURE__*/
      React.createElement(ImageView, _extends({}, this.state.data[this.state.activeID], {
        _closeImageView: this._closeImageView.bind(this) })) : /*#__PURE__*/

      React.createElement(Gallery, { data: this.state.data,
        _openImageView: this._openImageView.bind(this) })));



  }}


class ImageView extends React.Component {
  render() {
    return /*#__PURE__*/(
      React.createElement("div", { className: "imageview-wrapper fadeIn" }, /*#__PURE__*/
      React.createElement("div", { className: "imageview" }, /*#__PURE__*/
      React.createElement(Image, { CSSClass: "imageview-image",
        src: this.props.src,
        alt: this.props.name }), /*#__PURE__*/
      React.createElement("div", { className: "imageview-info" }, /*#__PURE__*/
      React.createElement("button", { className: "imageview-close", onClick: this.props._closeImageView }, "x"), /*#__PURE__*/
      React.createElement("h2", null, this.props.name), /*#__PURE__*/
      React.createElement("p", null, this.props.desc), /*#__PURE__*/
      React.createElement("h3", null, "Tags"), /*#__PURE__*/
      React.createElement("ul", null,
      this.props.tags.map(tag => /*#__PURE__*/React.createElement("li", null, tag)))))));





  }}


class Gallery extends React.Component {
  render() {
    return /*#__PURE__*/(
      React.createElement("div", { className: "gallery fadeIn" },

      this.props.data.map((data) => /*#__PURE__*/
      React.createElement(Tile, { key: data.id,
        id: data.id,
        src: data.src,
        name: data.name,
        desc: data.desc,
        _openImageView: this.props._openImageView }))));




  }}


class Tile extends React.Component {
  _handleClick() {
    this.props._openImageView(this.props.id);
  }
  render() {
    return /*#__PURE__*/(
      React.createElement("div", { className: "gallery-tile", onClick: this._handleClick.bind(this) }, /*#__PURE__*/
      React.createElement("div", { className: "picture-info" }, /*#__PURE__*/
      React.createElement("h2", null, this.props.name)), /*#__PURE__*/


      React.createElement(Image, {
        CSSClass: "tile-image",
        src: this.props.src,
        alt: this.props.name })));


  }}


const Image = (props) => /*#__PURE__*/
React.createElement("img", {
  className: props.CSSClass,
  src: props.src,
  alt: props.name });


// Render app
ReactDOM.render( /*#__PURE__*/React.createElement(App, null), document.getElementById('app'));

Code Explanation

  • function _extends() { ... } is a helper function used to create a new object that combines the properties of two or more objects.
  • class App extends React.Component { ... } defines the main component of the application. The component has three states: data, which contains an array of image information; activeID, which tracks the index of the image that is currently being viewed in the larger view; and imageView, which determines whether the larger view is visible or not. The component also defines several methods for handling image clicks and fetching data.
  • componentWillMount() { ... } is a React lifecycle method that is called before the component is mounted to the DOM. In this case, it calls the _loadData() method to fetch image data from a JSON file.
  • componentWillUnmount() { ... } is another React lifecycle method that is called before the component is unmounted from the DOM. In this case, it aborts the current data fetch if it is still in progress.
  • _loadData(url) { ... } is a method that fetches image data from the provided URL. If the fetch is successful, the data is saved to the data state of the App component. If the fetch fails, it falls back to using an XMLHttpRequest to fetch the data.
  • _openImageView(id) { ... } is a method that sets the activeID and imageView states when an image is clicked, triggering the display of the larger view.
  • _closeImageView() { ... } is a method that sets the imageView state to false, hiding the larger view.
  • class ImageView extends React.Component { ... } is a component that displays the larger image view. It takes in props including the image source, name, and description, as well as a method for closing the view.
  • class Gallery extends React.Component { ... } is a component that displays a grid of thumbnail images. It takes in an array of image data and a method for handling clicks on the images.
  • class Tile extends React.Component { ... } is a component that displays a single thumbnail image. It takes in the image source, name, and a method for handling clicks.
  • const Image = (props) => ... is a functional component that displays an image with the given source and alt text.
  • ReactDOM.render(...) is the last line of the code and renders the top-level App component to the DOM.

That’s all! hopefully, you have successfully created Simple Responsive Gallery Scale View using ReactJs. If you have any questions or suggestions, feel free to comment below.

Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply