DEV Community

KenjiGoh
KenjiGoh

Posted on

3 2

React - Image Editor

React - Image Editor

This post is inspired by this npm library react-image-pan-zoom-rotate

Instead of reading this, you can simply install the library add the following lines of code to the App.js.

import PanViewer from "react-image-pan-zoom-rotate";
<PanViewer image={imageURL} alt="cool" />
Enter fullscreen mode Exit fullscreen mode

Alternatively, let's try creating our own component.

I have rewritten the code using React useState hooks and styled-components, but only with rotate-left and flip horizontal or vertical options.

1. Create the styled-components wrappers

I like to use styled-components as we can pass in props.

import React, { useState } from "react";
import ReactDOM from "react-dom";
import styled from "styled-components";

const ToolBarContainer = styled.div`
  position: absolute;
  right: 20%;
  z-index: 2;
  top: 20px;
  user-select: none;
  border-radius: 2px;
  background: rgb(255, 255, 255);
  box-shadow: rgb(53 67 93 / 32%) 0px 2px 6px;
`;

const ToolBarItem = styled.div`
  text-align: center;
  cursor: pointer;
  height: 40px;
  width: 40px;
  border-bottom: 1px solid rgb(204, 204, 204);
`;

// Main part is here, where we manipulate the image by passing in props to transform it's style
const ImgContainer = styled.img`
  width: 500px;
  transform: scaleY(${(props) => props.flipY}) scaleX(${(props) => props.flipX})
    rotate(${(props) => props.rotation * 90}deg)
`;

// this is not styled-components, just for styling of the fas-icons in the toolbars box
const iconStyle = {
  height: "100%",
  width: "100%",
  padding: 10,
  boxSizing: "border-box",
};

Enter fullscreen mode Exit fullscreen mode

2. Create the React Components

Define useState hooks and create a ImageContainer and ToolbarContainer.

const ImagePortal = (props) => {
  const [flipX, setFlipX] = useState(1);
  const [flipY, setFlipY] = useState(1);
  const [rotation, setRotation] = useState(0);

  const flipImageX = () => {
    if (flipX === 1) {
      setFlipX(-1);
    }
    if (flipX === -1) {
      setFlipX(1);
    }
  };

  const flipImageY = () => {
    if (flipY === 1) {
      setFlipY(-1);
    }
    if (flipY === -1) {
      setFlipY(1);
    }
  };

  const rotateLeft = () => {
    if (rotation === -3) {
      setRotation(0);
    } else {
      setRotation(rotation - 1);
    }
  };

  const resetAll = () => {
    setRotation(0);
    setFlipY(1);
    setFlipX(1);
  };

  return(
    <>
      <ImgContainer
        src={props.image}
        alt="test"
        rotation={rotation}
        flipX={flipX}
        flipY={flipY}
      />

      <ToolBarContainer>
        <ToolBarItem>
          <i
            className="fas fa-rotate-left"
            onClick={rotateLeft}
            style={iconStyle}
          ></i>
        </ToolBarItem>

        <ToolBarItem>
          <i
            className="fa-solid fa-arrows-left-right"
            onClick={flipImageX}
            style={iconStyle}
          ></i>
        </ToolBarItem>

        <ToolBarItem>
          <i
            className="fa-solid fa-arrows-up-down"
            onClick={flipImageY}
            style={iconStyle}
          ></i>
        </ToolBarItem>

        <ToolBarItem>
          <i className="fas fa-repeat" onClick={resetAll} style={iconStyle}></i>
        </ToolBarItem>
      </ToolBarContainer>
    </>
  );
};

export default ImagePortal;
Enter fullscreen mode Exit fullscreen mode

3. Import to App.js

Now we just need to import the ImagePortal component into App.js

import styled from "styled-components";
import ImagePortal from "./components/ImagePortal";

// image url from unsplash
const imageURL =
  "https://images.unsplash.com/photo-1640622300930-6e8daa98536f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1772&q=80";

const Container = styled.div`
  display: flex;
  margin: auto;
  width: 60vmin;
`;

const App = () => {
  return (
    <Container>
      <ImagePortal image={imageURL} />
    </Container>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

End Result

Image description

Sentry blog image

How to reduce TTFB

In the past few years in the web dev world, we’ve seen a significant push towards rendering our websites on the server. Doing so is better for SEO and performs better on low-powered devices, but one thing we had to sacrifice is TTFB.

In this article, we’ll see how we can identify what makes our TTFB high so we can fix it.

Read more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs