最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React - Drag corner of element to resize contents - Stack Overflow

programmeradmin0浏览0评论

I'm working on a feature in my React project where when a user hovers over an element, which could contain an image or just text, a resize button appears in the top left corner and pressing down on that button while dragging the mouse will resize the element and it's contents accordingly.

I've already implemented showing the resize button on hover, but am having difficulty implementing the resizing feature.

For reference, I've attached a GIF of what I'm trying to implement. Resizing an Element

I'm working on a feature in my React project where when a user hovers over an element, which could contain an image or just text, a resize button appears in the top left corner and pressing down on that button while dragging the mouse will resize the element and it's contents accordingly.

I've already implemented showing the resize button on hover, but am having difficulty implementing the resizing feature.

For reference, I've attached a GIF of what I'm trying to implement. Resizing an Element

Share Improve this question asked Jun 17, 2020 at 19:21 ivyleaf57ivyleaf57 751 gold badge1 silver badge5 bronze badges 2
  • Show us what you've tried. The only problem I can think of is that you're showing the resize button onHover, and when you drag out of it, there's no more hover, because you're out of the frame, and your resize button is gone. – Pablo Recalde Commented Jun 17, 2020 at 19:29
  • I personnaly used a SubJX library. It works very well. github.com/nichollascarter/subjx – Matthew C Commented Aug 25, 2022 at 12:28
Add a comment  | 

2 Answers 2

Reset to default 16

If you've already added a resize button that sticks to the corner of the div to be resized:

  1. Listen for a mousedown event on the button
  2. In the listener,
    • store the starting size and click position
    • add a mousemove listener onMouseMove to document.body that tracks the cursor position
    • add a mouseup listener that removes mouseMove when the drag is released
  3. Use the changes in cursor position to resize the div appropriately.

Example:

const { useState } = React;

function Resizeable({ children }) {
  const [size, setSize] = useState({ x: 400, y: 300 });

  const handler = (mouseDownEvent) => {
    const startSize = size;
    const startPosition = { x: mouseDownEvent.pageX, y: mouseDownEvent.pageY };
    
    function onMouseMove(mouseMoveEvent) {
      setSize(currentSize => ({ 
        x: startSize.x - startPosition.x + mouseMoveEvent.pageX, 
        y: startSize.y - startPosition.y + mouseMoveEvent.pageY 
      }));
    }
    function onMouseUp() {
      document.body.removeEventListener("mousemove", onMouseMove);
      // uncomment the following line if not using `{ once: true }`
      // document.body.removeEventListener("mouseup", onMouseUp);
    }
    
    document.body.addEventListener("mousemove", onMouseMove);
    document.body.addEventListener("mouseup", onMouseUp, { once: true });
  };

  return (
    <div id="container" style={{ width: size.x, height: size.y }}>
      <button id="draghandle" type="button" onMouseDown={handler} >Resize</button>
    </div>
  );
}

ReactDOM.render(<Resizeable />, document.getElementById("root"));
#root {
  height: 100vh;
  width: 100vw;
}

#container {
  position: relative;
  background-color: lightpink;
  border: solid red 1px;
}

#draghandle {
  position: absolute;
  bottom: 0;
  right: 0;
  transform: translate(50%, 50%);
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

Note that only the mousedown event is applied to the button, and the other handlers are applied to document.body. This makes sure that quickly moving the cursor off the button doesn't cause events to be missed.

So you'll need three pieces of information to do this. The location of the mouse when it first clicked the resize handle, the location of the mouse as it moves and the elements height and width.

Start with getting the elements height and width:

const [height, setHeight] = useState({ height: 20 }); // initialise to 20px
const [dragging, setDragging] = useState(false);
/** -- snip -- **/
<img style={{ height }} /* snip */ />

With an image, html will automatically handle the scaling for you, so you only need to apply the height property and the width will automatically be scaled.

Now we need to get the position of the mouse onClick of the resize handle. I assume you already have the styling for your handle so we can ignore that:

const [mouseStart, setMouseStart] = useState({ x: 0, y: 0 });
/** -- snip -- */
<ResizeHandle 
    onMouseDown={e => {
      setDragging(true);
      setMouseStart({ x: e.offsetX, y: e.offsetY });
    }}
/> 

Then you need to listen to the mouseMove event and resize the img appropriately - This should be done in the parent component:

  <div
     onMouseMove={e => {
        if (dragging) {
          const pixelDifference = Math.max(mouseStart.x - e.offsetX, mouseStart.y - e.offsetY);
          setHeight(height + pixelDifference);
        }
     }}

     onMouseUp={() => setDragging(false)}
  >
     <img /* snip */ />
     <ResizeHandle /* snip */ />
  </div>
发布评论

评论列表(0)

  1. 暂无评论