9

I'm trying to implement a zoom function. onClick works fine, but I'd like to have it when I hold the zoom button down, it zooms continuously. How can I implement this with ReactJS?

Jquery: mousedown effect (while left click is held down) I was using this as a template, but onMousedown doesn't get registered according to console.log

<div className="zoomControl" >
                        <button className="zoomIn" onMouseDown={this.zoomIn}>+</button>
                        <button className="zoomOut" onClick={this.zoomOut}>-</button>
                </div>

zoomIn = () => {
    console.log('test');
    var self = this;
    this.timeout = setInterval(function(){
    // Do something continuously
        this.renderer.zoomIn();
    }, 100);

    return false;

};

zoomMouseUp = () => {
    clearInterval(this.timeout);
    return false;
};
Community
  • 1
  • 1
Tai
  • 426
  • 1
  • 8
  • 21

4 Answers4

10

You need to use both mouseUp and mouseDown. Start a time on mouseDown and call the zoom function with the timeout repeatedly and clear the time on mouseUp.

Here a demo with zoomIn and zoomOut to compare and better understand the algorithm.

Hope this helps!!

class Zoom extends React.Component {
   constructor(props) {
     super(props)
     this.state = {
       zoom: 1,
     }
     this.t = undefined
     this.start = 100
     this.repeat = this.repeat.bind(this)
     this.onMouseDown = this.onMouseDown.bind(this)
     this.onMouseUp = this.onMouseUp.bind(this)
     this.zoom = this.zoom.bind(this)
     this.zoomOut = this.zoomOut.bind(this)
   }
   zoom(){
     this.setState({zoom: this.state.zoom + 0.1})
   }
   repeat() {
     this.zoom()
     this.t = setTimeout(this.repeat, this.start)
     this.start = this.start / 2
   }

   onMouseDown() {
     this.repeat()
   }
   onMouseUp() {
     clearTimeout(this.t)
     this.start = 100
   }
   zoomOut(){
     this.setState({
       zoom: 1
     })
   }
  
  render() {
    return <div className="zoomControl" >
      <div className="zoom" style={{transform: 'scale('+ this.state.zoom +')'}}></div>
      <button className="zoomIn" onMouseUp={this.onMouseUp} onMouseDown={this.onMouseDown}>+</button>
      <button className="zoomOut" onClick={this.zoomOut}>-</button>
    </div>
   }
}
  
  ReactDOM.render(<Zoom/>, document.getElementById('app'))
body {
  overflow: hidden
}
.zoom {
  width: 20px;
  height: 20px;
  margin: 0 auto;
  background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Webwoman
  • 10,196
  • 12
  • 43
  • 87
Pranesh Ravi
  • 18,642
  • 9
  • 46
  • 70
3

If you have to do some kind of animation here, you're better off using requestAnimationFrame than setting intervals. I'd do it something like this.

class App extends React.Component {
    state = {
        value: 0,
        mousedown: false
    }

    zoom = () => {
        if (this.state.mousedown) {
            this.setState({ value: this.state.value + 1},
                () => { window.requestAnimationFrame(this.zoom) }
            )
        }
    }

    zoomIn = () => {
        window.requestAnimationFrame(this.zoom);
    }

    toggleMouseDown = () => {
        this.setState({
            mousedown: !this.state.mousedown
        });
        this.zoomIn()
    }

    render() {
        return(
            <div>
                <button
                    onMouseUp={this.toggleMouseDown}
                    onMouseDown={this.toggleMouseDown}>
                    Click me
                </button>
                {/* The rest of your component goes here */}
            </div>
        );
    }
}
Justin Smith
  • 346
  • 1
  • 3
  • 17
0

It's hard to get all of the context, but I'll try to give a relevant answer:

You don't have any property set to call zoomMouseUp when you release the button. I'd start with:

<button className="zoomIn" onMouseDown={this.zoomIn} onMouseUp={this.zoomMouseUp} onMouseOut={this.zoomMouseUp}>+</button>

You stated that it starts zooming, but doesn't stop. That makes me assume it's working, so that should probably fix it. I added the onMouseOut because if they press the button and move the mouse away without releasing it, it's going to continue.

There are a lot of ways to do this, but that's probably the most simple with what you have.

  • Also, if you're returning false from the events to try to stop it, that won't do anything, anymore in React. You need to get the event property and call event.stopPropagation() or event.preventDefault() if you are attempting to do either of those. – Donny Swany Oct 18 '16 at 18:32
  • When I do onClick={this.zoomIn} that works for a one time zoom. But onMouseDown doesn't get registered when I click it. Any reason why that might be? OnMouseUp does register. – Tai Oct 18 '16 at 18:32
0

My issue was due to right click being the primary click or some thing along the lines. It works fine as is.

Tai
  • 426
  • 1
  • 8
  • 21