Skip to content

Commit d230add

Browse files
Merge pull request #2 from mateusbslopes/feature/handle_multiple_touches
Feature/handle multiple touches
2 parents 48ff8ca + ff1f0f4 commit d230add

File tree

7 files changed

+75
-35
lines changed

7 files changed

+75
-35
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ A React carousel develop for the Scandiweb's React [developer test](./TEST_DESCR
55
## Table of content
66
- Usage
77
- Running
8+
- Known Issues
89

910
### Usage
1011
The component accepts the following params:
@@ -39,3 +40,5 @@ In order to run the example page locally on you computer (assuming that you alre
3940
- And to start the server:
4041
`yarn serve`
4142

43+
### Known Issues
44+
1. Multiple touches does not works correctly when one of the touches is not on the Carousel.

ROADMAP.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
1. Handle multiple touches
2-
- Be able to move 2 carousels on a touchable device
3-
2. Make it infinite scroll
4-
3. Add basic arrows when config:
1+
1. Make it infinite scroll
2+
2. Add basic arrows when config:
53
```jsx
64
<ReactCarousel
75
navigation={{
86
arrows: true,
97
}}
108
>...</ReactCarousel>
119
```
12-
4. Permit custom dots:
10+
3. Permit custom dots:
1311
```jsx
1412
<ReactCarousel
1513
navigation={{
@@ -19,7 +17,7 @@
1917
}}
2018
>...</ReactCarousel>
2119
```
22-
5. Permit custom arrows:
20+
4. Permit custom arrows:
2321
```jsx
2422
<ReactCarousel
2523
navigation={{
@@ -30,4 +28,4 @@
3028
}}
3129
>...</ReactCarousel>
3230
```
33-
6. Handle keyboard navigation (accessibility purpose)
31+
5. Handle keyboard navigation (accessibility purpose)

example/style.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export default `
22
width: 100%;
33
margin: auto;
4+
touch-action: pan-x pan-y;
45
56
.content {
67
width: clamp(200px, 100%, 1000px);

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
},
1818
"devDependencies": {
1919
"@babel/core": "^7.12.10",
20+
"@babel/plugin-proposal-class-properties": "^7.12.1",
2021
"@babel/preset-env": "^7.12.10",
2122
"@babel/preset-react": "^7.12.10",
2223
"@emotion/babel-plugin": "^11.1.2",

src/Item.jsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import React, { createRef, useState } from "react";
2+
import { TouchHandler } from "./services/TouchHandler";
23

34
const Item = ({ children, increaseValue, decreaseValue, setViewValue }) => {
45
const [x, setX] = useState(0);
56
const [viewX, setViewX] = useState(0);
67

8+
const [elementKey, setElementKey] = useState("");
9+
710
const itemRef = createRef();
811

912
const getTouches = (evt) => evt.touches;
@@ -15,7 +18,9 @@ const Item = ({ children, increaseValue, decreaseValue, setViewValue }) => {
1518
};
1619

1720
const handleTouchStart = (evt) => {
18-
let currentX = Math.trunc(getTouches(evt)[0].clientX);
21+
let key = TouchHandler.insertElement();
22+
setElementKey(key);
23+
let currentX = Math.trunc(getTouches(evt)[TouchHandler.getIndex(key)].clientX);
1924
setX(currentX);
2025
setViewX(currentX);
2126
};
@@ -28,7 +33,7 @@ const Item = ({ children, increaseValue, decreaseValue, setViewValue }) => {
2833
};
2934

3035
const handleTouchMove = (evt) => {
31-
let currentX = Math.trunc(getTouches(evt)[0].clientX);
36+
let currentX = Math.trunc(getTouches(evt)[TouchHandler.getIndex(elementKey)].clientX);
3237
if (currentX !== viewX) {
3338
setViewValue(x - currentX);
3439
setViewX(currentX);
@@ -41,6 +46,7 @@ const Item = ({ children, increaseValue, decreaseValue, setViewValue }) => {
4146
};
4247

4348
const handleTouchEnd = () => {
49+
TouchHandler.removeElement(elementKey);
4450
if (viewX < x) increaseValue();
4551
else if(viewX > x) decreaseValue();
4652
};

src/services/TouchHandler.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
export class TouchHandler {
2+
static touchedElementIndexes = {};
3+
static touchedElementIndexesLength = 0;
4+
5+
static getKey () {
6+
return Math.random().toString(36).substring(7);
7+
}
8+
9+
static insertElement() {
10+
let key = this.getKey();
11+
this.touchedElementIndexes[key] = this.touchedElementIndexesLength;
12+
this.touchedElementIndexesLength += 1;
13+
return key;
14+
}
15+
16+
static getIndex(key) {
17+
return this.touchedElementIndexes[key];
18+
}
19+
20+
static removeElement(key) {
21+
Object.keys(this.touchedElementIndexes).map(value => {
22+
if (value > this.touchedElementIndexes[key]) return value -= 1;
23+
})
24+
delete this.touchedElementIndexes[key];
25+
this.touchedElementIndexesLength -= 1;
26+
}
27+
}

webpack.config.js

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,54 @@
11
const path = require("path");
22

33
module.exports = {
4-
entry: path.resolve(__dirname, 'example', 'index.js'),
4+
entry: path.resolve(__dirname, "example", "index.js"),
55
output: {
6-
path: path.resolve(__dirname, 'dist'),
7-
filename: 'bundle.js'
6+
path: path.resolve(__dirname, "dist"),
7+
filename: "bundle.js",
88
},
99
devServer: {
10-
contentBase: [
11-
path.resolve(__dirname, 'dist')
12-
],
10+
contentBase: [path.resolve(__dirname, "dist")],
1311
open: true,
1412
port: 3000,
15-
host: '0.0.0.0',
16-
useLocalIp: true
13+
host: "0.0.0.0",
14+
useLocalIp: true,
1715
},
1816
module: {
1917
rules: [
2018
{
2119
test: [/\.js$/, /\.jsx$/],
2220
include: [
23-
path.resolve(__dirname, 'src'),
24-
path.resolve(__dirname, 'example')
21+
path.resolve(__dirname, "src"),
22+
path.resolve(__dirname, "example"),
2523
],
2624
exclude: [/node_modules/],
27-
use: [{
28-
loader: 'babel-loader',
29-
options: {
30-
presets: [
31-
['@babel/preset-env', {
32-
"targets": "defaults"
33-
}],
34-
'@babel/preset-react',
35-
'@emotion/babel-preset-css-prop'
36-
]
37-
}
38-
}]
25+
use: [
26+
{
27+
loader: "babel-loader",
28+
options: {
29+
presets: [
30+
[
31+
"@babel/preset-env",
32+
{
33+
targets: "defaults",
34+
},
35+
],
36+
"@babel/preset-react",
37+
"@emotion/babel-preset-css-prop",
38+
],
39+
plugins: ["@babel/plugin-proposal-class-properties"],
40+
},
41+
},
42+
],
3943
},
4044
{
4145
test: /\.(jpg|gif|mp4)$/i,
4246
use: [
4347
{
44-
loader: 'file-loader',
48+
loader: "file-loader",
4549
},
4650
],
4751
},
48-
]
49-
}
50-
}
52+
],
53+
},
54+
};

0 commit comments

Comments
 (0)