big picture
This commit is contained in:
39
site.css
39
site.css
@@ -30,3 +30,42 @@ h1 {
|
||||
.Grid img {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.BigPicture {
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
left: 0;
|
||||
padding: 30px;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.BigPicture-image {
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.BigPicture-footer {
|
||||
align-self: center;
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
justify-content: space-between;
|
||||
margin-top: 30px;
|
||||
max-width: 200px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.BigPicture-footerLink {
|
||||
color: #69c;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.BigPicture-footerLink:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
38
src/components/big_picture.tsx
Normal file
38
src/components/big_picture.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import * as Model from "../model";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
export interface Props {
|
||||
src: string;
|
||||
image: Model.Image;
|
||||
onClose: () => void;
|
||||
width: number;
|
||||
}
|
||||
|
||||
export class BigPicture extends React.PureComponent<Props, {}> {
|
||||
static displayName = "BigPicture";
|
||||
|
||||
render() {
|
||||
const src = `img/1600/${this.props.src}`;
|
||||
return <div className="BigPicture">
|
||||
<div
|
||||
className="BigPicture-image"
|
||||
style={{
|
||||
backgroundImage: `url(${src})`
|
||||
}}>
|
||||
</div>
|
||||
<div className="BigPicture-footer">
|
||||
<a className="BigPicture-footerLink"
|
||||
href={`img/${this.props.src}`}
|
||||
target="_blank">
|
||||
Download
|
||||
</a>
|
||||
<span className="BigPicture-footerLink"
|
||||
onClick={this.props.onClose}
|
||||
tabIndex={1} >
|
||||
Close
|
||||
</span>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import * as React from "react";
|
||||
export interface Props {
|
||||
images: Model.Images;
|
||||
onImageSelected: (key: string) => void;
|
||||
selectedImage: string | null;
|
||||
width: number;
|
||||
}
|
||||
|
||||
@@ -52,7 +51,6 @@ export class Grid extends React.PureComponent<Props, {}> {
|
||||
return <Picture
|
||||
image={image}
|
||||
onClick={() => this.props.onImageSelected(key)}
|
||||
selected={this.props.selectedImage === key}
|
||||
src={key}
|
||||
key={key}
|
||||
width={image.width/image.height * scale}
|
||||
|
||||
@@ -6,7 +6,6 @@ export interface Props {
|
||||
src: string;
|
||||
image: Model.Image;
|
||||
onClick: () => void;
|
||||
selected?: boolean;
|
||||
width: number;
|
||||
}
|
||||
|
||||
@@ -16,11 +15,10 @@ export class Picture extends React.PureComponent<Props, {}> {
|
||||
render() {
|
||||
const src = `img/600/${this.props.src}`;
|
||||
return <img
|
||||
className={ this.props.selected ? "Picture-selected" : ""}
|
||||
onClick={this.props.onClick}
|
||||
srcSet={this._srcset()}
|
||||
src={src}
|
||||
width={ this.props.selected ? "100%" : this.props.width + "px" }
|
||||
width={ this.props.width + "px" }
|
||||
/>;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { BigPicture } from "./big_picture";
|
||||
import { Grid } from "./grid";
|
||||
import * as Model from "../model";
|
||||
|
||||
@@ -7,16 +8,15 @@ export interface Props {}
|
||||
|
||||
export interface State {
|
||||
images: Model.Images;
|
||||
selectedIamge?: string | null;
|
||||
selectedImage?: string | null;
|
||||
width: number;
|
||||
}
|
||||
|
||||
export class Root extends React.PureComponent<Props, State> {
|
||||
static displayName = "Root";
|
||||
|
||||
state = {
|
||||
state: State = {
|
||||
images: {},
|
||||
selectedImage: null,
|
||||
width: window.innerWidth
|
||||
}
|
||||
|
||||
@@ -29,24 +29,52 @@ export class Root extends React.PureComponent<Props, State> {
|
||||
window.onresize = () => {
|
||||
this.setState({ width: window.innerWidth });
|
||||
}
|
||||
|
||||
window.onpopstate = this._loadHash;
|
||||
|
||||
this._loadHash();
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className="Root">
|
||||
<h1>Ski</h1>
|
||||
<hr />
|
||||
{ this._bigPicture() }
|
||||
<Grid
|
||||
images={ this.state.images }
|
||||
onImageSelected={ this._onImageSelected }
|
||||
selectedImage={ this.state.selectedImage }
|
||||
width={ this.state.width } />
|
||||
</div>;
|
||||
}
|
||||
|
||||
private _bigPicture = () => {
|
||||
if (this.state.selectedImage && this.state.images[this.state.selectedImage]) {
|
||||
return <BigPicture
|
||||
image={this.state.images[this.state.selectedImage]}
|
||||
src={this.state.selectedImage}
|
||||
onClose={this._showGrid}
|
||||
width={this.state.width}
|
||||
/>
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private _loadHash = () => {
|
||||
if (window.location.hash.length > 0) {
|
||||
this.setState({ selectedImage: window.location.hash.slice(1) });
|
||||
} else {
|
||||
this.setState({ selectedImage: null });
|
||||
}
|
||||
}
|
||||
|
||||
private _onImageSelected = (key: string) => {
|
||||
this.setState(state => ({
|
||||
...state,
|
||||
selectedImage: key
|
||||
}));
|
||||
this.setState({ selectedImage: key });
|
||||
window.history.pushState(null, "", `#${key}`);
|
||||
}
|
||||
|
||||
private _showGrid = () => {
|
||||
this.setState({ selectedImage: null });
|
||||
window.history.pushState(null, "", "#");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user