Skip to content

Commit

Permalink
IIIF and shuffle/timeline improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
jayvarner committed Nov 5, 2024
1 parent 6006fb1 commit 6dbe5fd
Show file tree
Hide file tree
Showing 27 changed files with 465 additions and 403 deletions.
2 changes: 0 additions & 2 deletions app/components/figures/Figure.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ export default function Figure({
groupCaption,
imageClassName,
id,
figureHeight,
figureWidth,
}: Props) {
const { hideSensitiveState } = useContext(ChapterContext);

Expand Down
3 changes: 1 addition & 2 deletions app/components/figures/IIIFViewer.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ClientOnly } from "remix-utils/client-only";

const fetchTileSource = async (figure: TFigure) => {
const response = await fetch(
`https://iip.readux.io/iiif/3/dxd/${figure.chapter}/${figure.fileName}.tiff/info.json`
`https://iiif.ecds.io/iiif/3/dxd/${figure.chapter}/${figure.fileName}.tiff/info.json`
);
const result = await response.json();
result.service[0].id = result.id;
Expand Down Expand Up @@ -49,7 +49,6 @@ const IIIFViewer = ({
};
fetchSource();
}
console.log("🚀 ~ figure:", figure);
}, [figure]);

if (tileSource && modalOpen) {
Expand Down
1 change: 1 addition & 0 deletions app/components/figures/Picture.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const Picture = ({ figure, className, center = true }: Props) => {
}
title={figure.title?.replace(/(<i>|<\/i>)/gi, '"') ?? figure.fileName}
draggable={!hideSensitiveState}
loading="lazy"
/>
</picture>
);
Expand Down
20 changes: 11 additions & 9 deletions app/components/home/DraggableTimeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default function DraggableTimeline({
}: Props) {
const { windowSize } = useResizeObserver();
const svgRef = useRef<SVGSVGElement>(null);
const [currentImageIndex, setCurrentImageIndex] = useState<number>(0);
const [currentImageIndex, setCurrentImageIndex] = useState<number>(selectedImage ? shuffledImages.indexOf(selectedImage) : 0);
const [isDragging, setIsDragging] = useState<boolean>(false);
const [startPosition, setStartPosition] = useState<startPosition | undefined>(
undefined
Expand Down Expand Up @@ -137,20 +137,22 @@ export default function DraggableTimeline({
className="relative z-10 right-0 focus:outline-none"
style={{ bottom: "39px" }}
>
{shuffledImages.map((img, index) => {
{shuffledImages.map((image, index) => {
const isSelected =
img.chapter === selectedImage?.chapter &&
img.fileName === selectedImage?.fileName;
image.chapter === selectedImage?.chapter &&
image.fileName === selectedImage?.fileName;
return (
<g key={img.fileName} id={img.fileName}>
<g key={image.fileName} id={image.fileName}>
<image
className={isSelected ? "outline outline-4 outline-red-500" : ""}
className={`cursor-pointer ${isSelected ? "outline outline-4 outline-red-500" : ""}`}
id={`index-${index}`}
style={{ cursor: "pointer" }}
// href={`/images/${img.chapter}/${img.fileName}.jpg`}
href={`https://iip.readux.io/iiif/3/dxd/${img.chapter}/${img.fileName}.tiff/full/75,/0/color.png`}
href={`https://iiif.ecds.io/iiif/3/dxd/${image.chapter}/${image.fileName}.tiff/full/150,/0/color.webp`}
width={150}
transform={getTransform(index)}
height={image.height && image.width ? Math.ceil(
(image.height / image.width) * 150
) : 150}
transform={getTransform(index)}
onMouseDown={() => {
setIsDragging(true);
setCurrentImageIndex(index);
Expand Down
51 changes: 29 additions & 22 deletions app/components/home/OrderedTimeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,16 @@ export default function OrderedTimeline({

useEffect(() => {
if (!selectedImage) return;
const selectedImageSelector = `img[src="/images/${selectedImage.chapter}/${selectedImage.fileName}.jpg`;
const selectedImageSelector = `img[src="https://iiif.ecds.io/iiif/3/dxd/${selectedImage.chapter}/${selectedImage.fileName}.tiff/full/150,/0/default.jpg`;
if (!sliderRef.current) return;
sliderRef.current
.querySelector<HTMLElement>(selectedImageSelector)
?.focus();
sliderRef.current
.querySelector<HTMLElement>(selectedImageSelector)
?.scrollIntoView({ block: "end", behavior: "smooth", inline: "center"});
}, [selectedImage]);

useEffect(() => {
setSelectedImage(sortedImages[currentImageIndex]);
// TODO: Rethink after homepage design changes
// sliderRef.current.scrollIntoView({ block: "end", behavior: "smooth" });
}, [setSelectedImage, currentImageIndex, sliderRef]);

const mouseDown = (pageX: number) => {
if (!sliderRef.current) return;
setMouseIsDown(true);
Expand Down Expand Up @@ -122,26 +119,36 @@ export default function OrderedTimeline({
selectedImage?.chapter === image.chapter &&
selectedImage?.fileName === image.fileName;
return (
<img
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-to-interactive-role
role="button"
<button
key={`otl-${image.fileName}`}
tabIndex={0}
onClick={() => updateSelected(image)}
onFocus={() => setSelectedImage(image)}
onKeyUp={() => setSelectedImage(image)}
className={classNames(
"absolute w-[150px] min-h-36 min-w-36 border border-red-400 bg-offwhite",
isSelected && "border-4 border-red-500"
)}
style={{
left: `${index * 10}px`,
top: "0",
zIndex: isSelected ? images.length + 1 : index + 1,
}}
src={`https://iip.readux.io/iiif/3/dxd/${image.chapter}/${image.fileName}.tiff/full/100,/0/color.jpg`}
alt={image.altText ?? ""}
/>
>
<picture>
<source srcSet={`https://iiif.ecds.io/iiif/3/dxd/${image.chapter}/${image.fileName}.tiff/full/150,/0/default.webp`} type="image/webp" />
<source srcSet={`https://iiif.ecds.io/iiif/3/dxd/${image.chapter}/${image.fileName}.tiff/full/150,/0/default.png`} type="image/png" />
<source srcSet={`https://iiif.ecds.io/iiif/3/dxd/${image.chapter}/${image.fileName}.tiff/full/150,/0/default.jpg`} type="image/jpg" />
<img
className={classNames(
"absolute w-[150px] min-h-36 min-w-36 border border-red-400 bg-offwhite",
isSelected && "border-4 border-red-500"
)}
style={{
left: `${index * 10}px`,
top: "0",
zIndex: isSelected ? images.length + 1 : index + 1,
}}
src={`https://iiif.ecds.io/iiif/3/dxd/${image.chapter}/${image.fileName}.tiff/full/150,/0/default.jpg`}
alt={image.altText ?? ""}
width={150}
height={image.height && image.width ? Math.ceil(
(image.height / image.width) * 150
) : 150}
/>
</picture>
</button>
);
})}
</div>
Expand Down
6 changes: 3 additions & 3 deletions app/components/home/SelectedImage.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ const SelectedImage = ({
>
<picture>
<source
srcSet={`https://iip.readux.io/iiif/3/dxd/${selectedImage.chapter}/${selectedImage.fileName}.tiff/full/,256/0/color.webp`}
srcSet={`https://iiif.ecds.io/iiif/3/dxd/${selectedImage.chapter}/${selectedImage.fileName}.tiff/full/,256/0/color.webp`}
/>
<source
srcSet={`https://iip.readux.io/iiif/3/dxd/${selectedImage.chapter}/${selectedImage.fileName}.tiff/full/,256/0/color.jpg`}
srcSet={`https://iiif.ecds.io/iiif/3/dxd/${selectedImage.chapter}/${selectedImage.fileName}.tiff/full/,256/0/color.jpg`}
/>
<img
src={`https://iip.readux.io/iiif/3/dxd/${selectedImage.chapter}/${selectedImage.fileName}.tiff/full/,256/0/color.jpg`}
src={`https://iiif.ecds.io/iiif/3/dxd/${selectedImage.chapter}/${selectedImage.fileName}.tiff/full/,256/0/color.jpg`}
alt={
selectedImage.altText?.replace(/(<i>|<\/i>)/gi, '"') ??
selectedImage.title?.replace(/(<i>|<\/i>)/gi, '"') ??
Expand Down
7 changes: 4 additions & 3 deletions app/components/home/Timeline.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const Timeline = ({ selectedImage, setSelectedImage }: Props) => {
setShuffledImages(randomTimelineImages(IMAGE_COUNT));
}, [shouldShuffle]);


useEffect(() => {
setSelectedImage(shuffledImages[0]);
}, [shuffledImages, setSelectedImage]);
Expand All @@ -33,12 +34,12 @@ const Timeline = ({ selectedImage, setSelectedImage }: Props) => {
<button
onClick={() => {
setTimelineType(TimelineType.Draggable);
setShouldShuffle((shouldShuffle) => !shouldShuffle);
setShouldShuffle(!shouldShuffle);
}}
type="button"
>
<img
className="w-14 m-2"
className="w-14 m-2 cursor-pointer"
src={
timelineType === TimelineType.Draggable
? "/images/ui/shuffle_click.png"
Expand All @@ -52,7 +53,7 @@ const Timeline = ({ selectedImage, setSelectedImage }: Props) => {
onClick={() => setTimelineType(TimelineType.Ordered)}
>
<img
className="w-14 m-2"
className="w-14 m-2 cursor-pointer"
src={
timelineType === TimelineType.Ordered
? "/images/ui/sort_selected.png"
Expand Down
35 changes: 18 additions & 17 deletions app/components/home/timelineUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,31 @@ import playfairFigures from "~/data/figures/playfair.json";
import shanawdithitFigures from "~/data/figures/shanawdithit.json";
import type { TFigure } from "~/types/figureType";

export type TFilteredFigures = (string | TFigure)[];
export type TFilteredFigures = [string, TFigure];

export enum TimelineType {
Draggable,
Ordered,
}

const filterFigures = (figures: TFilteredFigures) => {
console.log("🚀 ~ filterFigures ~ figures:", figures);
return figures[1].frontPage && figures[1].width;
};

export const timelineImages = () => {
const shanawdithit: TFilteredFigures[] = Object.entries(
shanawdithitFigures
).filter((figures) => figures[1].frontPage);

const description: TFilteredFigures[] = Object.entries(
descriptionFigures
).filter((figures) => figures[1].frontPage);
const allDubois: TFilteredFigures[] = Object.entries(duboisFigures).filter(
(figures) => figures[1].frontPage
);
const peabody: TFilteredFigures[] = Object.entries(peabodyFigures).filter(
(figures) => figures[1].frontPage
);
const playfair: TFilteredFigures[] = Object.entries(playfairFigures).filter(
(figures) => figures[1].frontPage
);
const shanawdithit: TFilteredFigures[] =
Object.entries(shanawdithitFigures).filter(filterFigures);

const description: TFilteredFigures[] =
Object.entries(descriptionFigures).filter(filterFigures);

const allDubois: TFilteredFigures[] =
Object.entries(duboisFigures).filter(filterFigures);
const peabody: TFilteredFigures[] =
Object.entries(peabodyFigures).filter(filterFigures);
const playfair: TFilteredFigures[] =
Object.entries(playfairFigures).filter(filterFigures);

const shuffledDubois = d3.shuffle(allDubois);
const dubois: TFilteredFigures[] = shuffledDubois.slice(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const IIIFViewer = ({ figure, scrollProgress }: Props) => {
const initViewer = async () => {
if (viewerRef.current) return;
const response = await fetch(
`https://iip.readux.io/iiif/3/dxd/shanawdithit/${figure}.tiff/info.json`
`https://iiif.ecds.io/iiif/3/dxd/shanawdithit/${figure}.tiff/info.json`
);

const info: TileSource = await response.json();
Expand Down
26 changes: 13 additions & 13 deletions app/data/chapterMeta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const chapterMeta: TChapterMeta = {
image:
"https://iip.readux/io/iiif/3/dxd/intro/7-1786_Playfair_-_1_Chart_of_all_the_import_and_exports_to_and_from_England_from_the_year_1700_to_1782.tiff/square/800,/0/default.jpg",
bgImage:
"https://iip.readux.io/iiif/3/dxd/intro/7-1786_Playfair_-_1_Chart_of_all_the_import_and_exports_to_and_from_England_from_the_year_1700_to_1782.tiff/193,274,721,264/full/0/default.jpg",
"https://iiif.ecds.io/iiif/3/dxd/intro/7-1786_Playfair_-_1_Chart_of_all_the_import_and_exports_to_and_from_England_from_the_year_1700_to_1782.tiff/193,274,721,264/full/0/default.jpg",
imageWidth: "800",
imageHeight: "800",
},
Expand All @@ -18,9 +18,9 @@ export const chapterMeta: TChapterMeta = {
description:
"Before there are data, there are people. People who offer up their lives as data — or whose lives become data without consent.",
image:
"https://iip.readux.io/iiif/3/dxd/description/5-The_history_of_the_rise.tiff/square/800,/0/default.jpg",
"https://iiif.ecds.io/iiif/3/dxd/description/5-The_history_of_the_rise.tiff/square/800,/0/default.jpg",
bgImage:
"https://iip.readux.io/iiif/3/dxd/description/5-The_history_of_the_rise.tiff/7,625,662,263/full/0/default.jpg",
"https://iiif.ecds.io/iiif/3/dxd/description/5-The_history_of_the_rise.tiff/7,625,662,263/full/0/default.jpg",
imageWidth: "800",
imageHeight: "800",
},
Expand All @@ -30,9 +30,9 @@ export const chapterMeta: TChapterMeta = {
description:
"Data visualization has never been neutral or objective. There is a meaning — and an argument — conveyed through each design.",
image:
"https://iip.readux.io/iiif/3/dxd/playfair/1-northamerica.tiff/square/800,/0/default.jpg",
"https://iiif.ecds.io/iiif/3/dxd/playfair/1-northamerica.tiff/square/800,/0/default.jpg",
bgImage:
"https://iip.readux.io/iiif/3/dxd/playfair/1-northamerica.tiff/190,242,1094,283/full/0/default.jpg",
"https://iiif.ecds.io/iiif/3/dxd/playfair/1-northamerica.tiff/190,242,1094,283/full/0/default.jpg",
imageWidth: "800",
imageHeight: "800",
},
Expand All @@ -42,9 +42,9 @@ export const chapterMeta: TChapterMeta = {
description:
"Maps can represent reality and can contest it. How can we learn to see the lines of power that they encode?",
image:
"https://iip.readux.io/iiif/3/dxd/shanawdithit/DRW-II.tiff/square/800,/0/default.jpg",
"https://iiif.ecds.io/iiif/3/dxd/shanawdithit/DRW-II.tiff/square/800,/0/default.jpg",
bgImage:
"https://iip.readux.io/iiif/3/dxd/shanawdithit/DRW-II.tiff/2384,4586,3446,1470/800,/0/default.jpg",
"https://iiif.ecds.io/iiif/3/dxd/shanawdithit/DRW-II.tiff/2384,4586,3446,1470/800,/0/default.jpg",
imageWidth: "800",
imageHeight: "800",
},
Expand All @@ -54,9 +54,9 @@ export const chapterMeta: TChapterMeta = {
description:
"We have explored only part of the history of data visualization. What possibilities can we imagine when we expand our view of the past?",
image:
"https://iip.readux.io/iiif/3/dxd/peabody/1600s.tiff/square/800,/0/default.jpg",
"https://iiif.ecds.io/iiif/3/dxd/peabody/1600s.tiff/square/800,/0/default.jpg",
bgImage:
"https://iip.readux.io/iiif/3/dxd/peabody/1600s.tiff/513,41,403,138/full/0/default.jpg",
"https://iiif.ecds.io/iiif/3/dxd/peabody/1600s.tiff/513,41,403,138/full/0/default.jpg",
imageWidth: "800",
imageHeight: "800",
},
Expand All @@ -66,9 +66,9 @@ export const chapterMeta: TChapterMeta = {
description:
"How can data visualization bear witness to oppression? How can we hold space for what cannot be conveyed through data alone?",
image:
"https://iip.readux.io/iiif/3/dxd/dubois/887.tiff/square/800,/0/default.jpg",
"https://iiif.ecds.io/iiif/3/dxd/dubois/887.tiff/square/800,/0/default.jpg",
bgImage:
"https://iip.readux.io/iiif/2/dxd/dubois/887.tiff/9,320,771,440/full/0/default.jpg",
"https://iiif.ecds.io/iiif/2/dxd/dubois/887.tiff/9,320,771,440/full/0/default.jpg",
imageWidth: "800",
imageHeight: "800",
},
Expand All @@ -78,9 +78,9 @@ export const chapterMeta: TChapterMeta = {
description:
"Any digital project is the work of many hands. How can this labor be visualized? What remains out of sight?",
image:
"https://iip.readux.io/iiif/3/dxd/labor/data-traces.tiff/square/800,/0/default.jpg",
"https://iiif.ecds.io/iiif/3/dxd/labor/data-traces.tiff/square/800,/0/default.jpg",
bgImage:
"https://iip.readux.io/iiif/3/dxd/labor/data-traces.tiff/870,221,686,260/full/0/default.jpg",
"https://iiif.ecds.io/iiif/3/dxd/labor/data-traces.tiff/870,221,686,260/full/0/default.jpg",
imageWidth: "800",
imageHeight: "800",
},
Expand Down
Loading

0 comments on commit 6dbe5fd

Please sign in to comment.