From 0e85ce97226af34c63e685117344d4d303c524b7 Mon Sep 17 00:00:00 2001 From: Avior Date: Thu, 13 May 2021 18:15:34 +0200 Subject: [PATCH] Dasticly changed Image component It is now WAY lighter and LESS buggy Signed-off-by: Avior --- src/dzeio/Image/Image.module.styl | 65 ++++---- src/dzeio/Image/index.tsx | 239 ++++++++++-------------------- 2 files changed, 108 insertions(+), 196 deletions(-) diff --git a/src/dzeio/Image/Image.module.styl b/src/dzeio/Image/Image.module.styl index 02cb3e7..0971a88 100644 --- a/src/dzeio/Image/Image.module.styl +++ b/src/dzeio/Image/Image.module.styl @@ -1,43 +1,34 @@ .parent - position relative - display inline-flex + transition-property padding, width, height, background, top, left + transition-duration .3s + transition-timing-function ease-in-out + cursor pointer -.image - transition .3s - object-fit contain - z-index 2 - - &.ph1 - position fixed - transition 0s - - - &.ph2 - width 100% !important - position fixed - max-width 100% !important - max-height 100% !important - box-sizing border-box - padding 5% - top 0 !important - left 0 !important +// Animation part 1 +// this is set to move the image from a normal position to a fixed one +// + one the image itself there is style with position +.fs1 + position fixed + z-index 1000 + padding 0 + > div + width 100% height 100% - background #000000A0 +// Animation part 2 +// this animation move the card from its original pos to a fullscreen one +.fs2 + padding 8px + width 100% !important + height 100vh !important + background rgba(black, 50%) + // padding 0 + user-select none + top 0 !important + left 0 !important + > div + width 100% + height 100% - &.after - background #00000000 - // height 100% - box-sizing border-box - position fixed - // width 100% - z-index 0 - padding initial - - -.hideOverflow +.body overflow hidden - - -.none - display none diff --git a/src/dzeio/Image/index.tsx b/src/dzeio/Image/index.tsx index 32b9d97..0ae0fe6 100644 --- a/src/dzeio/Image/index.tsx +++ b/src/dzeio/Image/index.tsx @@ -1,182 +1,103 @@ -import React from 'react' -import { buildClassName } from '../Util' -import NextImage from 'next/image' +import React, { MouseEventHandler } from 'react' +import NextImage, { ImageProps } from 'next/image' import css from './Image.module.styl' +import { buildClassName } from '../Util' -export interface ImageProps { - src: string - deleteOnError?: boolean - canFullscreen?: boolean - width: number - height: number - alt?: string - - // ClassNames - parentClassName?: string - className?: string - - // Events - onClick?: () => void +interface Props { + imageProps: ImageProps + /** + * Define if the image can go fullscreen + */ + fullscreen?: boolean } -type evType = React.SyntheticEvent +interface States { + image?: { + size: [number | string, number | string] + pos: [number, number] + } + transform?: [number, number] + className?: string +} -export default class Image extends React.Component { +export default class Image extends React.Component { - private ref: React.RefObject = React.createRef() - private plchldr: React.RefObject = React.createRef() - private parent: React.RefObject = React.createRef() - private pic: React.RefObject = React.createRef() + public state: States = {} - private cardPos: Array = [] - private cardSize: Array = [] + private animationCount = 0 - private isFullscreen = false - - public async componentDidMount() { - if (this.props.canFullscreen) { - window.addEventListener('scroll', this.onScroll) - window.addEventListener('resize', this.onResize) - this.onScroll() - this.onResize() + public componentDidUpdate() { + if (!this.props.fullscreen) {return} + if (this.state.image) { + document.body.classList.add(css.body) + } else { + document.body.classList.remove(css.body) } } - public async componentDidUpdate() { - this.pic.current?.classList.remove(css.none) - if (this.props.canFullscreen) { - this.onScroll() - this.onResize() - } - if (this.isFullscreen) { - this.onClick() - } - } - - public async componentWillUnmount() { - if (this.props.canFullscreen) { - window.removeEventListener('scroll', this.onScroll) - window.removeEventListener('resize', this.onResize) - } + public componentWillUnmount() { + if (!this.props.fullscreen) {return} + document.body.classList.remove(css.body) } public render() { - const pic = ( -
- -
- ) - if (this.props.canFullscreen) { - return ( -
-
- {pic} + if (!this.props.fullscreen) { + return + } + return ( + <> + {this.state.image && ( +
+ )} + +
+
- ) - } - return pic + + ) } - private onScroll = async () => { - if (!this.ref.current || this.isFullscreen || !this.props.canFullscreen) { - return - } - - this.cardPos = [this.ref.current.offsetTop - window.scrollY, this.ref.current.offsetLeft - window.scrollX] - this.ref.current.style.top = this.cardPos[0] + 'px' - this.ref.current.style.left = this.cardPos[1] + 'px' - } - - private onResize = async () => { - if (!this.ref.current || !this.plchldr.current || !this.props.canFullscreen || this.isFullscreen) { - return - } - let tmp = [this.ref.current.offsetHeight, this.ref.current.offsetWidth] - if (this.parent.current) { - tmp = [this.parent.current.offsetHeight, this.ref.current.offsetWidth] - } - this.plchldr.current.style.width = `${tmp[1]}px` - this.plchldr.current.style.height = `${tmp[0]}px` - } - - private onClick = async () => { - if (!this.ref.current || !this.props.canFullscreen || !this.plchldr.current) { - return - } - if (this.props.onClick) { - this.props.onClick() - } - - const i = this.ref.current - const c = this.plchldr.current - const body = document.body - i.style.top = this.cardPos[0] + 'px' - i.style.left = this.cardPos[1] + 'px' - - if (this.isFullscreen) { - i.style.width = this.cardSize[1] + 'px' - i.style.height = this.cardSize[0] + 'px' - body.classList.remove(css.hideOverflow) - i.classList.remove(css.ph2) - i.classList.add(css.after) - + private onClick: MouseEventHandler = (ev) => { + const target = ev.currentTarget + const isFullscreen = !(this.state.image && this.state.className) + const currentCount = ++this.animationCount + this.setState(isFullscreen ? { + image: this.state.image ?? { + size: [target.offsetWidth, target.offsetHeight], + pos: [target.offsetLeft - window.scrollX, target.offsetTop - window.scrollY] + }, + className: undefined + } : { + className: undefined + }, () => { setTimeout(() => { - if (i.classList.contains(css.ph2) || i.classList.contains(css.ph1) || this.isFullscreen) { + if (this.animationCount !== currentCount) { return } - const w = this.valToPixel(this.props.width) - const mh = this.valToPixel(this.props?.height) - const mw = this.valToPixel(this.props?.width) - c.classList.add(css.none) - i.style.height = '' - i.style.width = w - i.style.maxHeight = mh - i.style.maxWidth = mw - i.classList.remove(css.after) - }, 350) - this.isFullscreen = false - } else { - i.classList.add(css.ph1) - c.classList.remove(css.none) - i.classList.add(css.ph2) - i.classList.remove(css.ph1) - body.classList.add(css.hideOverflow) - this.isFullscreen = true - } + this.setState({ + className: isFullscreen ? css.fs2 : undefined, + image: isFullscreen ? this.state.image : undefined + }) + }, isFullscreen ? 10 : 310) + }) } - - private valToPixel(value: number|string|undefined): string { - if (typeof value === 'number') { - return `${value}px` - } - if (typeof value === 'undefined') { - return '' - } - return value - } - - private onLoad = async (ev: evType) => { - ev.currentTarget.style.height = '' - ev.currentTarget.style.width = '' - } - - private onError = async (ev: evType) => { - this.w('Picture not loaded', ev.currentTarget.src) - ev.currentTarget.parentElement?.classList.add(css.none) - } - - private w(...messages: any) { - console.warn('[ Picture ]', ...messages) - } - }