1
0
mirror of https://github.com/mastodon/mastodon synced 2024-11-28 14:58:21 +09:00

Fix focal point cropping in MediaGallery, fix focal point modal (#6740)

* Use object-position with object-fit instead of JS top/left

* Fix focal point modal
This commit is contained in:
Eugen Rochko 2018-03-11 15:12:33 +01:00 committed by GitHub
parent 56333cca88
commit 56eb5c3f34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 62 deletions

View File

@ -12,26 +12,6 @@ const messages = defineMessages({
toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Toggle visibility' }, toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Toggle visibility' },
}); });
const shiftToPoint = (containerToImageRatio, containerSize, imageSize, focusSize, toMinus) => {
const containerCenter = Math.floor(containerSize / 2);
const focusFactor = (focusSize + 1) / 2;
const scaledImage = Math.floor(imageSize / containerToImageRatio);
let focus = Math.floor(focusFactor * scaledImage);
if (toMinus) focus = scaledImage - focus;
let focusOffset = focus - containerCenter;
const remainder = scaledImage - focus;
const containerRemainder = containerSize - containerCenter;
if (remainder < containerRemainder) focusOffset -= containerRemainder - remainder;
if (focusOffset < 0) focusOffset = 0;
return (focusOffset * -100 / containerSize) + '%';
};
class Item extends React.PureComponent { class Item extends React.PureComponent {
static contextTypes = { static contextTypes = {
@ -44,8 +24,6 @@ class Item extends React.PureComponent {
index: PropTypes.number.isRequired, index: PropTypes.number.isRequired,
size: PropTypes.number.isRequired, size: PropTypes.number.isRequired,
onClick: PropTypes.func.isRequired, onClick: PropTypes.func.isRequired,
containerWidth: PropTypes.number,
containerHeight: PropTypes.number,
}; };
static defaultProps = { static defaultProps = {
@ -84,7 +62,7 @@ class Item extends React.PureComponent {
} }
render () { render () {
const { attachment, index, size, standalone, containerWidth, containerHeight } = this.props; const { attachment, index, size, standalone } = this.props;
let width = 50; let width = 50;
let height = 100; let height = 100;
@ -143,45 +121,16 @@ class Item extends React.PureComponent {
const originalUrl = attachment.get('url'); const originalUrl = attachment.get('url');
const originalWidth = attachment.getIn(['meta', 'original', 'width']); const originalWidth = attachment.getIn(['meta', 'original', 'width']);
const originalHeight = attachment.getIn(['meta', 'original', 'height']);
const hasSize = typeof originalWidth === 'number' && typeof previewWidth === 'number'; const hasSize = typeof originalWidth === 'number' && typeof previewWidth === 'number';
const srcSet = hasSize ? `${originalUrl} ${originalWidth}w, ${previewUrl} ${previewWidth}w` : null; const srcSet = hasSize ? `${originalUrl} ${originalWidth}w, ${previewUrl} ${previewWidth}w` : null;
const sizes = hasSize ? `(min-width: 1025px) ${320 * (width / 100)}px, ${width}vw` : null; const sizes = hasSize ? `(min-width: 1025px) ${320 * (width / 100)}px, ${width}vw` : null;
const focusX = attachment.getIn(['meta', 'focus', 'x']); const focusX = attachment.getIn(['meta', 'focus', 'x']) || 0;
const focusY = attachment.getIn(['meta', 'focus', 'y']); const focusY = attachment.getIn(['meta', 'focus', 'y']) || 0;
const imageStyle = {}; const x = ((focusX / 2) + .5) * 100;
const y = ((focusY / -2) + .5) * 100;
if (originalWidth && originalHeight && containerWidth && containerHeight && focusX && focusY) {
const widthRatio = originalWidth / (containerWidth * (width / 100));
const heightRatio = originalHeight / (containerHeight * (height / 100));
let hShift = 0;
let vShift = 0;
if (widthRatio > heightRatio) {
hShift = shiftToPoint(heightRatio, (containerWidth * (width / 100)), originalWidth, focusX);
} else if(widthRatio < heightRatio) {
vShift = shiftToPoint(widthRatio, (containerHeight * (height / 100)), originalHeight, focusY, true);
}
if (originalWidth > originalHeight) {
imageStyle.height = '100%';
imageStyle.width = 'auto';
imageStyle.minWidth = '100%';
} else {
imageStyle.height = 'auto';
imageStyle.width = '100%';
imageStyle.minHeight = '100%';
}
imageStyle.top = vShift;
imageStyle.left = hShift;
} else {
imageStyle.height = '100%';
}
thumbnail = ( thumbnail = (
<a <a
@ -196,7 +145,7 @@ class Item extends React.PureComponent {
sizes={sizes} sizes={sizes}
alt={attachment.get('description')} alt={attachment.get('description')}
title={attachment.get('description')} title={attachment.get('description')}
style={imageStyle} style={{ objectPosition: `${x}% ${y}%` }}
/> />
</a> </a>
); );
@ -320,7 +269,7 @@ export default class MediaGallery extends React.PureComponent {
if (this.isStandaloneEligible()) { if (this.isStandaloneEligible()) {
children = <Item standalone onClick={this.handleClick} attachment={media.get(0)} />; children = <Item standalone onClick={this.handleClick} attachment={media.get(0)} />;
} else { } else {
children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} onClick={this.handleClick} attachment={attachment} index={i} size={size} containerWidth={width} containerHeight={style.height} />); children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} onClick={this.handleClick} attachment={attachment} index={i} size={size} />);
} }
} }

View File

@ -103,7 +103,7 @@ export default class FocalPointModal extends ImmutablePureComponent {
const height = media.getIn(['meta', 'original', 'height']) || null; const height = media.getIn(['meta', 'original', 'height']) || null;
return ( return (
<div className='modal-root__modal video-modal'> <div className='modal-root__modal video-modal focal-point-modal'>
<div className={classNames('focal-point', { dragging })} ref={this.setRef}> <div className={classNames('focal-point', { dragging })} ref={this.setRef}>
<ImageLoader <ImageLoader
previewSrc={media.get('preview_url')} previewSrc={media.get('preview_url')}

View File

@ -4315,18 +4315,16 @@ a.status-card {
display: block; display: block;
text-decoration: none; text-decoration: none;
color: $ui-secondary-color; color: $ui-secondary-color;
height: 100%;
line-height: 0; line-height: 0;
&, &,
img { img {
height: 100%;
width: 100%; width: 100%;
} }
img { img {
position: relative;
object-fit: cover; object-fit: cover;
height: auto;
} }
} }
@ -5076,6 +5074,12 @@ noscript {
} }
} }
.focal-point-modal {
max-width: 80vw;
max-height: 80vh;
position: relative;
}
.focal-point { .focal-point {
position: relative; position: relative;
cursor: pointer; cursor: pointer;
@ -5085,6 +5089,14 @@ noscript {
cursor: move; cursor: move;
} }
img {
max-width: 80vw;
max-height: 80vh;
width: auto;
height: auto;
margin: auto;
}
&__reticle { &__reticle {
position: absolute; position: absolute;
width: 100px; width: 100px;