Skip to content

Commit 7d7942b

Browse files
committed
refactor + styles
1 parent f647583 commit 7d7942b

File tree

3 files changed

+101
-94
lines changed

3 files changed

+101
-94
lines changed

app/components/mappings/rotate.js

Lines changed: 31 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2,79 +2,45 @@ import React, { useEffect, useRef } from 'react';
22
import { environment } from '#store/environment';
33
import { observer } from 'mobx-react';
44
import { exportSprite } from '#formats/image';
5-
import rotSprite, {
6-
Pixels,
7-
addMarginToImageData,
8-
getRotateDiagonal,
9-
} from '#util/rotsprite';
5+
import { rotateImageData } from '#util/rotsprite';
106
import { Input, Slider, Item, Button, Modal } from '#ui';
117
import { mappingState } from './state';
128

13-
export const Rotate = observer(() => {
14-
const canvasRef = useRef();
15-
16-
useEffect(() => {
17-
if (!canvasRef.current) return;
18-
const spriteCanv = exportSprite(environment.currentSprite);
19-
const spriteCtx = spriteCanv.getContext('2d');
20-
21-
const { width, height } = spriteCanv;
22-
23-
const imageData = spriteCtx.getImageData(0, 0, width, height);
24-
25-
const { diagonal, xMargin, yMargin } = getRotateDiagonal(width, height);
26-
27-
const spriteData = addMarginToImageData(
28-
spriteCtx,
29-
imageData,
30-
xMargin,
31-
yMargin,
32-
);
33-
34-
const data = new Uint32Array(diagonal ** 2);
35-
36-
for (let i = 0; i < spriteData.data.length; i += 4) {
37-
const r = spriteData.data[i];
38-
const g = spriteData.data[i + 1];
39-
const b = spriteData.data[i + 2];
40-
const a = spriteData.data[i + 3];
41-
data[i / 4] = (a << 24) + (r << 16) + (g << 8) + b;
42-
}
9+
function rotateCurrentSprite(canvas, angle) {
10+
const spriteCanv = exportSprite(environment.currentSprite);
11+
const spriteCtx = spriteCanv.getContext('2d');
12+
const { width, height } = spriteCanv;
13+
const imageData = spriteCtx.getImageData(0, 0, width, height);
14+
const rotatedData = rotateImageData(imageData, angle, width, height);
4315

44-
const rotated = rotSprite(
45-
new Pixels(diagonal, diagonal, data),
46-
(mappingState.rotate.angle * Math.PI) / 180,
47-
).pixels;
16+
const ctx = canvas.getContext('2d');
17+
canvas.width = rotatedData.width;
18+
canvas.height = rotatedData.height;
19+
ctx.putImageData(rotatedData, 0, 0);
20+
}
4821

49-
const pixelData = new Uint8ClampedArray(data.length * 4);
22+
export const Rotate = observer(() => {
23+
const canvasRef = useRef();
5024

51-
for (let i = 0; i < data.length; i++) {
52-
const value = rotated[i];
25+
const { active, angle } = mappingState.rotate;
5326

54-
pixelData[i * 4] = (value >> 16) & 0xff;
55-
pixelData[i * 4 + 1] = (value >> 8) & 0xff;
56-
pixelData[i * 4 + 2] = value & 0xff;
57-
pixelData[i * 4 + 3] = (value >> 24) & 0xff;
27+
useEffect(() => {
28+
if (!canvasRef.current) {
29+
requestAnimationFrame(() => {
30+
canvasRef.current &&
31+
rotateCurrentSprite(canvasRef.current, angle);
32+
});
33+
return;
5834
}
59-
60-
const rotatedData = new ImageData(pixelData, diagonal, diagonal);
61-
62-
const canvas = canvasRef.current;
63-
const ctx = canvas.getContext('2d');
64-
65-
canvas.width = diagonal;
66-
canvas.height = diagonal;
67-
ctx.putImageData(rotatedData, 0, 0);
68-
}, [environment.currentSprite, mappingState.rotate.angle]);
35+
rotateCurrentSprite(canvasRef.current, angle);
36+
}, [environment.currentSprite, angle, active]);
6937

7038
const assertInput = (num) => {
7139
const value = Math.max(0, Math.min(360, num));
7240
if (Number.isNaN(value)) return 0;
7341
return value;
7442
};
7543

76-
const { active } = mappingState.rotate;
77-
7844
return (
7945
<Modal
8046
className="rotsprite"
@@ -108,13 +74,13 @@ export const Rotate = observer(() => {
10874
/>
10975
</div>
11076

111-
<Slider
112-
min="0"
113-
step="1"
114-
max="360"
115-
store={mappingState.rotate}
116-
accessor="angle"
117-
/>
77+
<Slider
78+
min="0"
79+
step="1"
80+
max="360"
81+
store={mappingState.rotate}
82+
accessor="angle"
83+
/>
11884
</div>
11985
<div className="actions">
12086
<Button color="magenta" onClick={mappingState.toggleRotate}>

app/util/rotsprite.js

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -139,34 +139,35 @@ export class Pixels {
139139
};
140140
}
141141

142-
143-
export function addMarginToImageData(ctx, imageData, xMargin, yMargin) {
144-
// Create a new ImageData object with the new dimensions, including the margin.
145-
const newImageData = ctx.createImageData(
146-
imageData.width + xMargin * 2,
147-
imageData.height + yMargin * 2
148-
);
149-
150-
// Loop through the original image data and copy the pixel values to the new
151-
// ImageData object, taking the margin into account.
152-
for (let row = 0; row < imageData.height; row++) {
153-
for (let col = 0; col < imageData.width; col++) {
154-
const sourcePixel = [ imageData.data[(row * imageData.width + col) * 4 + 0],
155-
imageData.data[(row * imageData.width + col) * 4 + 1],
156-
imageData.data[(row * imageData.width + col) * 4 + 2],
157-
imageData.data[(row * imageData.width + col) * 4 + 3]
158-
];
159-
160-
const destRow = row + yMargin;
161-
const destCol = col + xMargin;
162-
for (let i = 0; i < 4; i++) {
163-
newImageData.data[(destRow * newImageData.width + destCol) * 4 + i] =
164-
sourcePixel[i];
165-
}
142+
export function addMarginToImageData(imageData, xMargin, yMargin) {
143+
// Create a new ImageData object with the new dimensions, including the margin.
144+
const newImageData = new ImageData(
145+
imageData.width + xMargin * 2,
146+
imageData.height + yMargin * 2,
147+
);
148+
149+
// Loop through the original image data and copy the pixel values to the new
150+
// ImageData object, taking the margin into account.
151+
for (let row = 0; row < imageData.height; row++) {
152+
for (let col = 0; col < imageData.width; col++) {
153+
const sourcePixel = [
154+
imageData.data[(row * imageData.width + col) * 4 + 0],
155+
imageData.data[(row * imageData.width + col) * 4 + 1],
156+
imageData.data[(row * imageData.width + col) * 4 + 2],
157+
imageData.data[(row * imageData.width + col) * 4 + 3],
158+
];
159+
160+
const destRow = row + yMargin;
161+
const destCol = col + xMargin;
162+
for (let i = 0; i < 4; i++) {
163+
newImageData.data[
164+
(destRow * newImageData.width + destCol) * 4 + i
165+
] = sourcePixel[i];
166+
}
167+
}
166168
}
167-
}
168169

169-
return newImageData;
170+
return newImageData;
170171
}
171172

172173
export function getRotateDiagonal(width, height) {
@@ -178,3 +179,41 @@ export function getRotateDiagonal(width, height) {
178179

179180
return { diagonal: xMargin * 2 + width, xMargin, yMargin };
180181
}
182+
183+
export function rotateImageData(imageData, angle, width, height) {
184+
const { diagonal, xMargin, yMargin } = getRotateDiagonal(width, height);
185+
186+
const spriteData = addMarginToImageData(
187+
imageData,
188+
xMargin,
189+
yMargin,
190+
);
191+
192+
const data = new Uint32Array(diagonal ** 2);
193+
194+
for (let i = 0; i < spriteData.data.length; i += 4) {
195+
const r = spriteData.data[i];
196+
const g = spriteData.data[i + 1];
197+
const b = spriteData.data[i + 2];
198+
const a = spriteData.data[i + 3];
199+
data[i / 4] = (a << 24) + (r << 16) + (g << 8) + b;
200+
}
201+
202+
const rotated = rotSprite(
203+
new Pixels(diagonal, diagonal, data),
204+
(angle * Math.PI) / 180,
205+
).pixels;
206+
207+
const pixelData = new Uint8ClampedArray(data.length * 4);
208+
209+
for (let i = 0; i < data.length; i++) {
210+
const value = rotated[i];
211+
212+
pixelData[i * 4] = (value >> 16) & 0xff;
213+
pixelData[i * 4 + 1] = (value >> 8) & 0xff;
214+
pixelData[i * 4 + 2] = value & 0xff;
215+
pixelData[i * 4 + 3] = (value >> 24) & 0xff;
216+
}
217+
218+
return new ImageData(pixelData, diagonal, diagonal);
219+
}

styles/components/rotsprite.scss

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
.rotsprite {
2+
padding: 20px;
23
canvas {
34
background-image: url(../images/t.png);
45
border: 3px solid $grey;
56
width: 400px;
67
height: 400px;
7-
margin: 10px;
8+
margin: 10px 0;
89
}
910

1011
.angles {
11-
margin: 10px;
12+
margin: 10px 0;
13+
margin-top: 0;
1214
.numbers {
1315
display: flex;
1416
justify-content: space-between;
@@ -27,7 +29,7 @@
2729
.actions {
2830
display: flex;
2931
justify-content: space-between;
30-
margin: 10px;
32+
margin: 10px 0;
3133
margin-bottom: 0;
3234
}
3335
}

0 commit comments

Comments
 (0)