-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from irohalab/responsive-image
add responsive image, this component is extract from mira-ui
- Loading branch information
Showing
7 changed files
with
466 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'; |
169 changes: 169 additions & 0 deletions
169
projects/irohalab/deneb-ui/src/responsive-image/responsive-image-wrapper.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
Oops, something went wrong.