Przeglądaj źródła

inky boxes

main
Steve Ruiz 4 lat temu
rodzic
commit
84c93060d0

+ 1
- 12
components/canvas/canvas.tsx Wyświetl plik

@@ -11,10 +11,6 @@ import Bounds from './bounds/bounding-box'
11 11
 import BoundsBg from './bounds/bounds-bg'
12 12
 import Selected from './selected'
13 13
 import Handles from './bounds/handles'
14
-import { isMobile, screenToWorld, throttle } from 'utils/utils'
15
-import session from 'state/session'
16
-import { PointerInfo } from 'types'
17
-import { fastDrawUpdate } from 'state/hacks'
18 14
 import useCanvasEvents from 'hooks/useCanvasEvents'
19 15
 
20 16
 export default function Canvas() {
@@ -56,16 +52,9 @@ const MainSVG = styled('svg', {
56 52
   zIndex: 100,
57 53
   backgroundColor: '$canvas',
58 54
   pointerEvents: 'all',
55
+  // cursor: 'none',
59 56
 
60 57
   '& *': {
61 58
     userSelect: 'none',
62 59
   },
63 60
 })
64
-
65
-// const throttledPointerMove = throttle((payload: any) => {
66
-//   state.send('MOVED_POINTER', payload)
67
-// }, 16)
68
-
69
-const throttledPointerMove = (payload: any) => {
70
-  state.send('MOVED_POINTER', payload)
71
-}

+ 64
- 0
components/canvas/cursor.tsx Wyświetl plik

@@ -0,0 +1,64 @@
1
+import React, { useEffect, useRef } from 'react'
2
+import styled from 'styles'
3
+
4
+export default function Cursor() {
5
+  const rCursor = useRef<SVGSVGElement>(null)
6
+
7
+  useEffect(() => {
8
+    function updatePosition(e: PointerEvent) {
9
+      console.log('hi')
10
+      const cursor = rCursor.current
11
+
12
+      cursor.setAttribute(
13
+        'transform',
14
+        `translate(${e.clientX - 12} ${e.clientY - 10})`
15
+      )
16
+    }
17
+
18
+    document.body.addEventListener('pointermove', updatePosition)
19
+    return () => {
20
+      document.body.removeEventListener('pointermove', updatePosition)
21
+    }
22
+  }, [])
23
+
24
+  return (
25
+    <StyledCursor
26
+      ref={rCursor}
27
+      width="35px"
28
+      height="35px"
29
+      viewBox="0 0 35 35"
30
+      version="1.1"
31
+      pointerEvents="none"
32
+      xmlns="http://www.w3.org/2000/svg"
33
+      xmlnsXlink="http://www.w3.org/1999/xlink"
34
+    >
35
+      <path
36
+        d="M12,24.4219 L12,8.4069 L23.591,20.0259 L16.81,20.0259 L16.399,20.1499 L12,24.4219 Z"
37
+        id="point-border"
38
+        fill="#FFFFFF"
39
+      />
40
+      <path
41
+        d="M21.0845,25.0962 L17.4795,26.6312 L12.7975,15.5422 L16.4835,13.9892 L21.0845,25.0962 Z"
42
+        id="stem-border"
43
+        fill="#FFFFFF"
44
+      />
45
+      <path
46
+        d="M19.751,24.4155 L17.907,25.1895 L14.807,17.8155 L16.648,17.0405 L19.751,24.4155 Z"
47
+        id="stem"
48
+        fill="#000000"
49
+      />
50
+      <path
51
+        d="M13,10.814 L13,22.002 L15.969,19.136 L16.397,18.997 L21.165,18.997 L13,10.814 Z"
52
+        id="point"
53
+        fill="#000000"
54
+      />
55
+    </StyledCursor>
56
+  )
57
+}
58
+
59
+const StyledCursor = styled('g', {
60
+  position: 'absolute',
61
+  zIndex: 1000,
62
+  top: 0,
63
+  left: 0,
64
+})

+ 3
- 16
lib/shape-utils/arrow.tsx Wyświetl plik

@@ -1,23 +1,9 @@
1 1
 import { v4 as uuid } from 'uuid'
2 2
 import * as vec from 'utils/vec'
3 3
 import * as svg from 'utils/svg'
4
-import {
5
-  ArrowShape,
6
-  Bounds,
7
-  ColorStyle,
8
-  DashStyle,
9
-  ShapeHandle,
10
-  ShapeType,
11
-  SizeStyle,
12
-} from 'types'
4
+import { ArrowShape, Bounds, ShapeHandle, ShapeType } from 'types'
13 5
 import { registerShapeUtils } from './index'
14
-import {
15
-  circleFromThreePoints,
16
-  clamp,
17
-  getBoundsCenter,
18
-  isAngleBetween,
19
-  rotateBounds,
20
-} from 'utils/utils'
6
+import { circleFromThreePoints, isAngleBetween } from 'utils/utils'
21 7
 import { pointInBounds } from 'utils/bounds'
22 8
 import {
23 9
   intersectArcBounds,
@@ -72,6 +58,7 @@ const arrow = registerShapeUtils<ArrowShape>({
72 58
 
73 59
     return {
74 60
       id: uuid(),
61
+      seed: Math.random(),
75 62
       type: ShapeType.Arrow,
76 63
       isGenerated: false,
77 64
       name: 'Arrow',

+ 1
- 0
lib/shape-utils/circle.tsx Wyświetl plik

@@ -14,6 +14,7 @@ const circle = registerShapeUtils<CircleShape>({
14 14
   create(props) {
15 15
     return {
16 16
       id: uuid(),
17
+      seed: Math.random(),
17 18
       type: ShapeType.Circle,
18 19
       isGenerated: false,
19 20
       name: 'Circle',

+ 1
- 0
lib/shape-utils/dot.tsx Wyświetl plik

@@ -13,6 +13,7 @@ const dot = registerShapeUtils<DotShape>({
13 13
   create(props) {
14 14
     return {
15 15
       id: uuid(),
16
+      seed: Math.random(),
16 17
       type: ShapeType.Dot,
17 18
       isGenerated: false,
18 19
       name: 'Dot',

+ 1
- 0
lib/shape-utils/draw.tsx Wyświetl plik

@@ -24,6 +24,7 @@ const draw = registerShapeUtils<DrawShape>({
24 24
   create(props) {
25 25
     return {
26 26
       id: uuid(),
27
+      seed: Math.random(),
27 28
       type: ShapeType.Draw,
28 29
       isGenerated: false,
29 30
       name: 'Draw',

+ 1
- 0
lib/shape-utils/ellipse.tsx Wyświetl plik

@@ -19,6 +19,7 @@ const ellipse = registerShapeUtils<EllipseShape>({
19 19
   create(props) {
20 20
     return {
21 21
       id: uuid(),
22
+      seed: Math.random(),
22 23
       type: ShapeType.Ellipse,
23 24
       isGenerated: false,
24 25
       name: 'Ellipse',

+ 1
- 0
lib/shape-utils/group.tsx Wyświetl plik

@@ -26,6 +26,7 @@ const group = registerShapeUtils<GroupShape>({
26 26
   create(props) {
27 27
     return {
28 28
       id: uuid(),
29
+      seed: Math.random(),
29 30
       type: ShapeType.Group,
30 31
       isGenerated: false,
31 32
       name: 'Group',

+ 1
- 0
lib/shape-utils/line.tsx Wyświetl plik

@@ -15,6 +15,7 @@ const line = registerShapeUtils<LineShape>({
15 15
   create(props) {
16 16
     return {
17 17
       id: uuid(),
18
+      seed: Math.random(),
18 19
       type: ShapeType.Line,
19 20
       isGenerated: false,
20 21
       name: 'Line',

+ 1
- 0
lib/shape-utils/polyline.tsx Wyświetl plik

@@ -13,6 +13,7 @@ const polyline = registerShapeUtils<PolylineShape>({
13 13
   create(props) {
14 14
     return {
15 15
       id: uuid(),
16
+      seed: Math.random(),
16 17
       type: ShapeType.Polyline,
17 18
       isGenerated: false,
18 19
       name: 'Polyline',

+ 1
- 0
lib/shape-utils/ray.tsx Wyświetl plik

@@ -14,6 +14,7 @@ const ray = registerShapeUtils<RayShape>({
14 14
   create(props) {
15 15
     return {
16 16
       id: uuid(),
17
+      seed: Math.random(),
17 18
       type: ShapeType.Ray,
18 19
       isGenerated: false,
19 20
       name: 'Ray',

+ 82
- 3
lib/shape-utils/rectangle.tsx Wyświetl plik

@@ -2,8 +2,11 @@ import { v4 as uuid } from 'uuid'
2 2
 import * as vec from 'utils/vec'
3 3
 import { RectangleShape, ShapeType } from 'types'
4 4
 import { registerShapeUtils } from './index'
5
-import { translateBounds } from 'utils/utils'
5
+import { getSvgPathFromStroke, translateBounds, getNoise } from 'utils/utils'
6 6
 import { defaultStyle, getShapeStyle } from 'lib/shape-styles'
7
+import getStroke from 'perfect-freehand'
8
+
9
+const pathCache = new WeakMap<RectangleShape, string>([])
7 10
 
8 11
 const rectangle = registerShapeUtils<RectangleShape>({
9 12
   boundsCache: new WeakMap([]),
@@ -11,6 +14,7 @@ const rectangle = registerShapeUtils<RectangleShape>({
11 14
   create(props) {
12 15
     return {
13 16
       id: uuid(),
17
+      seed: Math.random(),
14 18
       type: ShapeType.Rectangle,
15 19
       isGenerated: false,
16 20
       name: 'Rectangle',
@@ -28,19 +32,28 @@ const rectangle = registerShapeUtils<RectangleShape>({
28 32
     }
29 33
   },
30 34
 
31
-  render({ id, size, radius, style }) {
35
+  render(shape) {
36
+    const { id, size, radius, style, point } = shape
32 37
     const styles = getShapeStyle(style)
38
+
39
+    if (!pathCache.has(shape)) {
40
+      renderPath(shape)
41
+    }
42
+
43
+    const path = pathCache.get(shape)
44
+
33 45
     return (
34 46
       <g id={id}>
35 47
         <rect
36
-          id={id}
37 48
           rx={radius}
38 49
           ry={radius}
39 50
           x={+styles.strokeWidth / 2}
40 51
           y={+styles.strokeWidth / 2}
41 52
           width={Math.max(0, size[0] + -styles.strokeWidth)}
42 53
           height={Math.max(0, size[1] + -styles.strokeWidth)}
54
+          strokeWidth={0}
43 55
         />
56
+        <path d={path} fill={styles.stroke} />
44 57
       </g>
45 58
     )
46 59
   },
@@ -103,3 +116,69 @@ const rectangle = registerShapeUtils<RectangleShape>({
103 116
 })
104 117
 
105 118
 export default rectangle
119
+
120
+function easeInOut(t: number) {
121
+  return t * (2 - t)
122
+}
123
+
124
+function ease(t: number) {
125
+  return t * t * t
126
+}
127
+
128
+function pointsBetween(a: number[], b: number[], steps = 6) {
129
+  return Array.from(Array(steps))
130
+    .map((_, i) => ease(i / steps))
131
+    .map((t) => [...vec.lrp(a, b, t), (1 - t) / 2])
132
+}
133
+
134
+function renderPath(shape: RectangleShape) {
135
+  const styles = getShapeStyle(shape.style)
136
+
137
+  const noise = getNoise(shape.seed)
138
+  const off = -0.25 + shape.seed / 2
139
+
140
+  const offsets = Array.from(Array(4)).map((_, i) => [
141
+    noise(i, i + 1) * off * 16,
142
+    noise(i + 2, i + 3) * off * 16,
143
+  ])
144
+
145
+  const [w, h] = shape.size
146
+  const tl = vec.add([0, 0], offsets[0])
147
+  const tr = vec.add([w, 0], offsets[1])
148
+  const br = vec.add([w, h], offsets[2])
149
+  const bl = vec.add([0, h], offsets[3])
150
+
151
+  const lines = shuffleArr(
152
+    [
153
+      pointsBetween(tr, br),
154
+      pointsBetween(br, bl),
155
+      pointsBetween(bl, tl),
156
+      pointsBetween(tl, tr),
157
+    ],
158
+    shape.id.charCodeAt(5)
159
+  )
160
+
161
+  const stroke = getStroke(
162
+    [
163
+      ...lines.flat().slice(4),
164
+      ...lines[0].slice(0, 4),
165
+      lines[0][4],
166
+      lines[0][5],
167
+      lines[0][5],
168
+    ],
169
+    {
170
+      size: 1 + +styles.strokeWidth * 2,
171
+      thinning: 0.6,
172
+      easing: (t) => t * t * t * t,
173
+      end: { taper: +styles.strokeWidth * 20 },
174
+      start: { taper: +styles.strokeWidth * 20 },
175
+      simulatePressure: false,
176
+    }
177
+  )
178
+
179
+  pathCache.set(shape, getSvgPathFromStroke(stroke))
180
+}
181
+
182
+function shuffleArr<T>(arr: T[], offset: number): T[] {
183
+  return arr.map((_, i) => arr[(i + offset) % arr.length])
184
+}

+ 16
- 0
public/icons/grab.svg Wyświetl plik

@@ -0,0 +1,16 @@
1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+    <defs></defs>
4
+    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
5
+        <g id="openhand">
6
+            <g id="bg-copy" fill="#FFFFFF" opacity="1">
7
+                <rect id="bg" x="0" y="0" width="35" height="35"></rect>
8
+            </g>
9
+            <path d="M13.5557,17.5742 C13.4577,17.1992 13.3597,16.7272 13.1497,16.0222 C12.9827,15.4652 12.8077,15.1632 12.6797,14.7892 C12.5247,14.3342 12.3767,14.0682 12.1837,13.6082 C12.0447,13.2792 11.8197,12.5602 11.7267,12.1682 C11.6077,11.6592 11.7597,11.2442 11.9707,10.9622 C12.2237,10.6232 12.9327,10.4722 13.3277,10.6112 C13.6987,10.7412 14.0717,11.1232 14.2437,11.3992 C14.5317,11.8592 14.6007,12.0312 14.9607,12.9412 C15.3537,13.9332 15.5247,14.8592 15.5717,15.1722 L15.6567,15.6242 C15.6557,15.5842 15.6137,14.5022 15.6127,14.4622 C15.5777,13.4332 15.5527,12.6392 15.5747,11.5232 C15.5767,11.3972 15.6387,10.9362 15.6587,10.8082 C15.7367,10.3082 15.9637,10.0082 16.3317,9.8292 C16.7437,9.6282 17.2577,9.6142 17.7327,9.8122 C18.1557,9.9852 18.3587,10.3622 18.4197,10.8342 C18.4337,10.9432 18.5137,11.8212 18.5127,11.9412 C18.4997,12.9662 18.5187,13.5822 18.5277,14.1152 C18.5317,14.3462 18.5307,15.7402 18.5447,15.5842 C18.6057,14.9282 18.6387,12.3952 18.8887,11.6422 C19.0327,11.2092 19.2937,10.8962 19.6827,10.7132 C20.1137,10.5102 20.7957,10.6432 21.0867,10.9562 C21.3717,11.2612 21.5327,11.6482 21.5687,12.1092 C21.6007,12.5142 21.5497,13.0062 21.5487,13.3542 C21.5487,14.2212 21.5277,14.6782 21.5117,15.4752 C21.5107,15.5132 21.4967,15.7732 21.5347,15.6572 C21.6287,15.3772 21.7227,15.1152 21.8007,14.9122 C21.8497,14.7872 22.0417,14.2982 22.1597,14.0532 C22.2737,13.8192 22.3707,13.6842 22.5747,13.3652 C22.7747,13.0522 22.9897,12.9172 23.2427,12.8042 C23.7827,12.5692 24.3517,12.9162 24.5437,13.3952 C24.6297,13.6102 24.5527,14.1082 24.5157,14.5002 C24.4547,15.1472 24.2617,15.8062 24.1637,16.1482 C24.0357,16.5952 23.8897,17.3832 23.8237,17.7492 C23.7517,18.1432 23.5897,19.1312 23.4647,19.5692 C23.3787,19.8702 23.0937,20.5472 22.8127,20.9532 C22.8127,20.9532 21.7387,22.2032 21.6207,22.7652 C21.5037,23.3282 21.5427,23.3322 21.5197,23.7302 C21.4957,24.1292 21.6407,24.6532 21.6407,24.6532 C21.6407,24.6532 20.8387,24.7572 20.4067,24.6872 C20.0157,24.6252 19.5317,23.8462 19.4067,23.6092 C19.2347,23.2812 18.8677,23.3442 18.7247,23.5862 C18.4997,23.9692 18.0157,24.6562 17.6737,24.6992 C17.0057,24.7832 15.6197,24.7292 14.5347,24.7192 C14.5347,24.7192 14.7197,23.7082 14.3077,23.3612 C14.0027,23.1012 13.4777,22.5772 13.1637,22.3012 L12.3317,21.3802 C12.0477,21.0202 11.7027,20.2872 11.0887,19.3952 C10.7407,18.8912 10.0617,18.3102 9.8047,17.8162 C9.5817,17.3912 9.4737,16.8622 9.6147,16.4912 C9.8397,15.8972 10.2897,15.5942 10.9767,15.6592 C11.4957,15.7092 11.8247,15.8652 12.2147,16.1962 C12.4397,16.3862 12.7877,16.7302 12.9647,16.9442 C13.1277,17.1392 13.1677,17.2202 13.3417,17.4532 C13.5717,17.7602 13.6437,17.9122 13.5557,17.5742" id="hand" fill="#FFFFFF"></path>
10
+            <path d="M13.5557,17.5742 C13.4577,17.1992 13.3597,16.7272 13.1497,16.0222 C12.9827,15.4652 12.8077,15.1632 12.6797,14.7892 C12.5247,14.3342 12.3767,14.0682 12.1837,13.6082 C12.0447,13.2792 11.8197,12.5602 11.7267,12.1682 C11.6077,11.6592 11.7597,11.2442 11.9707,10.9622 C12.2237,10.6232 12.9327,10.4722 13.3277,10.6112 C13.6987,10.7412 14.0717,11.1232 14.2437,11.3992 C14.5317,11.8592 14.6007,12.0312 14.9607,12.9412 C15.3537,13.9332 15.5247,14.8592 15.5717,15.1722 L15.6567,15.6242 C15.6557,15.5842 15.6137,14.5022 15.6127,14.4622 C15.5777,13.4332 15.5527,12.6392 15.5747,11.5232 C15.5767,11.3972 15.6387,10.9362 15.6587,10.8082 C15.7367,10.3082 15.9637,10.0082 16.3317,9.8292 C16.7437,9.6282 17.2577,9.6142 17.7327,9.8122 C18.1557,9.9852 18.3587,10.3622 18.4197,10.8342 C18.4337,10.9432 18.5137,11.8212 18.5127,11.9412 C18.4997,12.9662 18.5187,13.5822 18.5277,14.1152 C18.5317,14.3462 18.5307,15.7402 18.5447,15.5842 C18.6057,14.9282 18.6387,12.3952 18.8887,11.6422 C19.0327,11.2092 19.2937,10.8962 19.6827,10.7132 C20.1137,10.5102 20.7957,10.6432 21.0867,10.9562 C21.3717,11.2612 21.5327,11.6482 21.5687,12.1092 C21.6007,12.5142 21.5497,13.0062 21.5487,13.3542 C21.5487,14.2212 21.5277,14.6782 21.5117,15.4752 C21.5107,15.5132 21.4967,15.7732 21.5347,15.6572 C21.6287,15.3772 21.7227,15.1152 21.8007,14.9122 C21.8497,14.7872 22.0417,14.2982 22.1597,14.0532 C22.2737,13.8192 22.3707,13.6842 22.5747,13.3652 C22.7747,13.0522 22.9897,12.9172 23.2427,12.8042 C23.7827,12.5692 24.3517,12.9162 24.5437,13.3952 C24.6297,13.6102 24.5527,14.1082 24.5157,14.5002 C24.4547,15.1472 24.2617,15.8062 24.1637,16.1482 C24.0357,16.5952 23.8897,17.3832 23.8237,17.7492 C23.7517,18.1432 23.5897,19.1312 23.4647,19.5692 C23.3787,19.8702 23.0937,20.5472 22.8127,20.9532 C22.8127,20.9532 21.7387,22.2032 21.6207,22.7652 C21.5037,23.3282 21.5427,23.3322 21.5197,23.7302 C21.4957,24.1292 21.6407,24.6532 21.6407,24.6532 C21.6407,24.6532 20.8387,24.7572 20.4067,24.6872 C20.0157,24.6252 19.5317,23.8462 19.4067,23.6092 C19.2347,23.2812 18.8677,23.3442 18.7247,23.5862 C18.4997,23.9692 18.0157,24.6562 17.6737,24.6992 C17.0057,24.7832 15.6197,24.7292 14.5347,24.7192 C14.5347,24.7192 14.7197,23.7082 14.3077,23.3612 C14.0027,23.1012 13.4777,22.5772 13.1637,22.3012 L12.3317,21.3802 C12.0477,21.0202 11.7027,20.2872 11.0887,19.3952 C10.7407,18.8912 10.0617,18.3102 9.8047,17.8162 C9.5817,17.3912 9.4737,16.8622 9.6147,16.4912 C9.8397,15.8972 10.2897,15.5942 10.9767,15.6592 C11.4957,15.7092 11.8247,15.8652 12.2147,16.1962 C12.4397,16.3862 12.7877,16.7302 12.9647,16.9442 C13.1277,17.1392 13.1677,17.2202 13.3417,17.4532 C13.5717,17.7602 13.6437,17.9122 13.5557,17.5742" id="hand-border" stroke="#000000" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"></path>
11
+            <path d="M20.5664,21.7344 L20.5664,18.2754" id="line3" stroke="#000000" stroke-width="0.75" stroke-linecap="round"></path>
12
+            <path d="M18.5508,21.7461 L18.5348,18.2731" id="line2" stroke="#000000" stroke-width="0.75" stroke-linecap="round"></path>
13
+            <path d="M16.5547,18.3047 L16.5757,21.7307" id="line1" stroke="#000000" stroke-width="0.75" stroke-linecap="round"></path>
14
+        </g>
15
+    </g>
16
+</svg>

+ 15
- 0
public/icons/pointer.svg Wyświetl plik

@@ -0,0 +1,15 @@
1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+    <defs></defs>
4
+    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
5
+        <g id="pointer">
6
+            <g id="bg" fill="#FFFFFF" opacity="0.00999999978">
7
+                <rect x="0" y="0" width="35" height="35"></rect>
8
+            </g>
9
+            <path d="M12,24.4219 L12,8.4069 L23.591,20.0259 L16.81,20.0259 L16.399,20.1499 L12,24.4219 Z" id="point-border" fill="#FFFFFF"></path>
10
+            <path d="M21.0845,25.0962 L17.4795,26.6312 L12.7975,15.5422 L16.4835,13.9892 L21.0845,25.0962 Z" id="stem-border" fill="#FFFFFF"></path>
11
+            <path d="M19.751,24.4155 L17.907,25.1895 L14.807,17.8155 L16.648,17.0405 L19.751,24.4155 Z" id="stem" fill="#000000"></path>
12
+            <path d="M13,10.814 L13,22.002 L15.969,19.136 L16.397,18.997 L21.165,18.997 L13,10.814 Z" id="point" fill="#000000"></path>
13
+        </g>
14
+    </g>
15
+</svg>

+ 13
- 0
public/icons/resize.svg Wyświetl plik

@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+    <defs></defs>
4
+    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
5
+        <g id="resizenortheastsouthwest">
6
+            <g id="bg-copy" fill="#FFFFFF" opacity="1">
7
+                <rect id="bg" x="0" y="0" width="35" height="35"></rect>
8
+            </g>
9
+            <path d="M19.7432,17.0869 L15.6712,21.1549 L18.5002,23.9829 L10.0272,23.9699 L10.0142,15.4999 L12.8552,18.3419 L16.9302,14.2739 L18.3442,12.8589 L15.5002,10.0169 L23.9862,10.0169 L23.9862,18.5009 L21.1562,15.6739 L19.7432,17.0869 Z" id="resize-border" fill="#FFFFFF"></path>
10
+            <path d="M18.6826,16.7334 L14.2556,21.1574 L16.0836,22.9854 L11.0276,22.9694 L11.0136,17.9154 L12.8556,19.7564 L17.2836,15.3344 L19.7576,12.8594 L17.9136,11.0164 L22.9866,11.0164 L22.9866,16.0874 L21.1566,14.2594 L18.6826,16.7334 Z" id="resize" fill="#000000"></path>
11
+        </g>
12
+    </g>
13
+</svg>

+ 17
- 0
state/cursor.ts Wyświetl plik

@@ -0,0 +1,17 @@
1
+const cursorSvgs = {
2
+  default: 'pointer',
3
+  resize: 'resize',
4
+  grab: 'grab',
5
+}
6
+
7
+class Cursor {
8
+  setCursor(cursor: keyof typeof cursorSvgs, rotation = 0) {
9
+    document.body.style.setProperty('cursor', `url(${cursorSvgs[cursor]}.svg)`)
10
+  }
11
+
12
+  resetCursor() {
13
+    this.setCursor('default')
14
+  }
15
+}
16
+
17
+export default new Cursor()

+ 1
- 0
state/sessions/translate-session.ts Wyświetl plik

@@ -189,6 +189,7 @@ export function getTranslateSnapshot(data: Data) {
189 189
         const clone = {
190 190
           ...shape,
191 191
           id: uuid(),
192
+          seed: Math.random(),
192 193
           parentId: shape.parentId,
193 194
           childIndex: getChildIndexAbove(cData, shape.id),
194 195
         }

+ 1
- 0
types.ts Wyświetl plik

@@ -105,6 +105,7 @@ export type ShapeStyles = {
105 105
 
106 106
 export interface BaseShape {
107 107
   id: string
108
+  seed: number
108 109
   type: ShapeType
109 110
   parentId: string
110 111
   childIndex: number

+ 83
- 0
utils/utils.ts Wyświetl plik

@@ -1677,3 +1677,86 @@ export function setSelectedIds(data: Data, ids: string[]) {
1677 1677
 export function setToArray<T>(set: Set<T>): T[] {
1678 1678
   return Array.from(set.values())
1679 1679
 }
1680
+
1681
+const G2 = (3.0 - Math.sqrt(3.0)) / 6.0
1682
+
1683
+const Grad = [
1684
+  [1, 1],
1685
+  [-1, 1],
1686
+  [1, -1],
1687
+  [-1, -1],
1688
+  [1, 0],
1689
+  [-1, 0],
1690
+  [1, 0],
1691
+  [-1, 0],
1692
+  [0, 1],
1693
+  [0, -1],
1694
+  [0, 1],
1695
+  [0, -1],
1696
+]
1697
+
1698
+// Thanks to joshforisha
1699
+// https://github.com/joshforisha/fast-simplex-noise-js/blob/main/src/2d.ts
1700
+export function getNoise(seed = Math.random()) {
1701
+  const p = new Uint8Array(256)
1702
+  for (let i = 0; i < 256; i++) p[i] = i
1703
+
1704
+  let n: number
1705
+  let q: number
1706
+  for (let i = 255; i > 0; i--) {
1707
+    n = Math.floor((i + 1) * seed)
1708
+    q = p[i]
1709
+    p[i] = p[n]
1710
+    p[n] = q
1711
+  }
1712
+
1713
+  const perm = new Uint8Array(512)
1714
+  const permMod12 = new Uint8Array(512)
1715
+  for (let i = 0; i < 512; i++) {
1716
+    perm[i] = p[i & 255]
1717
+    permMod12[i] = perm[i] % 12
1718
+  }
1719
+
1720
+  return (x: number, y: number): number => {
1721
+    // Skew the input space to determine which simplex cell we're in
1722
+    const s = (x + y) * 0.5 * (Math.sqrt(3.0) - 1.0) // Hairy factor for 2D
1723
+    const i = Math.floor(x + s)
1724
+    const j = Math.floor(y + s)
1725
+    const t = (i + j) * G2
1726
+    const X0 = i - t // Unskew the cell origin back to (x,y) space
1727
+    const Y0 = j - t
1728
+    const x0 = x - X0 // The x,y distances from the cell origin
1729
+    const y0 = y - Y0
1730
+
1731
+    // Determine which simplex we are in.
1732
+    const i1 = x0 > y0 ? 1 : 0
1733
+    const j1 = x0 > y0 ? 0 : 1
1734
+
1735
+    // Offsets for corners
1736
+    const x1 = x0 - i1 + G2
1737
+    const y1 = y0 - j1 + G2
1738
+    const x2 = x0 - 1.0 + 2.0 * G2
1739
+    const y2 = y0 - 1.0 + 2.0 * G2
1740
+
1741
+    // Work out the hashed gradient indices of the three simplex corners
1742
+    const ii = i & 255
1743
+    const jj = j & 255
1744
+    const g0 = Grad[permMod12[ii + perm[jj]]]
1745
+    const g1 = Grad[permMod12[ii + i1 + perm[jj + j1]]]
1746
+    const g2 = Grad[permMod12[ii + 1 + perm[jj + 1]]]
1747
+
1748
+    // Calculate the contribution from the three corners
1749
+    const t0 = 0.5 - x0 * x0 - y0 * y0
1750
+    const n0 = t0 < 0 ? 0.0 : Math.pow(t0, 4) * (g0[0] * x0 + g0[1] * y0)
1751
+
1752
+    const t1 = 0.5 - x1 * x1 - y1 * y1
1753
+    const n1 = t1 < 0 ? 0.0 : Math.pow(t1, 4) * (g1[0] * x1 + g1[1] * y1)
1754
+
1755
+    const t2 = 0.5 - x2 * x2 - y2 * y2
1756
+    const n2 = t2 < 0 ? 0.0 : Math.pow(t2, 4) * (g2[0] * x2 + g2[1] * y2)
1757
+
1758
+    // Add contributions from each corner to get the final noise value.
1759
+    // The result is scaled to return values in the interval [-1, 1]
1760
+    return 70.14805770653952 * (n0 + n1 + n2)
1761
+  }
1762
+}

Ładowanie…
Anuluj
Zapisz