File size: 3,780 Bytes
eca7f7a 2e787a2 eca7f7a 2e787a2 eca7f7a 78b81a5 2e787a2 eca7f7a 2e787a2 78b81a5 2e787a2 78b81a5 2e787a2 78b81a5 2e787a2 78b81a5 2e787a2 78b81a5 2e787a2 78b81a5 2e787a2 eca7f7a 2e787a2 78b81a5 2e787a2 eca7f7a 2e787a2 eca7f7a 2e787a2 eca7f7a 2e787a2 eca7f7a |
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 125 126 127 |
import { useCallback } from "react";
import { useScreenshot } from "use-react-screenshot";
export function useStoryCapture() {
const [image, takeScreenshot] = useScreenshot({
type: "image/png",
quality: 1.0,
});
const calculateOptimalWidth = (element) => {
// Get all comic pages
const comicPages = element.querySelectorAll("[data-comic-page]");
if (!comicPages.length) return element.scrollWidth;
// Get width of a single page (they all have the same width)
const firstPage = comicPages[0];
const pageWidth = firstPage.offsetWidth;
const gap = 32; // Fixed gap between pages
const padding = 32; // Fixed padding on both sides
// Calculate total width:
// - All pages width (pageWidth * nbPages)
// - Gaps only between pages, so (nbPages - 1) gaps
// - Padding on both sides
const totalWidth =
pageWidth * comicPages.length +
(comicPages.length > 1 ? gap * (comicPages.length - 1) : 0) +
padding * 2;
console.log("Width calculation:", {
numberOfPages: comicPages.length,
pageWidth,
gapBetweenPages: gap,
totalGaps: comicPages.length > 1 ? gap * (comicPages.length - 1) : 0,
padding,
totalWidth,
});
return totalWidth;
};
const captureStory = useCallback(
async (containerRef) => {
if (!containerRef.current) return null;
const element = containerRef.current.querySelector("[data-comic-layout]");
if (!element) {
console.error("Comic layout container not found");
return null;
}
try {
// Save original styles
const originalStyle = element.style.cssText;
const originalScroll = element.scrollLeft;
const originalWidth = element.style.width;
const originalPadding = element.style.padding;
const originalGap = element.style.gap;
// Calculate optimal width
const optimalWidth = calculateOptimalWidth(element);
// Reset scroll and styles temporarily for the screenshot
Object.assign(element.style, {
width: `${optimalWidth}px`,
display: "flex",
flexDirection: "row",
gap: "32px",
padding: "32px",
paddingLeft: "32px !important", // Force override the dynamic padding
paddingRight: "32px !important", // Force override the dynamic padding
overflow: "hidden",
transition: "none", // Disable transitions during capture
});
element.scrollLeft = 0;
// Force reflow
element.offsetHeight;
// Take screenshot
const result = await takeScreenshot(element, {
backgroundColor: "#242424",
width: optimalWidth,
height: element.scrollHeight,
style: {
transform: "none",
transition: "none",
},
});
// Restore original styles
element.style.cssText = originalStyle;
element.style.width = originalWidth;
element.style.padding = originalPadding;
element.style.gap = originalGap;
element.scrollLeft = originalScroll;
return result;
} catch (error) {
console.error("Error capturing story:", error);
return null;
}
},
[takeScreenshot]
);
const downloadStoryImage = useCallback(
async (containerRef, filename = "my-story.png") => {
const image = await captureStory(containerRef);
if (!image) return;
const link = document.createElement("a");
link.href = image;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
},
[captureStory]
);
return {
captureStory,
downloadStoryImage,
};
}
|