Skip to content

Commit

Permalink
Merge pull request #10 from irohalab/responsive-image
Browse files Browse the repository at this point in the history
add responsive image, this component is extract from mira-ui
  • Loading branch information
EverettSummer authored Sep 9, 2024
2 parents 1d47c6a + 6b7eae2 commit 1f9b029
Show file tree
Hide file tree
Showing 7 changed files with 466 additions and 2 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "deneb-ui",
"version": "4.2.0",
"version": "4.3.0",
"scripts": {
"ng": "ng",
"start": "ng serve --project Deneb-UI-Demo",
Expand Down
31 changes: 31 additions & 0 deletions projects/irohalab/deneb-ui/src/core/dom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// select closet parent element
export function closest(el: any, selector: string) {
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;

while (el) {
if (matchesSelector.call(el, selector)) {
return el;
} else {
el = el.parentElement;
}
}
return null;
}

export function getRemPixel(remValue: number): number {
return remValue * parseFloat(window.getComputedStyle(document.body).getPropertyValue('font-size').match(/(\d+(?:\.\d+)?)px/)[1]);
}

/**
* get the vw in pixel
* @param value
*/
export function getVwInPixel(value: number): number {
let w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
return value / 100 * w;
}

export function getVhInPixel(value: number): number {
let h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
return value / 100 * h;
}
4 changes: 3 additions & 1 deletion projects/irohalab/deneb-ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ const UI_MODULES = [
UIScrollbarModule,
UIDropdownModule,
UIToggleModule,
UIPopoverModule
UIPopoverModule,

];

@NgModule({
Expand All @@ -40,5 +41,6 @@ export * from './scrollbar';
export * from './dropdown';
export * from './toggle';
export * from './popover';
export * from './responsive-image';

export * from './dark-theme.service';
17 changes: 17 additions & 0 deletions projects/irohalab/deneb-ui/src/responsive-image/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { NgModule } from '@angular/core';
import { UIResponsiveImage } from './responsive-image.directive';
import { UIResponsiveService } from './responsive.service';
import { UIResponsiveImageWrapper } from './responsive-image-wrapper';

@NgModule({
declarations: [UIResponsiveImage, UIResponsiveImageWrapper],
providers: [UIResponsiveService],
exports: [UIResponsiveImage, UIResponsiveImageWrapper]
})
export class UIResponsiveImageModule {

}

export * from './responsive.service';
export * from './responsive-image.directive'
export * from './responsive-image-wrapper';
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { ResponsiveDimension, UIResponsiveImage } from './responsive-image.directive';

export interface ResponsiveWrapperSize {
/**
* can be rem, em, pixel, %, vw, auto
*/
width?: string;
/**
* can be rem, em, pixel, %, vh, auto
*/
height?: string;
/**
* A value represents height / width
* If ratio is used, width must have value and cannot be auto,
* and height will be ignored.
*/
ratio?: number;

/**
* the image original width and height in pixel
*/
originalWidth: number;
originalHeight: number;
}

export const DEFAULT_HIDDEN_OPACITY = 0.01;

@Component({
selector: 'ui-responsive-image',
template: `<img class="responsive-image"
[originalSrc]="src"
[dimension]="dimension"
[style.width]="imageWidth"
[style.height]="imageHeight"
[style.position]="imagePosition"
[style.opacity]="imageOpacity"
(imageLoad)="onLoad($event)"
(imageError)="onError($event)">`,
styles: [`
:host {
box-sizing: border-box;
position: relative;
}
.responsive-image {
display: block;
object-fit: cover;
transition: opacity 500ms;
}
`],
host: {
'[style.display]': 'display',
'[style.width]': 'hostWidth',
'[style.height]': 'hostHeight',
'[style.paddingBottom]': 'hostPaddingBottom',
'[style.background]': 'background'
}
})
export class UIResponsiveImageWrapper {

dimension: ResponsiveDimension;

@Input()
src: string;

@Input()
display: string = 'block';

@Input()
set size(s: ResponsiveWrapperSize) {
let dimen: ResponsiveDimension;
if (s.ratio) {
this.imageWidth = '100%';
this.imageHeight = '100%';
this.hostWidth = s.width;
this.hostHeight = '0';
this.hostPaddingBottom = `${s.ratio * 100}%`;
this.imagePosition = 'absolute';
let widthInPixel = UIResponsiveImage.getPx(s.width);
if (widthInPixel !== 0) {
dimen = {
width: `${widthInPixel}px`,
height: `${widthInPixel * s.ratio}px`,
originalWidth: s.originalWidth,
originalHeight: s.originalHeight
};
} else {
if (s.originalHeight / s.originalWidth < s.ratio) {
dimen = {
width: 'auto',
height: '100%',
originalWidth: s.originalWidth,
originalHeight: s.originalHeight
}
} else {
dimen = {
width: '100%',
height: 'auto',
originalWidth: s.originalWidth,
originalHeight: s.originalHeight
}
}
}
} else {
this.hostWidth = s.width;
this.hostHeight = s.height;
dimen = {
width: 'auto',
height: 'auto',
originalWidth: s.originalWidth,
originalHeight: s.originalHeight
};
if (s.width === 'auto') {
this.imageWidth = 'auto';
} else {
this.imageWidth = '100%';
let widthInPixel = Math.round(UIResponsiveImage.getPx(s.width));
if (widthInPixel !== 0) {
dimen.width = `${widthInPixel}px`;
} else {
dimen.width = '100%';
}
}

if (s.height === 'auto') {
this.imageHeight = 'auto';
} else {
this.imageHeight = '100%';
let heightInPixel = Math.round(UIResponsiveImage.getPx(s.height));
if (heightInPixel !== 0) {
dimen.height = `${heightInPixel}px`;
} else {
dimen.height = '100%';
}
}
}
this.dimension = dimen;
};

@Input()
background: string = '#cccccc'; // color

hostWidth: string;
hostHeight: string;
hostPaddingBottom: string = '0';

imageWidth: string;
imageHeight: string;
imagePosition: string = 'static';

imageOpacity: number = DEFAULT_HIDDEN_OPACITY;

@Output()
imageLoad = new EventEmitter<Event>();

@Output()
imageError = new EventEmitter<Event>();

onLoad(event: Event) {
this.imageOpacity = 1;
this.imageLoad.emit(event);
}

onError(event: Event) {
this.imageOpacity = DEFAULT_HIDDEN_OPACITY;
this.imageError.emit(event);
}
}
Loading

0 comments on commit 1f9b029

Please sign in to comment.