DEV Community

Amr shadid
Amr shadid

Posted on

React zoom and pan with draggable elements

I just try to build drag-able elements then move them around the screen and zoom it using mouse events, So how we can implement that using React.

I was searching in npm.io to find a package that can provide those features. Finally, I found some packages that can implement what I want, for that, I want to share the outcome here and highlight how I make integrate these packages with each other.

Sql builder, finally result

The first chapter will explain how we can create draggable elements, is a great existing package called
react-draggable, This package is powerful that can provide draggable elements using JavaScript.

It's very easy to use and has powerful features.

The below code snippet explains how we can create drag-able elements. Draggable elements have powerful functions that are called when on-drag start or on end to perform some routine like update state or do something.

import * as React from 'react'
import Draggable from 'react-draggable'

export default function Table(props: ITableProps
                                    & ITableOptionsProps) {

    return (
        <Draggable onDrag={props.onDrag} onStop={props.onStop}>
            <div className='table'>

                <div className='table-name'>
                    <h3>{props.name}</h3>
                </div>

                {props.att.map((value,index)=>(

                    <div key={index} className='attribute' id={props.name+"."+value.name}>
                        <div className='element'><h3>{value.name}</h3></div>
                        <div className='element type'><h3>{value.type}</h3></div>
                        <div className='element null'><h3>{value.null}</h3></div>
                        <div className='element pk'>{value.pk?<h3>pk</h3>:null}</div>
                    </div>
                ))}
            </div>
        </Draggable>
    );}
Enter fullscreen mode Exit fullscreen mode

CSS:

.table{
  position: fixed;
  display: flex;
  flex-direction: column;
  cursor: move;
  align-items: center;
  background-color: transparent;
  min-width: 380px;
  min-height: 200px;
  border: 2px solid #9BA1A6;
  border-radius: 7px;
}
Enter fullscreen mode Exit fullscreen mode

the output of the above code block is div have style class called table <div className='table'> these table elements can drag around the page using mouse.

Now the second chapter explains how we can build a transform Wrapper that can provide zoom and pan, of course using the great package called react-zoom-pan-pinch, react-zoom-pan-pinch is a powerful package that provides transform wrapper, transform component, and zoom controlling features.

After we create drag-able elements now we need to contain these elements in the transform wrapper to enable zoom controlling and pan the elements as a group.

import * as React from 'react';
import { AppContext } from '../../context';
import Table from '../table';
import { 
TransformWrapper, 
TransformComponent 
} from "react-zoom-pan-pinch";


export default function Main(props: IMainProps) {
  const context = React.useContext(AppContext)
  const [isMoveable, setIsMoveable] = React.useState<boolean>(false);

  const onDrag = () => {
    setIsMoveable(true)
    //etc
  }
  const onStop = () => {
    setIsMoveable(false)
    //etc 

  }


  return (
    <>
      <TransformWrapper
        initialScale={1}
        disabled={isMoveable}
        minScale={.5}
        maxScale={1}
        limitToBounds={false}
        onPanning={updateXarrow}
        onZoom={updateXarrow}
        pinch={{ step: 5 }}
      >

        <TransformComponent 
          contentClass='main' 
          wrapperStyle={{ height: '100vh', width: '80vw' }}>


          {context?.database.schema.map((value, index) => (
            <Table 
              key={index} 
              name={value.name} 
              att={value.att} 
              onDrag={onDrag} 
              onStop={onStop}/>
          ))}

        </TransformComponent>
      </TransformWrapper>

    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

CSS for content on transform component:

.main{
  display: flex;
  flex-direction: row;
  position: absolute;
}
Enter fullscreen mode Exit fullscreen mode

we passed two functions to draggable element the first one is onDrag this function will perform when the user start drag element and the last one onStop is will perform when the user finished dragging element, The main ideas of using this function:

  • provide enable control for transform wrapper to fix a conflict between draggable elements and transform wrapper.

  • perform some updater functions like when we have an arrow between two draggable elements and we move one then we need to update arrow positions.

Now we have draggable elements and transform wrapper, you can visit sql builder tool on Github to get a full example with source code.

Oldest comments (2)

Collapse
 
ghanayemomar profile image
Ghanayem Omar

wow!
amazing

Collapse
 
ravulask profile image
ravulask

Could you please help me with this query.I am stuck with this issue: dev.to/ravulask/need-help-react-zo...