Skip to content

Commit

Permalink
add grid, snap mirror plugin and test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
zjffun committed Jul 2, 2020
1 parent a6a958e commit ffea4d3
Show file tree
Hide file tree
Showing 10 changed files with 502 additions and 136 deletions.
5 changes: 4 additions & 1 deletion examples/.prettierrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"trailingComma": "all",
"printWidth": 120,
"singleQuote": true
"singleQuote": true,
"bracketSpacing": false,
"arrowParens": "always"
}
2 changes: 1 addition & 1 deletion examples/src/content/Plugins/SnapMirror/SnapMirror.scss
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
background: #fff;
content: "";
}

}
.star1 {
left: 15%;
Expand All @@ -59,6 +58,7 @@
.star2 {
left: 25%;
top: 60%;
border-radius: 50%;
}
.star3 {
left: 35%;
Expand Down
150 changes: 30 additions & 120 deletions examples/src/content/Plugins/SnapMirror/index.js
Original file line number Diff line number Diff line change
@@ -1,147 +1,57 @@
// eslint-disable-next-line import/no-unresolved
import {Draggable} from '@shopify/draggable';
import {Draggable, Plugins} from '@shopify/draggable';

function getNearestPoint(point) {
const width = 50;
const divX = parseInt(point.x / width, 10);
const divY = parseInt(point.y / width, 10);
const modX = point.x % width;
const modY = point.y % width;

return {
x: (divX + (modX * 2 > width)) * width,
y: (divY + (modY * 2 > width)) * width,
};
}

function getNearestPointForSky(point, points) {
let result = point;
let distance = Infinity;

points.forEach((poi) => {
if (
!(
point.x < poi.x + poi.range[1] &&
point.x > poi.x - poi.range[3] &&
point.y > poi.y - poi.range[0] &&
point.y < poi.y + poi.range[2]
)
) {
return;
function initSky() {
const container = document.querySelector('.sky');
const containerRect = container.getBoundingClientRect();

const targets = [];
[...document.querySelectorAll('.star')].forEach((star) => {
const rect = star.getBoundingClientRect();
let range = {rect: [15, 25, 25, 15]};
if (star.classList.contains('star1')) {
range = {rect: [Infinity, Infinity, Infinity, Infinity]};
}
const tempDistance = (point.x - poi.x) ** 2 + (point.y - poi.y) ** 2;
if (tempDistance < distance) {
result = poi;
distance = tempDistance;
if (star.classList.contains('star2')) {
range = {circle: 20};
}
targets.push({x: rect.x + 20 - containerRect.x, y: rect.y + 20 - containerRect.y, range});
});

// console.log(points);
return result;
}

function initSky() {
const container = document.querySelector('.sky');

const points = [];
let pointerStart = {x: 0, y: 0};
let mirrorStart = {x: 0, y: 0};
// const offset = {x: 0, y: 0};

const draggable = new Draggable([container], {
draggable: '.sky__item',
mirror: {
constrainDimensions: true,
},
plugins: [Plugins.SnapMirror],
SnapMirror: {
targets,
relativePoints: [{x: 0.5, y: 0.5}],
},
});

draggable.on('mirror:created', (evt) => {
const boundingClientRect = evt.source.getBoundingClientRect();

mirrorStart = {
x: boundingClientRect.x,
y: boundingClientRect.y,
};
pointerStart = {
x: evt.sensorEvent.clientX,
y: evt.sensorEvent.clientY,
};

[...document.querySelectorAll('.star')].forEach((star) => {
const rect = star.getBoundingClientRect();
let range = [15, 25, 25, 15];
if (star.classList.contains('star1')) {
range = [Infinity, Infinity, Infinity, Infinity];
}
points.push({x: rect.x + 15 - mirrorStart.x, y: rect.y + 15 - mirrorStart.y, range});
});
});

draggable.on('mirror:move', (evt) => {
evt.cancel();

requestAnimationFrame(() => {
const {clientX, clientY} = evt.sensorEvent;
const nearestPoint = getNearestPointForSky(
{
x: clientX - pointerStart.x,
y: clientY - pointerStart.y,
},
points,
);
const translate = {
x: mirrorStart.x + nearestPoint.x,
y: mirrorStart.y + nearestPoint.y,
};
draggable.on('mirror:created', () => {});

evt.mirror.style.transform = `translate3d(${translate.x}px, ${translate.y}px, 0px)`;
});
});
draggable.on('mirror:move', () => {});
}

export default function PluginsSnapMirror() {
const container = document.querySelector('.box');

let pointerStart = {x: 0, y: 0};
let mirrorStart = {x: 0, y: 0};
// const offset = {x: 0, y: 0};

const draggable = new Draggable([container], {
draggable: '.box__item',
mirror: {
constrainDimensions: true,
},
});

draggable.on('mirror:created', (evt) => {
const boundingClientRect = evt.source.getBoundingClientRect();

mirrorStart = {
x: boundingClientRect.x,
y: boundingClientRect.y,
};
pointerStart = {
x: evt.sensorEvent.clientX,
y: evt.sensorEvent.clientY,
};
});

draggable.on('mirror:move', (evt) => {
evt.cancel();

requestAnimationFrame(() => {
const {clientX, clientY} = evt.sensorEvent;
const nearestPoint = getNearestPoint({
x: clientX - pointerStart.x,
y: clientY - pointerStart.y,
});
const translate = {
x: mirrorStart.x + nearestPoint.x,
y: mirrorStart.y + nearestPoint.y,
};

evt.mirror.style.transform = `translate3d(${translate.x}px, ${translate.y}px, 0px)`;
});
plugins: [Plugins.SnapMirror],
SnapMirror: {
targets: [
Plugins.SnapMirror.grid({
x: 50,
y: 50,
}),
],
},
});

// demo sky
Expand Down
7 changes: 7 additions & 0 deletions scripts/build/bundles.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ const bundles = [
source: 'Plugins/SortAnimation/index',
path: 'plugins/',
},

{
name: 'SnapMirror',
filename: 'snap-mirror',
source: 'Plugins/SnapMirror/index',
path: 'plugins/',
},
];

module.exports = {bundles};
33 changes: 19 additions & 14 deletions src/Plugins/SnapMirror/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ This plugin is not included in the default Draggable bundle, so you'll need to i

<!-- add a gif / video ? -->

<!-- Inspired by interactjs. -->
<!-- Inspired by interact.js -->

### Import

```js
import { Plugins } from '@shopify/draggable';
import {Plugins} from '@shopify/draggable';
```

```js
Expand All @@ -31,21 +31,23 @@ import SnapMirror from '@shopify/draggable/lib/plugins/snap-mirror';
**`targets {Array<Object|Function>}`**
An object contain target options or a function returning an object contain target options.

If a snap target is a function, then it is called and given the x and y coordinates of the event as the first two parameters and the current SnapMirror instance as the third parameter.

Target options:

| Name | Type | Description |
| -------------- | ---------------------- | ----------- |
| `x` | `number` | |
| `y` | `number` | |
| `range` | `Object` or `Function` | |
| `range.circle` | `number` | |
| `range.rect` | `Array` | |
| Name | Type | Description |
| ------- | -------- | ----------------------------------------------------------------------------------------------------------------------- |
| `x` | `number` | The x coordinates of snap target relative to offset. |
| `y` | `number` | The y coordinates of snap target relative to offset. |
| `range` | `number` | The range of a snap target is the distance the pointer must be from the target's coordinates for a snap to be possible. |

**`offset {string|Object}`**
A string or an object with `x` and `y` properties.
A string `container` or an object with `x` and `y` properties.
The `offset` option lets you shift the coordinates of the targets.

**`relativePoints {Object}`**
If using `container`, offset will set to the upper left corner coordinates of the current source container.

**`relativePoints {Array<Object>}`**
An object with `x` and `y` properties.
The `relativePoints` option lets you set where the drag element should snap.

Expand All @@ -58,19 +60,22 @@ The `range` option lets you set the default range for all targets.
You can use the `SnapMirror.grid()` method to create a target that snaps to a grid.
The method takes an object describing a grid and returns a function that snaps to the corners of that grid.

**`inRectRange(range: Array)`**
You can use the `SnapMirror.rectRange()` method check if a point in ract Range.

### Examples

```js
import { Sortable, Plugins } from '@shopify/draggable';
import {Sortable, Plugins} from '@shopify/draggable';

const sortable = new Sortable(document.querySelectorAll('ul'), {
draggable: 'li',
SnapMirror: {
targets: [{x: 100, y: 100, range: 50}],
relativePoints: [{x: 0.5, y: 0.5}],
offset: "container"
offset: 'container',
},
plugins: [Plugins.SnapMirror]
plugins: [Plugins.SnapMirror],
});
```

Expand Down
Loading

0 comments on commit ffea4d3

Please sign in to comment.