/
Drag-ii.tsx
124 lines (118 loc) 路 3.72 KB
/
Drag-ii.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import React, { useState } from 'react';
import { LinePath } from '@vx/shape';
import { Drag } from '@vx/drag';
import { curveBasis } from '@vx/curve';
import { LinearGradient } from '@vx/gradient';
import { ShowProvidedProps } from '../../types';
type Lines = { x: number; y: number }[][];
export default function DragII({ width, height }: ShowProvidedProps) {
const [lines, setLines] = useState<Lines>([]);
if (width < 10) return null;
return (
<div className="DragII" style={{ touchAction: 'none' }}>
<svg width={width} height={height}>
<LinearGradient
id="stroke"
from="#ff614e"
to="#ffdc64"
gradientUnits="userSpaceOnUse" // need for gradients to render on straight lines
/>
<rect fill="#04002b" width={width} height={height} rx={14} />
{lines.map((line, i) => (
<LinePath
key={`line-${i}`}
fill="transparent"
stroke="url(#stroke)"
strokeWidth={3}
data={line}
curve={curveBasis}
x={d => d.x}
y={d => d.y}
/>
))}
<Drag
width={width}
height={height}
resetOnStart
onDragStart={({ x = 0, y = 0 }) => {
// add the new line with the starting point
setLines(currLines => [...currLines, [{ x, y }]]);
}}
onDragMove={({ x = 0, y = 0, dx, dy }) => {
// add the new point to the current line
setLines(currLines => {
const nextLines = [...currLines];
const newPoint = { x: x + dx, y: y + dy };
const lastIndex = nextLines.length - 1;
nextLines[lastIndex] = [...(nextLines[lastIndex] || []), newPoint];
return nextLines;
});
}}
>
{({ x = 0, y = 0, dx, dy, isDragging, dragStart, dragEnd, dragMove }) => (
<g>
{/* decorate the currently drawing line */}
{isDragging && (
<g>
<rect
fill="white"
width={8}
height={8}
x={x + dx - 4}
y={y + dy - 4}
pointerEvents="none"
/>
<circle
cx={x}
cy={y}
r={4}
fill="transparent"
stroke="white"
pointerEvents="none"
/>
</g>
)}
{/* create the drawing area */}
<rect
fill="transparent"
width={width}
height={height}
onMouseDown={dragStart}
onMouseUp={dragEnd}
onMouseMove={dragMove}
onTouchStart={dragStart}
onTouchEnd={dragEnd}
onTouchMove={dragMove}
/>
</g>
)}
</Drag>
</svg>
<div className="deets">
<div>
Based on Mike Bostock's{' '}
<a href="https://bl.ocks.org/mbostock/f705fc55e6f26df29354">Line Drawing</a>
</div>
</div>
<style jsx>{`
.DragII {
display: flex;
flex-direction: column;
user-select: none;
}
svg {
margin: 1rem 0;
cursor: crosshair;
}
.deets {
display: flex;
flex-direction: row;
font-size: 12px;
}
.deets > div {
margin: 0.25rem;
}
`}</style>
</div>
);
}