Skip to content

Commit

Permalink
rotate a tool
Browse files Browse the repository at this point in the history
  • Loading branch information
mcnuttandrew committed Jan 24, 2024
1 parent 8c19f1e commit 9f0b220
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 174 deletions.
196 changes: 192 additions & 4 deletions src/components/ColorScatterPlot.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
makeScales,
dragEventToColorZ,
dragEventToColorXY,
screenSpaceAvg,
} from "../lib/utils";
import configStore from "../stores/config-store";
import { scaleLinear } from "d3-scale";
Expand Down Expand Up @@ -100,6 +101,9 @@
$: x = scales.x;
$: y = scales.y;
$: z = scales.z;
// screen -> color space
$: xInv = scales.xInv;
$: yInv = scales.yInv;
$: CircleProps = (color: Color, i: number) => ({
cx: x(color),
Expand Down Expand Up @@ -137,7 +141,13 @@
dragging: interactionMode === "drag",
};
let interactionMode: "idle" | "drag" | "select" | "point-touch" = "idle";
let interactionMode:
| "idle"
| "drag"
| "select"
| "point-touch"
| "stretch"
| "rotate" = "idle";
let dragTargetPos = { x: 0, y: 0 };
let dragDelta = { x: 0, y: 0 };
function dragStart(e: any) {
Expand Down Expand Up @@ -258,6 +268,126 @@
"fill-opacity": "0.5",
class: "pointer-events-none",
};
$: initialRotationColors = [] as Color[];
$: initialRotatePos = { x: 0, y: 0 };
$: rotatePivotCenter = { x: 0, y: 0 };
$: rotatePosition = { x: 0, y: 0 };
function rotateStart(e: any) {
// console.log("rotate start");
startDragging();
interactionMode = "rotate";
initialRotationColors = [...colors];
// const pos = toXY(e);
initialRotatePos = {
x: e.target.getBBox().x,
y: e.target.getBBox().y,
};
rotatePivotCenter = screenSpaceAvg(
focusedColors
.map((x) => initialRotationColors[x])
.map((el) => ({
x: x(el),
y: y(el),
}))
);
rotateUpdate(e);
}
function rotateUpdate(e: any) {
// console.log("rotate update");
let currentPos = toXY(e);
currentPos = {
x: currentPos.x - svgContainer.getBoundingClientRect().x,
y: currentPos.y - svgContainer.getBoundingClientRect().y,
};
rotatePosition = currentPos;
let newAngle = Math.atan2(
currentPos.y - rotatePivotCenter.y,
currentPos.x - rotatePivotCenter.x
);
const initialAngle = Math.atan2(
initialRotatePos.y - rotatePivotCenter.y,
initialRotatePos.x - rotatePivotCenter.x
);
let angle = newAngle - initialAngle;
angle = angle < 0 ? angle + 2 * Math.PI : angle;
const xc = rotatePivotCenter.x;
const yc = rotatePivotCenter.y;
const newColors = focusedColors
.map((x) => initialRotationColors[x])
.map((color) => {
const x1 = x(color);
const y1 = y(color);
const x3 =
Math.cos(angle) * (x1 - xc) - Math.sin(angle) * (y1 - yc) + xc;
const y3 =
Math.sin(angle) * (x1 - xc) + Math.cos(angle) * (y1 - yc) + yc;
const newChannels = [...color.toChannels()] as [number, number, number];
newChannels[config.xChannelIndex] = xInv(x3, y3);
newChannels[config.yChannelIndex] = yInv(x3, y3);
return color.fromChannels(newChannels);
});
onColorsChange(newColors);
}
function rotateEnd() {
// console.log("rotate end");
interactionMode = "idle";
stopDragging();
}
$: handles = [
// {
// type: "stretch",
// label: "left",
// x: pos.xPos - 15,
// y: pos.yPos + pos.selectionHeight / 2,
// },
// {
// type: "stretch",
// label: "right",
// x: pos.xPos + pos.selectionWidth + 5,
// y: pos.yPos + pos.selectionHeight / 2,
// },
// {
// type: "stretch",
// label: "top",
// x: pos.xPos + pos.selectionWidth / 2,
// y: pos.yPos - 15,
// },
// {
// type: "stretch",
// label: "bottom",
// x: pos.xPos + pos.selectionWidth / 2,
// y: pos.yPos + pos.selectionHeight + 5,
// },
{
type: "rotate",
label: "",
x: pos.xPos,
y: pos.yPos,
},
{
type: "rotate",
label: "",
x: pos.xPos,
y: pos.yPos + pos.selectionHeight,
},
{
type: "rotate",
label: "",
x: pos.xPos + pos.selectionWidth,
y: pos.yPos,
},
{
type: "rotate",
label: "",
x: pos.xPos + pos.selectionWidth,
y: pos.yPos + pos.selectionHeight,
},
];
let svgContainer: any;
</script>

<!-- svelte-ignore a11y-no-static-element-interactions -->
Expand All @@ -269,7 +399,7 @@
</span>
<div class="flex h-full">
<div class="h-full py-4" style="max-height: {height}px"></div>
<svg {width} {height} class="ml-2">
<svg {width} {height} class="ml-2" bind:this={svgContainer}>
<g transform={`translate(${margin.left}, ${margin.top})`}>
{#if config.isPolar}
<ColorScatterPlotPolarGuide {...guideProps} {rScale} />
Expand All @@ -283,10 +413,14 @@
on:touchstart|preventDefault={selectionStart(false)}
on:touchmove|preventDefault={interactionMode === "drag"
? dragUpdate(false)
: selectionUpdate(false)}
: interactionMode === "rotate"
? rotateUpdate
: selectionUpdate(false)}
on:touchend|preventDefault={interactionMode === "drag"
? dragEnd(false)
: selectionEnd(false)}
: interactionMode === "rotate"
? rotateEnd
: selectionEnd(false)}
/>

<g
Expand Down Expand Up @@ -374,6 +508,51 @@
on:mousedown|preventDefault={(e) => dragStart(e)}
/>
{/if}
{#if focusedColors.length > 1}
{#each handles as handle}
{#if handle.type === "stretch"}
<rect
x={handle.x}
y={handle.y}
width={10}
fill={"black"}
cursor="grab"
height={10}
/>
{/if}
{#if handle.type === "rotate"}
<circle
cx={handle.x}
cy={handle.y}
r={10}
fill={"steelblue"}
opacity={0.5}
cursor="grab"
on:mousedown|preventDefault|stopPropagation={rotateStart}
on:mouseup|preventDefault|stopPropagation={rotateEnd}
on:touchstart|preventDefault|stopPropagation={rotateStart}
on:touchmove|preventDefault|stopPropagation={rotateUpdate}
on:touchend|preventDefault|stopPropagation={rotateEnd}
/>
{/if}
{/each}
{#if interactionMode === "rotate"}
<circle
fill="green"
r={10}
cx={rotatePosition.x}
cy={rotatePosition.y}
pointer-events="none"
/>
<line
x1={rotatePivotCenter.x}
y1={rotatePivotCenter.y}
x2={rotatePosition.x}
y2={rotatePosition.y}
stroke="green"
/>
{/if}
{/if}
</g>
</g>
{#if interactionMode === "select"}
Expand All @@ -400,6 +579,15 @@
on:touchend|preventDefault={dragEnd(false)}
/>
{/if}
{#if interactionMode === "rotate"}
<rect
{...fillParamsXY}
on:mousemove|preventDefault={rotateUpdate}
on:mouseup|preventDefault={rotateEnd}
on:touchmove|preventDefault={rotateUpdate}
on:touchend|preventDefault={rotateEnd}
/>
{/if}
</svg>
</div>
</div>
Expand Down
2 changes: 0 additions & 2 deletions src/content-modules/Controls.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import DistributePoints from "./contextual-tools/DistributePoints.svelte";
import AdjustColor from "./contextual-tools/AdjustColor.svelte";
import AddColor from "./contextual-tools/AddColor.svelte";
import Rotate from "./contextual-tools/Rotate.svelte";
import ColorChannelPicker from "../components/ColorChannelPicker.svelte";
$: currentPal = $colorStore.palettes[$colorStore.currentPal];
Expand All @@ -31,7 +30,6 @@
{/if}

<AdjustColor />
<Rotate />
<DistributePoints />
<AlignSelection />
<ModifySelection />
Expand Down
Loading

0 comments on commit 9f0b220

Please sign in to comment.