i'm setting my state after calculating it in mouseup and mouse leave event but it's not updating it how to solve in mouseup and mouse leave
Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state.
onMouseMove = (e) => {
if (!this.isDown) {
return;
}
e.preventDefault();
var x = e.pageX - this.slider.current.offsetLeft;
var walk = x - this.startX;
this.startX = x;
var z = walk;
var finalValue = this.state.left + (z / 3);
finalValue = Math.floor(finalValue * 100) / 100;
this.setState({ left: finalValue }, () => { });
this.setState({ percent: false })
}
onMouseLeave = () => {
this.isDown = false;
var left = this.state.left;
for (let i = 0; i < 6; i++) {
this.el = 306*[i]
console.log(this.el);
if (left<=this.el) {
this.setState({left:this.el},()=>{})
// return
}
console.log(this.state.left);
}
}
onMouseUp = () => {
this.isDown = false;
this.slider.current.style.cursor = 'pointer';
var left = this.state.left;
for (let i = 0; i < 6; i++) {
this.el = 306*[i]
console.log(this.el);
if (left<=this.el) {
this.setState({left:this.el},()=>{})
// return
}
console.log(this.state.left);
}
}
render() {
return (
<div className="slider-wrapper" >
<div onMouseDown={this.onMouseDown}
style={this.state.percent ? this.goLeftPercent() : this.mouseMove()}
onMouseUp={this.onMouseUp} onMouseLeave={this.onMouseLeave}
onMouseMove={this.onMouseMove} ref={this.slider} className="slider-container">
)
}
If I understand correctly you can try the below changes.
Constructor
constructor() {
super();
this.onMouseLeave = this.onMouseLeave.bind(this);
this.onMouseUp = this.onMouseUp.bind(this);
}
Render()
<li onMouseUp={this.onMouseUp} onMouseLeave={this.onMouseLeave} >
Related
Here's Mozilla's code for handling touch gestures, such as two finger pinch/zoom, etc.
https://github.com/mdn/dom-examples/blob/main/touchevents/Multi-touch_interaction.html
And here is the live demo:
https://mdn.github.io/dom-examples/touchevents/Multi-touch_interaction.html
(This will only work on mobile—or at least it doesn't work on my Macbook Chrome browser.
I'm trying to replicate the same output using React. Here's what I have:
import React, { useState, useEffect } from 'react';
const TouchEventsContainer = () => {
const [logEvents, setLogEvents] = useState(false);
const [tpCache, setTpCache] = useState([]);
const [logText, setLogText] = useState("");
const [testText, setTestText] = useState("Tap Swipe");
const enableLog = () => {
setLogEvents(!logEvents);
setTestText(logText);
};
const clearLog = () => setLogText('');
const log = (name, ev, printTargetIds) => {
let s = `${name}: touches = ${ev.touches.length} ; targetTouches = ${ev.targetTouches.length} ; changedTouches = ${ev.changedTouches.length}`;
if (printTargetIds) {
s += "";
for (var i = 0; i < ev.targetTouches.length; i++) {
s += `... id = ${ev.targetTouches[i].identifier} <br>`;
}
}
setLogText((prevLogText) => prevLogText + s + "<br>");
};
const updateBackground = (ev) => {
switch (ev.targetTouches.length) {
case 1:
ev.target.style.background = "yellow";
break;
case 2:
ev.target.style.background = "pink";
break;
default:
ev.target.style.background = "lightblue";
}
}
const handlePinchZoom = (ev) => {
if (ev.targetTouches.length === 2 && ev.changedTouches.length === 2) {
let point1 = -1, point2 = -1;
for (let i = 0; i < tpCache.length; i++) {
if (tpCache[i].identifier === ev.targetTouches[0].identifier) point1 = i;
if (tpCache[i].identifier === ev.targetTouches[1].identifier) point2 = i;
}
if (point1 >= 0 && point2 >= 0) {
let diff1 = Math.abs(tpCache[point1].clientX - ev.targetTouches[0].clientX);
let diff2 = Math.abs(tpCache[point2].clientX - ev.targetTouches[1].clientX);
const PINCH_THRESHHOLD = ev.target.clientWidth / 10;
if (diff1 >= PINCH_THRESHHOLD && diff2 >= PINCH_THRESHHOLD)
ev.target.style.background = "green";
} else {
setTpCache([]);
}
}
}
const startHandler = (ev) => {
ev.preventDefault();
if (ev.targetTouches.length === 2) {
const newTpCache = [...tpCache];
for (let i = 0; i < ev.targetTouches.length; i++) {
newTpCache.push(ev.targetTouches[i]);
}
setTpCache(newTpCache);
}
if (logEvents) {
log("touchStart", ev, true);
}
updateBackground(ev);
};
const moveHandler = (ev) => {
ev.preventDefault();
if (logEvents) {
log("touchMove", ev, false);
}
if (!(ev.touches.length === 2 && ev.targetTouches.length === 2)) {
updateBackground(ev);
}
ev.target.style.outline = "dashed";
handlePinchZoom(ev);
};
const endHandler = (ev) => {
ev.preventDefault();
if (logEvents) {
log(ev.type, ev, false);
}
if (ev.targetTouches.length === 0) {
ev.target.style.background = "white";
ev.target.style.outline = "1px solid black";
}
};
const setHandlers = (name) => {
const el = document.getElementById(name);
el.ontouchstart = startHandler;
el.ontouchmove = moveHandler;
el.ontouchcancel = endHandler;
el.ontouchend = endHandler;
};
useEffect(() => {
setHandlers("target1");
setHandlers("target2");
setHandlers("target3");
setHandlers("target4");
}, []);
return (
<>
<h1>Multi-touch interaction</h1>
<div id="target1">{testText}</div>
<div id="target2"> Tap, Hold or Swipe me 2</div>
<div id="target3"> Tap, Hold or Swipe me 3</div>
<div id="target4"> Tap, Hold or Swipe me 4</div>
<button id="log" onClick={() => enableLog()}>Start/Stop event logging</button>
<button id="clearlog" onClick={() => clearLog()}>Clear the log</button>
<p></p>
<div>{logText}</div>
</>
);
};
export default TouchEventsContainer;
I have 2 problems:
My log output (currently in a ) doesn't produce anything. I think it's because my string contains HTML. I tried using "dangerousInnerHTML" and some other things, but to no avail.
The two finger pinch-zoom (when background color turns green) doesn't seem to be detected.
What is wrong with my React conversion?
Also I'm currently rendering my TouchEventsContainer within the context of a different JS view (on my app) for testing, but I don't think that's the issue.
How to target multiple tables with different ids in jquery and make them use the same function for drag and drop rows of the data table. I have 7 tables with different ids in the same page. To make the rows draggable I am using the below mentioned queries. I want to target all the 7 tables to work in similar way. Thank You
"use strict";
const table = document.getElementById('mytable');
const tbody = table.querySelector('tbody');
var currRow = null,
dragElem = null,
mouseDownX = 0,
mouseDownY = 0,
mouseX = 0,
mouseY = 0,
mouseDrag = false;
function init() {
bindMouse();
}
function bindMouse() {
document.addEventListener('mousedown', (event) => {
if (event.button != 0) return true;
let target = getTargetRow(event.target);
if (target) {
currRow = target;
addDraggableRow(target);
currRow.classList.add('is-dragging');
let coords = getMouseCoords(event);
mouseDownX = coords.x;
mouseDownY = coords.y;
mouseDrag = true;
}
});
document.addEventListener('mousemove', (event) => {
if (!mouseDrag) return;
let coords = getMouseCoords(event);
mouseX = coords.x - mouseDownX;
mouseY = coords.y - mouseDownY;
moveRow(mouseX, mouseY);
});
document.addEventListener('mouseup', (event) => {
if (!mouseDrag) return;
currRow.classList.remove('is-dragging');
table.removeChild(dragElem);
dragElem = null;
mouseDrag = false;
});
}
function swapRow(row, index) {
let currIndex = Array.from(tbody.children).indexOf(currRow),
row1 = currIndex > index ? currRow : row,
row2 = currIndex > index ? row : currRow;
tbody.insertBefore(row1, row2);
}
function moveRow(x, y) {
dragElem.style.transform = "translate3d(" + x + "px, " + y + "px, 0)";
let dPos = dragElem.getBoundingClientRect(),
currStartY = dPos.y, currEndY = currStartY + dPos.height,
rows = getRows();
for (var i = 0; i < rows.length; i++) {
let rowElem = rows[i],
rowSize = rowElem.getBoundingClientRect(),
rowStartY = rowSize.y, rowEndY = rowStartY + rowSize.height;
if (currRow !== rowElem && isIntersecting(currStartY, currEndY, rowStartY, rowEndY)) {
if (Math.abs(currStartY - rowStartY) < rowSize.height / 2)
swapRow(rowElem, i);
}
}
}
function addDraggableRow(target) {
dragElem = target.cloneNode(true);
dragElem.classList.add('draggable-table__drag');
dragElem.style.height = getStyle(target, 'height');
dragElem.style.background = getStyle(target, 'backgroundColor');
for (var i = 0; i < target.children.length; i++) {
let oldTD = target.children[i],
newTD = dragElem.children[i];
newTD.style.width = getStyle(oldTD, 'width');
newTD.style.height = getStyle(oldTD, 'height');
newTD.style.padding = getStyle(oldTD, 'padding');
newTD.style.margin = getStyle(oldTD, 'margin');
}
table.appendChild(dragElem);
let tPos = target.getBoundingClientRect(),
dPos = dragElem.getBoundingClientRect();
dragElem.style.bottom = ((dPos.y - tPos.y) - tPos.height) + "px";
dragElem.style.left = "-1px";
document.dispatchEvent(new MouseEvent('mousemove',
{ view: window, cancelable: true, bubbles: true }
));
}
function getRows() {
return table.querySelectorAll('tbody tr');
}
function getTargetRow(target) {
let elemName = target.tagName.toLowerCase();
if (elemName == 'tr') return target;
if (elemName == 'td') return target.closest('tr');
}
function getMouseCoords(event) {
return {
x: event.clientX,
y: event.clientY
};
}
function getStyle(target, styleName) {
let compStyle = getComputedStyle(target),
style = compStyle[styleName];
return style ? style : null;
}
function isIntersecting(min0, max0, min1, max1) {
return Math.max(min0, max0) >= Math.min(min1, max1) &&
Math.min(min0, max0) <= Math.max(min1, max1);
}
init();
instead of using a static table variable, could you add an event to target the table that user is pointing to. Something like, if user hover on table 1, pass it to the function. Because obviously the user only works with 1 table at a time, unless you want user to move rows between tables
I have two events drag start and drag end. At the time of drag start I am deciding whether to move it or copy depending on some logic and setSelectedElement is running and setting the new element to it but as you can see console of new element in drag end and console for previously selected in drag start are both empty.
after some debugging, I found out it is turning to an empty string supplied in the very beginning of use state.
App.js
export default function App() {
const [selectedElement, setSelectedElement] = useState("");
const [diffX, setDiffX] = useState(0);
const [diffY, setDiffY] = useState(0);
const [group, setGroup] = useState([]);
useEffect(() => {
console.log("selected element changed");
}, [selectedElement]);
const handleDragStart = (event) => {
console.log("drag start ");
// console.log("class list", event.currentTarget.classList);
console.log("previous selected element is ", selectedElement);
let functionalityType = "";
let elementSelected = "";
let classList = event.currentTarget.classList;
for (let i = 0; i < classList.length; i++) {
//move element
if (classList[i].includes("group")) {
functionalityType = "move";
break;
}
}
if (functionalityType !== "move") {
console.log("inside copy");
elementSelected = event.currentTarget.cloneNode(true);
elementSelected.style.position = "absolute";
elementSelected.addEventListener("dragstart", handleDragStart);
elementSelected.addEventListener("dragend", handleDragEnd);
} else {
console.log("inside move");
elementSelected = event.currentTarget;
// console.log("event current target", event.currentTarget);
}
setDiffX(event.clientX - event.currentTarget.getBoundingClientRect().left);
setDiffY(event.clientY - event.currentTarget.getBoundingClientRect().top);
setSelectedElement(elementSelected);
};
const handleDragEnd = (event) => {
console.log("drag end");
let newElement = selectedElement;
console.log("new element is", newElement);
newElement.style.top = event.clientY - diffY + "px";
newElement.style.left = event.clientX - diffX + "px";
document.getElementById("MidArea").appendChild(newElement);
}
return (
<div
draggable={true}
onDragStart={props.handleDragStart}
onDragEnd={props.handleDragEnd}
className="draggable"
>);
}
Is there any reason you're doing setSelectedElement(elementSelected); outside else statement
Your code lacks some details to debug and find the missing piece however, drag and drop, I had this implemented sometime back, try the below
const stopDrag = () => {
document.onmouseup = null;
document.onmousemove = null;
};
export const dragComponent = (dragRef) => {
let coordinateOne = 0;
let coordinateTwo = 0;
let coordinateThree = 0;
let coordinateFour = 0;
const dragHandle = dragRef.current;
const elementDrag = (event) => {
event.preventDefault();
coordinateOne = coordinateThree - event.clientX;
coordinateTwo = coordinateFour - event.clientY;
coordinateThree = event.clientX;
coordinateFour = event.clientY;
dragHandle.style.top = `${dragHandle.offsetTop - coordinateTwo}px`;
dragHandle.style.left = `${dragHandle.offsetLeft - coordinateOne}px`;
};
const dragDown = (event) => {
event.preventDefault();
coordinateThree = event.clientX;
coordinateFour = event.clientY;
document.onmouseup = stopDrag;
document.onmousemove = elementDrag;
};
dragHandle.onmousedown = dragDown;
};
function MyComponent(){
const dragRef = useRef();
useEffect(() => {
dragComponent(dragRef);
}, []);
return (
<div draggable ref={dragRef}>
<h1> I am draggable..drag me around</h1>
</div>
)
}
Did you try this:
setDiffX(event.clientX - event.currentTarget.getBoundingClientRect().left);
setDiffY(event.clientY - event.currentTarget.getBoundingClientRect().top);
dragElementRef.current = elementSelected;
setSelectedElement(elementSelected);
};
let dragElementRef = useRef(selectedElement);
....
....
const handleDragEnd = (event) => {
//setTimeout(() => {
console.log("drag end");
let newElement = dragElementRef.current;
console.log("new element is", newElement);
newElement.style.top = event.clientY - diffY + "px";
newElement.style.left = event.clientX - diffX + "px";
document.getElementById("MidArea").appendChild(newElement);
//},500);
}
What I think is happening is your handleDragEnd() is being called before the next render cycle with updated value of state exists.
Try adding a setTimeout to add some delay.
I have a custom cursor component based off Codrops https://tympanus.net/codrops/2019/01/31/custom-cursor-effects/.
I have it working nicely on every page except one, which is a portfolio page that dynamically shows/hides content based on the current state.
If I change states (show component not initially loaded + hide initial component OR hide component not initially loaded + show initially loaded content), the custom cursor no longer reacts to the class name.
I am showing/hiding the content based on the current state of the component.
I've tried to re "init" the cursor, but that causes problems with the size/position of the custom cursor.
I understand the Cursor.js doesn't know when to "look" for the new classes after the state change, but I can't figure out how to make it "watch" for the changes, and since re initializing the cursor isn't working, I'm not sure what I should try. Should I try an eventListener that forces the cursor to look at the classes again?
Ideally the custom cursor will interact with both dynamic and non-dynamic elements, but I'm at a point that I question if this is even possible.
Any advice would be greatly appreciated. Or if anyone has an example of a React Custom Cursor that works in this scenario, I'd love to check it out.
Portfolio.js
render() {
return (
<div>
<div className="cursor">
<div className="circle-cursor circle-cursor--inner"></div>
</div>
<canvas
className="circle-cursor circle-cursor--outer"
resize="true"
></canvas>
//CURSOR
<CustomCursor />
//SHOW ALL PROJECTS ON STATE CHANGE
{ this.state.showAllItems ?
<div className={styles.grid}>
{list.map(item => (
<div key={item.index} className={styles.grid__item}>
<a href="#/a" key={item.index} value={item.index} onClick={e => this.onClick(e, item)} >
<div key={item.index} className={styles.glitch + " portfolioLinkHover " + styles.glitchStyle1}>
<div className={styles.glitch__img + " img"} style={{background: 'url('+ item.imgSrc + ') no-repeat 50% 0'}}></div>
<div className={styles.glitch__img + " img"} style={{background: 'url('+ item.imgSrc + ') no-repeat 50% 0'}}></div>
</div>
</a>
<h2>{item.itemTitle} <span>{item.itemSubtitle}</span></h2>
</a>
</p>
</div>
))}
</div>
: null }
//SHOW PROJECT ON STATE CHANGE
{ this.state.currentProject ?
<div className={styles.projectContainer + " portfolioLinkHover"}>
<Project />
</div> : null }
</div>
);
}
Cursor.js
import React, {Component} from 'react';
import Util from "./utils/util";
import './styles/cursor.scss';
import TweenMax from 'gsap';
class CustomCursor extends Component{
constructor(props) {
super(props);
this.state = { isOn: this.props.isOn };
}
componentDidMount(){
if(this.state.isOn == "true"){
this.initHovers();
}
else{
this.initCursor();
this.initCanvas();
this.initHovers();
}
}
initCursor() {
this.clientX = -100;
this.clientY = -100;
this.innerCursor = document.querySelector(".circle-cursor--inner");
this.outerCursor = document.querySelector(".custom-cursor--outer");
this.outerCursorSpeed = 1;
this.lastX = 0;
this.lastY = 0;
this.isStuck = false;
this.showCursor = false;
const { paper } = window;
const unveilCursor = e => {
this.group.position = new paper.Point(e.clientX, e.clientY);
setTimeout(() => {
this.outerCursorSpeed = 0.2;
}, 100);
this.showCursor = true;
};
document.addEventListener("mousemove", unveilCursor);
document.addEventListener("mousemove", e => {
this.clientX = e.clientX;
this.clientY = e.clientY;
});
const render = () => {
TweenMax.set(this.innerCursor, {
x: this.clientX,
y: this.clientY
});
if (this.showCursor) {
document.removeEventListener("mousemove", unveilCursor);
}
requestAnimationFrame(render);
};
requestAnimationFrame(render);
}
initCanvas() {
const { paper, SimplexNoise } = window;
const canvas = document.querySelector(".circle-cursor--outer");
const shapeBounds = {
width: 75,
height: 75
};
paper.setup(canvas);
const strokeColor = "rgba(255, 0, 0, 0.5)";
const strokeWidth = 1;
const segments = 8;
const radius = 25;
const noiseScale = 150; // speed
const noiseRange = 4; // range of distortion
let isNoisy = false;
const polygon = new paper.Path.RegularPolygon(
new paper.Point(0, 0),
segments,
radius
);
polygon.strokeColor = strokeColor;
polygon.strokeWidth = strokeWidth;
polygon.smooth();
this.group = new paper.Group([polygon]);
this.group.applyMatrix = false;
const noiseObjects = polygon.segments.map(() => new SimplexNoise());
let bigCoordinates = [];
paper.view.onFrame = event => {
if (!this.isStuck) {
// move circle around normally
this.lastX = Util.lerp(this.lastX, this.clientX, this.outerCursorSpeed);
this.lastY = Util.lerp(this.lastY, this.clientY, this.outerCursorSpeed);
this.group.position = new paper.Point(this.lastX, this.lastY);
} else if (this.isStuck) {
// fixed position on a nav item
this.lastX = Util.lerp(this.lastX, this.stuckX, this.outerCursorSpeed);
this.lastY = Util.lerp(this.lastY, this.stuckY, this.outerCursorSpeed);
this.group.position = new paper.Point(this.lastX, this.lastY);
}
if (this.isStuck && polygon.bounds.width < shapeBounds.width) {
// scale up the shape
polygon.scale(1.08);
} else if (!this.isStuck && polygon.bounds.width > 30) {
// remove noise
if (isNoisy) {
polygon.segments.forEach((segment, i) => {
segment.point.set(bigCoordinates[i][0], bigCoordinates[i][1]);
});
isNoisy = false;
bigCoordinates = [];
}
// scale down the shape
const scaleDown = 0.92;
polygon.scale(scaleDown);
}
// while stuck and when big, do perlin noise
if (this.isStuck && polygon.bounds.width >= shapeBounds.width) {
isNoisy = true;
// first get coordinates of large circle
if (bigCoordinates.length === 0) {
polygon.segments.forEach((segment, i) => {
bigCoordinates[i] = [segment.point.x, segment.point.y];
});
}
// calculate noise value for each point at that frame
polygon.segments.forEach((segment, i) => {
const noiseX = noiseObjects[i].noise2D(event.count / noiseScale, 0);
const noiseY = noiseObjects[i].noise2D(event.count / noiseScale, 1);
const distortionX = Util.map(noiseX, -1, 1, -noiseRange, noiseRange);
const distortionY = Util.map(noiseY, -1, 1, -noiseRange, noiseRange);
const newX = bigCoordinates[i][0] + distortionX;
const newY = bigCoordinates[i][1] + distortionY;
segment.point.set(newX, newY);
});
}
// hover state for main nav items
if (this.fillOuterCursor && polygon.fillColor !== strokeColor) {
polygon.fillColor = strokeColor;
polygon.strokeColor = "transparent";
} else if (!this.fillOuterCursor && polygon.fillColor !== "transparent") {
polygon.strokeColor = "rgba(255, 0, 0, 0.5)";
polygon.fillColor = "transparent";
}
// hover state for portfolio nav items
if (this.isOnPortfolioItem) {
polygon.fillColor = strokeColor;
polygon.strokeColor = "rgba(255, 226, 0, 0.5)";
// scale up the shape
polygon.bounds.width = 45;
polygon.bounds.height = 45;
} else if (!this.fillOuterCursor) {
polygon.strokeColor = "rgba(255, 0, 0, 0.5)";
polygon.fillColor = "transparent";
}
polygon.smooth();
};
}
initHovers() {
const handleMouseEnter = e => {
const navItem = e.currentTarget;
const navItemBox = navItem.getBoundingClientRect();
this.stuckX = Math.round(navItemBox.left + navItemBox.width / 2);
this.stuckY = Math.round(navItemBox.top + navItemBox.height / 2);
this.isStuck = true;
};
const handleMouseLeave = () => {
this.isStuck = false;
};
const linkItems = document.querySelectorAll(".browser-window__link");
linkItems.forEach(item => {
item.addEventListener("mouseenter", handleMouseEnter);
item.addEventListener("mouseleave", handleMouseLeave);
});
const mainNavItemMouseEnter = () => {
this.outerCursorSpeed = 0.8;
this.fillOuterCursor = true;
};
const mainNavItemMouseLeave = () => {
this.outerCursorSpeed = 0.2;
this.fillOuterCursor = false;
};
const portfolioItems = document.querySelectorAll(".portfolioLinkHover");
portfolioItems.forEach(item => {
item.addEventListener("mouseenter", handleLinkEnter);
item.addEventListener("mouseleave", handleLinkLeave);
});
}
render() {
return (
<div></div>
);
}
}
export default CustomCursor;
i'm making a drag able slider on mouse move i'm taking a starting mouse position and subtracting it with current mouse position and setting it to state and adding it to element scroll Left but it's not working
onMouseMove = (e) => {
if (!this.isDown) {
return
}
e.preventDefault();
var x = e.pageX - this.slider.current.offsetLeft;
var walk = this.startX - x;
var z = this.scrollLeft - walk;
console.log( this.slider.current.scrollLeft);
this.setState({ left: this.state.left + z })
var slider = document.querySelector('.slider-container');
// console.log(slider);
slider.scrollLeft=this.state.left
}
This is because the this.setState is not executed directly. It is queued to be processed by react. The callback can be used to determine when it has finished:
onMouseMove = (e) => {
if (!this.isDown) {
return
}
e.preventDefault();
var x = e.pageX - this.slider.current.offsetLeft;
var walk = this.startX - x;
var z = this.scrollLeft - walk;
console.log( this.slider.current.scrollLeft);
this.setState({ left: this.state.left + z }, () => {
var slider = document.querySelector('.slider-container');
// console.log(slider);
this.slider.scrollLeft=this.state.left
})
}
Checkout the following example:
import React from "react";
import ReactDOM from "react-dom";
class App extends React.Component {
p = 0;
constructor(props) {
super(props);
this.state = {
left: 0
};
this.slider = React.createRef();
}
onMouseDown = e => {
e.persist();
this.isDown = true;
this.startX = e.pageX - this.slider.current.offsetLeft;
this.scrollLeft = this.slider.current.scrollLeft;
this.slider.current.style.cursor = "grabbing";
// console.log(
// e.pageX - this.slider.current.offsetLeft,
// this.slider.current.scrollLeft
// );
};
onMouseLeave = () => {
this.isDown = false;
};
onMouseUp = () => {
this.isDown = false;
this.slider.current.style.cursor = "pointer";
};
onMouseMove = e => {
if (!this.isDown) {
return;
}
e.preventDefault();
var x = e.pageX - this.slider.current.offsetLeft;
var walk = (this.startX - x) / 20;
var z = this.slider.current.scrollLeft - walk;
this.setState({ left: this.state.left + z }, () => {
this.slider.current.scrollLeft = this.state.left;
});
};
goLeftPercent = () => {
return {
transform: `translatex(${this.p}px)`,
transition: "0.3s"
};
};
goLeft = () => {
if (this.p < -970) {
return;
}
this.p += -326;
this.setState({ left: this.p, percent: true });
};
goRight = () => {
if (this.p === 0) {
return;
}
this.p += 326;
this.setState({ left: this.p });
};
mouseMove = () => {
if (this.state.left > 0) {
this.setState({ left: 0 });
return;
} else if (this.state.left < -980) {
this.setState({ left: -980 });
return;
}
return {
transform: `translatex(${this.state.left}px)`
};
};
render() {
const slides = [
{ src: "", name: "Livingroom1" },
{ src: "", name: "Livingroom2" }
];
return (
<div className="slider">
<div className="slider-wrapper">
<div
onMouseDown={this.onMouseDown}
style={this.state.percent ? this.goLeftPercent() : this.mouseMove()}
onMouseUp={this.onMouseUp}
onMouseLeave={this.onMouseLeave}
onMouseMove={this.onMouseMove}
ref={this.slider}
className="slider-container test"
>
{slides.map(slide => (
<div className="slide">
<img src={slide.src} alt="" />
<div className="overlay">
<h1>{slide.name}</h1>
</div>
</div>
))}
</div>
</div>
<div className="slider-arrows">
<div onClick={this.goLeft} className="arrow-wrapper">
{" "}
Left
<div className="arrow-left">
<div className="arrow-top" /> <div className="arrow-bottom" />{" "}
</div>
</div>
<div onClick={this.goRight} className="arrow-right">
Right
</div>
</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
interactive demo: https://codesandbox.io/s/sad-murdock-8f766
Just use 'Ref.current.scrollLeft += anyvalue;' or 'Ref.current.scrollLeft -= anyvalue;' (use '+' to scroll right and '-' to scroll left.)
this works for me in React:-
const handlePrevBtnClick = () => {
Ref.current.scrollLeft -= 80;
}
const handleNextBtnClick = () => {
Ref.current.scrollLeft += 80;
}