Skip to content

Commit

Permalink
Image block: Fix stretched images constrained by max-width (#53274)
Browse files Browse the repository at this point in the history
* Fix dragging to resize from stretching image in the frontend

* Add image block v7 deprecation

* Update deprecation comment

* Prevent image losing its aspect ratio at smaller window dimensions

* Revert "Prevent image losing its aspect ratio at smaller window dimensions"

This reverts commit 8ac9f8c.

---------

Co-authored-by: scruffian <ben@scruffian.com>
  • Loading branch information
ajlende and scruffian committed Aug 3, 2023
1 parent af0beae commit 8a29e63
Show file tree
Hide file tree
Showing 12 changed files with 278 additions and 33 deletions.
4 changes: 2 additions & 2 deletions packages/block-library/src/image/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@
"__experimentalRole": "content"
},
"width": {
"type": "number"
"type": "string"
},
"height": {
"type": "number"
"type": "string"
},
"aspectRatio": {
"type": "string"
Expand Down
209 changes: 208 additions & 1 deletion packages/block-library/src/image/deprecated.js
Original file line number Diff line number Diff line change
Expand Up @@ -740,4 +740,211 @@ const v6 = {
},
};

export default [ v6, v5, v4, v3, v2, v1 ];
/**
* Deprecation for converting to string width and height block attributes and
* removing the width and height img element attributes which are not needed
* as they get added by the TODO hook.
*
* @see https://github.com/WordPress/gutenberg/pull/53274
*/
const v7 = {
attributes: {
align: {
type: 'string',
},
url: {
type: 'string',
source: 'attribute',
selector: 'img',
attribute: 'src',
__experimentalRole: 'content',
},
alt: {
type: 'string',
source: 'attribute',
selector: 'img',
attribute: 'alt',
default: '',
__experimentalRole: 'content',
},
caption: {
type: 'string',
source: 'html',
selector: 'figcaption',
__experimentalRole: 'content',
},
title: {
type: 'string',
source: 'attribute',
selector: 'img',
attribute: 'title',
__experimentalRole: 'content',
},
href: {
type: 'string',
source: 'attribute',
selector: 'figure > a',
attribute: 'href',
__experimentalRole: 'content',
},
rel: {
type: 'string',
source: 'attribute',
selector: 'figure > a',
attribute: 'rel',
},
linkClass: {
type: 'string',
source: 'attribute',
selector: 'figure > a',
attribute: 'class',
},
id: {
type: 'number',
__experimentalRole: 'content',
},
width: {
type: 'number',
},
height: {
type: 'number',
},
aspectRatio: {
type: 'string',
},
scale: {
type: 'string',
},
sizeSlug: {
type: 'string',
},
linkDestination: {
type: 'string',
},
linkTarget: {
type: 'string',
source: 'attribute',
selector: 'figure > a',
attribute: 'target',
},
},
supports: {
anchor: true,
behaviors: {
lightbox: true,
},
color: {
text: false,
background: false,
},
filter: {
duotone: true,
},
__experimentalBorder: {
color: true,
radius: true,
width: true,
__experimentalSkipSerialization: true,
__experimentalDefaultControls: {
color: true,
radius: true,
width: true,
},
},
},
migrate( { width, height, ...attributes } ) {
return {
...attributes,
width: `${ width }px`,
height: `${ height }px`,
};
},
save( { attributes } ) {
const {
url,
alt,
caption,
align,
href,
rel,
linkClass,
width,
height,
aspectRatio,
scale,
id,
linkTarget,
sizeSlug,
title,
} = attributes;

const newRel = ! rel ? undefined : rel;
const borderProps = getBorderClassesAndStyles( attributes );

const classes = classnames( {
[ `align${ align }` ]: align,
[ `size-${ sizeSlug }` ]: sizeSlug,
'is-resized': width || height,
'has-custom-border':
!! borderProps.className ||
( borderProps.style &&
Object.keys( borderProps.style ).length > 0 ),
} );

const imageClasses = classnames( borderProps.className, {
[ `wp-image-${ id }` ]: !! id,
} );

const image = (
<img
src={ url }
alt={ alt }
className={ imageClasses || undefined }
style={ {
...borderProps.style,
aspectRatio,
objectFit: scale,
width,
height,
} }
width={ width }
height={ height }
title={ title }
/>
);

const figure = (
<>
{ href ? (
<a
className={ linkClass }
href={ href }
target={ linkTarget }
rel={ newRel }
>
{ image }
</a>
) : (
image
) }
{ ! RichText.isEmpty( caption ) && (
<RichText.Content
className={ __experimentalGetElementClassName(
'caption'
) }
tagName="figcaption"
value={ caption }
/>
) }
</>
);

return (
<figure { ...useBlockProps.save( { className: classes } ) }>
{ figure }
</figure>
);
},
};

export default [ v7, v6, v5, v4, v3, v2, v1 ];
52 changes: 28 additions & 24 deletions packages/block-library/src/image/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ export default function Image( {
linkTarget,
sizeSlug,
} = attributes;

// The only supported unit is px, so we can parseInt to strip the px here.
const numericWidth = width ? parseInt( width, 10 ) : undefined;
const numericHeight = height ? parseInt( height, 10 ) : undefined;

const imageRef = useRef();
const prevCaption = usePrevious( caption );
const [ showCaption, setShowCaption ] = useState( !! caption );
Expand Down Expand Up @@ -473,23 +478,14 @@ export default function Image( {
</ToolsPanelItem>
) }
<DimensionsTool
value={ {
width: width && `${ width }px`,
height: height && `${ height }px`,
scale,
aspectRatio,
} }
value={ { width, height, scale, aspectRatio } }
onChange={ ( newValue ) => {
// Rebuilding the object forces setting `undefined`
// for values that are removed since setAttributes
// doesn't do anything with keys that aren't set.
setAttributes( {
width:
newValue.width &&
parseInt( newValue.width, 10 ),
height:
newValue.height &&
parseInt( newValue.height, 10 ),
width: newValue.width,
height: newValue.height,
scale: newValue.scale,
aspectRatio: newValue.aspectRatio,
} );
Expand Down Expand Up @@ -587,8 +583,8 @@ export default function Image( {
<ImageEditor
id={ id }
url={ url }
width={ width }
height={ height }
width={ numericWidth }
height={ numericHeight }
clientWidth={ fallbackClientWidth }
naturalHeight={ naturalHeight }
naturalWidth={ naturalWidth }
Expand All @@ -604,14 +600,18 @@ export default function Image( {
} else if ( ! isResizable ) {
img = <div style={ { width, height, aspectRatio } }>{ img }</div>;
} else {
const numericRatio = aspectRatio && evalAspectRatio( aspectRatio );
const customRatio = numericWidth / numericHeight;
const ratio =
( aspectRatio && evalAspectRatio( aspectRatio ) ) ||
( width && height && width / height ) ||
naturalWidth / naturalHeight ||
1;

const currentWidth = ! width && height ? height * ratio : width;
const currentHeight = ! height && width ? width / ratio : height;
numericRatio || customRatio || naturalWidth / naturalHeight || 1;
const currentWidth =
! numericWidth && numericHeight
? numericHeight * ratio
: numericWidth;
const currentHeight =
! numericHeight && numericWidth
? numericWidth / ratio
: numericHeight;

const minWidth =
naturalWidth < naturalHeight ? MIN_SIZE : MIN_SIZE * ratio;
Expand Down Expand Up @@ -687,10 +687,14 @@ export default function Image( {
onResizeStart={ onResizeStart }
onResizeStop={ ( event, direction, elt ) => {
onResizeStop();
// Since the aspect ratio is locked when resizing, we can
// use the width of the resized element to calculate the
// height in CSS to prevent stretching when the max-width
// is reached.
setAttributes( {
width: elt.offsetWidth,
height: elt.offsetHeight,
aspectRatio: undefined,
width: `${ elt.offsetWidth }px`,
height: 'auto',
aspectRatio: `${ ratio }`,
} );
} }
resizeRatio={ align === 'center' ? 2 : 1 }
Expand Down
2 changes: 0 additions & 2 deletions packages/block-library/src/image/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ export default function save( { attributes } ) {
width,
height,
} }
width={ width }
height={ height }
title={ title }
/>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<!-- wp:image {"align":"left","width":100,"height":100} -->
<figure class="wp-block-image alignleft is-resized"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" alt="" style="width:100px;height:100px" width="100" height="100"/></figure>
<figure class="wp-block-image alignleft is-resized"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" alt="" style="width:100px;height:100px"/></figure>
<!-- /wp:image -->
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<!-- wp:image {"align":"left","width":100,"height":100} -->
<figure class="wp-block-image alignleft is-resized"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" alt="" style="width:100px;height:100px" width="100" height="100"/></figure>
<figure class="wp-block-image alignleft is-resized"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" alt="" style="width:100px;height:100px"/></figure>
<!-- /wp:image -->
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<!-- wp:image {"align":"left","id":13,"width":358,"height":164,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image alignleft size-large is-resized"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" alt="" class="wp-image-13" style="width:358px;height:164px" width="358" height="164"/></figure>
<figure class="wp-block-image alignleft size-large is-resized"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" alt="" class="wp-image-13" style="width:358px;height:164px"/></figure>
<!-- /wp:image -->
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<!-- wp:image {"align":"left","width":164,"height":164,"sizeSlug":"large","className":"is-style-rounded","style":{"border":{"radius":"100%"}}} -->
<figure class="wp-block-image alignleft size-large is-resized has-custom-border is-style-rounded"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" alt="" style="border-radius:100%;width:164px;height:164px" width="164" height="164"/></figure>
<figure class="wp-block-image alignleft size-large is-resized has-custom-border is-style-rounded"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" alt="" style="border-radius:100%;width:164px;height:164px"/></figure>
<!-- /wp:image -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<!-- wp:image {"width":164,"height":164,"sizeSlug":"large"} -->
<figure class="wp-block-image size-large is-resized"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" alt="" style="width:164px;height:164px;" width="164" height="164"/></figure>
<!-- /wp:image -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[
{
"name": "core/image",
"isValid": true,
"attributes": {
"url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==",
"alt": "",
"caption": "",
"sizeSlug": "large",
"width": "164px",
"height": "164px"
},
"innerBlocks": []
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[
{
"blockName": "core/image",
"attrs": {
"width": 164,
"height": 164,
"sizeSlug": "large"
},
"innerBlocks": [],
"innerHTML": "\n<figure class=\"wp-block-image size-large is-resized\"><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==\" alt=\"\" style=\"width:164px;height:164px;\" width=\"164\" height=\"164\"/></figure>\n",
"innerContent": [
"\n<figure class=\"wp-block-image size-large is-resized\"><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==\" alt=\"\" style=\"width:164px;height:164px;\" width=\"164\" height=\"164\"/></figure>\n"
]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<!-- wp:image {"width":"164px","height":"164px","sizeSlug":"large"} -->
<figure class="wp-block-image size-large is-resized"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" alt="" style="width:164px;height:164px"/></figure>
<!-- /wp:image -->

0 comments on commit 8a29e63

Please sign in to comment.