Skip to content

Instantly share code, notes, and snippets.

@connor-davis
Created September 24, 2021 15:03
Show Gist options
  • Save connor-davis/61672cc5dab5ce0da5b60b512113d21b to your computer and use it in GitHub Desktop.
Save connor-davis/61672cc5dab5ce0da5b60b512113d21b to your computer and use it in GitHub Desktop.
import { createSignal, onMount } from "solid-js";
let Cropper = ({ src, onContinue = () => {}, onCancel = () => {} }) => {
let [base, setBase] = createSignal({});
let [bounds, setBounds] = createSignal({});
let [active, setActive] = createSignal(false);
onMount(() => {
let srcImage = document.getElementById("srcImage");
let canvas = document.getElementById("cropper");
let context = canvas.getContext("2d");
let cropBox = document.getElementById("cropBox");
if (srcImage instanceof HTMLImageElement) {
srcImage.onload = () => {
setBase({
width: srcImage.offsetWidth,
height: srcImage.offsetHeight,
x: srcImage.offsetLeft,
y: srcImage.offsetTop,
});
cropBox.style.width = `${srcImage.offsetHeight}px`;
cropBox.style.height = `${srcImage.offsetHeight}px`;
cropBox.style.position = "abolute";
cropBox.style.top = "0px";
cropBox.style.left = `${
srcImage.offsetWidth / 2 - srcImage.offsetHeight / 2
}px`;
srcImage.classList.add("hidden");
context.drawImage(srcImage, 0, 0, canvas.width, canvas.height);
setBounds({
width: cropBox.offsetWidth,
height: cropBox.offsetHeight,
x: cropBox.offsetLeft,
y: cropBox.offsetTop,
});
};
}
});
let moveBox = ({ x, y }) => {
let cropBox = document.getElementById("cropBox");
let mouseX = x;
cropBox.style.left = `${mouseX - base().x / 2}px`;
setBounds({
width: cropBox.offsetWidth,
height: cropBox.offsetHeight,
x: cropBox.offsetLeft,
y: cropBox.offsetTop,
});
};
let crop = async () => {
let cropper = document.getElementById("cropper");
let canvas = document.createElement("canvas");
let context = canvas.getContext("2d");
let url = cropper.toDataURL();
let image = new Image();
image.src = url;
image.onload = () => {
canvas.width = bounds().width;
canvas.height = bounds().height;
context.drawImage(
image,
0,
0,
bounds().width,
bounds().height,
0,
0,
bounds().width,
bounds().height
);
let url = canvas.toDataURL();
onContinue(url);
};
};
return (
<div class="absolute left-0 top-0 right-0 bottom-0 z-20">
<div
class="absolute bg-black bg-opacity-50 w-full h-full z-10"
onClick={() => onCancel()}
></div>
<div class="absolute flex flex-col justify-center items-center w-full h-full z-30">
<div class="relative flex flex-col w-96 h-auto space-y-5">
<img id="srcImage" src={src} height={512} />
<div
id="cropBox"
class="absolute flex border-l-2 border-t-2 border-r-2 border-b-2 border-white border-dashed"
onMouseDown={() => {
setActive(true);
}}
onMouseUp={() => {
setActive(false);
}}
onMouseMove={(event) => {
if (active()) moveBox({ x: event.offsetX, y: event.offsetY });
}}
></div>
<canvas
id="cropper"
class="bg-black"
width={base().width}
height={base().height}
onMouseDown={() => {
setActive(true);
}}
onMouseUp={() => {
setActive(false);
}}
onMouseMove={(event) => {
if (active()) moveBox({ x: event.offsetX, y: event.offsetY });
}}
></canvas>
<div class="flex justify-between items-center bg-gray-900 w-full h-auto p-2">
<div
class="flex justify-center items-center px-3 py-1 text-gray-400 hover:text-blue-500 cursor-pointer"
onClick={() => onCancel()}
>
Cancel
</div>
<div
class="flex justify-center items-center px-3 py-1 text-gray-400 hover:text-blue-500 cursor-pointer"
onClick={() => {
crop();
}}
>
Continue
</div>
</div>
</div>
</div>
</div>
);
};
export default Cropper;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment