<span class="supt-line">
    <span class="supt-line__inner"></span>
</span>

No notes defined.

<span class="supt-line">
	<span class="supt-line__inner"></span>
</span>
/* No context defined. */
  • Content:
    import { animate, JSAnimation, onScroll } from 'animejs';
    
    import { Sizes } from '@/js/Sizes';
    import { BREAKPOINTS } from '@/js/constants';
    
    export interface LineOptions {
    	scale: {
    		mobile: {
    			x: number[];
    			y: number[];
    		};
    		desktop: {
    			x: number[];
    			y: number[];
    		};
    	};
    	threshold: {
    		enter: string;
    		leave?: string;
    	};
    	sync?: boolean | string;
    	desktopBreakpoint?: (typeof BREAKPOINTS)[keyof typeof BREAKPOINTS];
    }
    
    export class Line {
    	$element: HTMLElement;
    	$container: HTMLElement;
    	$inner: HTMLElement;
    
    	options: LineOptions;
    	sizes: Sizes;
    	animation: JSAnimation | null = null;
    
    	constructor($element: HTMLElement, $container: HTMLElement, options: LineOptions) {
    		this.$element = $element;
    		this.$container = $container;
    		this.$inner = this.$element.querySelector('.supt-line__inner') as HTMLElement;
    		this.options = options;
    		this.sizes = new Sizes(); // Use Singleton
    
    		this.init();
    
    		window.addEventListener('resize', this.handleResize.bind(this));
    	}
    
    	init() {
    		if (this.animation) {
    			this.animation.cancel();
    		}
    
    		const scaleX =
    			this.sizes.currentWidth >= (this.options.desktopBreakpoint ?? BREAKPOINTS.md)
    				? this.options.scale.desktop.x
    				: this.options.scale.mobile.x;
    		const scaleY =
    			this.sizes.currentWidth >= (this.options.desktopBreakpoint ?? BREAKPOINTS.md)
    				? this.options.scale.desktop.y
    				: this.options.scale.mobile.y;
    
    		this.animation = animate(this.$inner, {
    			scaleX,
    			scaleY,
    			ease: 'linear',
    			autoplay: onScroll({
    				container: document.body,
    				target: this.$container,
    				enter: this.options.threshold.enter,
    				leave: this.options.threshold.leave,
    				sync: this.options.sync ?? true,
    			}),
    		});
    	}
    
    	private handleResize(): void {
    		this.init();
    	}
    }
    
    export class LineGlow {
    	$element: HTMLElement;
    	$container: HTMLElement;
    	$glow: HTMLElement;
    
    	options: LineOptions;
    	sizes: Sizes;
    	animation: JSAnimation | null = null;
    
    	constructor($element: HTMLElement, $container: HTMLElement, options: LineOptions) {
    		this.$element = $element;
    		this.$container = $container;
    		this.$glow = this.$element.querySelector('.supt-line__glow') as HTMLElement;
    		this.options = options;
    		this.sizes = new Sizes(); // Use Singleton
    
    		this.init();
    
    		window.addEventListener('resize', this.handleResize.bind(this));
    	}
    
    	init() {
    		if (this.animation) {
    			this.animation.cancel();
    		}
    
    		const height = this.$element.offsetHeight / 1.2 + 2;
    		this.$glow.style.strokeDasharray = `${height}`;
    
    		this.animation = animate(this.$glow, {
    			strokeDashoffset: [height, 0],
    			ease: 'linear',
    			autoplay: onScroll({
    				container: document.body,
    				target: this.$container,
    				enter: this.options.threshold.enter,
    				leave: this.options.threshold.leave,
    				sync: this.options.sync ?? true,
    			}),
    		});
    	}
    
    	private handleResize(): void {
    		this.init();
    	}
    }
    
  • URL: /components/raw/line/index.ts
  • Filesystem Path: src/components/atoms/line/index.ts
  • Size: 2.8 KB
  • Content:
    .supt-line {
    	pointer-events: none;
    
    	&:not(.-glow) {
    		display: block;
    		width: var(--line-xs-width);
    		height: var(--line-xs-height);
    		background-color: $color-grey-2;
    
    		@media (min-width: $breakpoint-md) {
    			width: var(--line-md-width);
    			height: var(--line-md-height);
    		}
    
    		.supt-line__inner {
    			position: absolute;
    			top: 0;
    			left: 0;
    			width: var(--line-xs-width);
    			height: var(--line-xs-height);
    			background-color: $color-main;
    			transform-origin: top;
    
    			@media (min-width: $breakpoint-md) {
    				width: var(--line-md-width);
    				height: var(--line-md-height);
    			}
    		}
    	}
    
    	&.-glow {
    		position: relative;
    		width: 100%;
    		height: 100%;
    
    		.supt-line__line {
    			position: relative;
    			display: block;
    			width: 1px;
    			height: 100%;
    			background-color: $color-new;
    			left: 50%;
    			transform: translateX(-50%);
    		}
    
    		.supt-line__glow {
    			position: absolute;
    			top: 0;
    			left: calc(-50% + 1px);
    			width: auto;
    			height: 100%;
    			transform-origin: top;
    			overflow: visible;
    			transform: scaleY(1.2) translateX(-50%);
    			stroke-dasharray: 600;
    		}
    	}
    }
    
  • URL: /components/raw/line/line.css
  • Filesystem Path: src/components/atoms/line/line.css
  • Size: 1.1 KB