feat: add naturalWidth and naturalHeight bindings (#7857)

Closes #7771
---------

Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
pull/8321/head
Tan Li Hau 2 years ago committed by GitHub
parent ba8f979f03
commit d16dd5d7ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -751,6 +751,22 @@ Videos additionally have readonly `videoWidth` and `videoHeight` bindings.
></video> ></video>
``` ```
##### Image element bindings
---
Image elements (`<img>`) have two readonly bindings:
* `naturalWidth` (readonly) — the original width of the image, available after the image has loaded
* `naturalHeight` (readonly) — the original height of the image, available after the image has loaded
```sv
<img
bind:naturalWidth
bind:naturalHeight
></img>
```
##### Block-level element bindings ##### Block-level element bindings
--- ---

@ -22,7 +22,9 @@ const read_only_media_attributes = new Set([
'seeking', 'seeking',
'ended', 'ended',
'videoHeight', 'videoHeight',
'videoWidth' 'videoWidth',
'naturalWidth',
'naturalHeight'
]); ]);
export default class Binding extends Node { export default class Binding extends Node {

@ -918,6 +918,13 @@ export default class Element extends Node {
} else if (is_void(this.name)) { } else if (is_void(this.name)) {
return component.error(binding, compiler_errors.invalid_binding_on(binding.name, `void elements like <${this.name}>. Use a wrapper element instead`)); return component.error(binding, compiler_errors.invalid_binding_on(binding.name, `void elements like <${this.name}>. Use a wrapper element instead`));
} }
} else if (
name === 'naturalWidth' ||
name === 'naturalHeight'
) {
if (this.name !== 'img') {
return component.error(binding, compiler_errors.invalid_binding_element_with('<img>', name));
}
} else if ( } else if (
name === 'textContent' || name === 'textContent' ||
name === 'innerHTML' name === 'innerHTML'

@ -137,6 +137,10 @@ const events = [
event_names: ['toggle'], event_names: ['toggle'],
filter: (node: Element, _name: string) => filter: (node: Element, _name: string) =>
node.name === 'details' node.name === 'details'
},
{
event_names: ['load'],
filter: (_: Element, name: string) => name === 'naturalHeight' || name === 'naturalWidth'
} }
]; ];

@ -0,0 +1,95 @@
/* generated by Svelte vX.Y.Z */
import {
SvelteComponent,
add_render_callback,
attr,
detach,
element,
init,
insert,
listen,
noop,
safe_not_equal,
set_data,
space,
src_url_equal,
text
} from "svelte/internal";
function create_fragment(ctx) {
let img;
let img_src_value;
let t0;
let t1;
let t2;
let t3;
let mounted;
let dispose;
return {
c() {
img = element("img");
t0 = space();
t1 = text(/*naturalWidth*/ ctx[0]);
t2 = text(" x ");
t3 = text(/*naturalHeight*/ ctx[1]);
if (!src_url_equal(img.src, img_src_value = "something.jpg")) attr(img, "src", img_src_value);
if (/*naturalWidth*/ ctx[0] === void 0 || /*naturalHeight*/ ctx[1] === void 0) add_render_callback(() => /*img_load_handler*/ ctx[2].call(img));
},
m(target, anchor) {
insert(target, img, anchor);
insert(target, t0, anchor);
insert(target, t1, anchor);
insert(target, t2, anchor);
insert(target, t3, anchor);
if (!mounted) {
dispose = listen(img, "load", /*img_load_handler*/ ctx[2]);
mounted = true;
}
},
p(ctx, [dirty]) {
if (dirty & /*naturalWidth*/ 1) set_data(t1, /*naturalWidth*/ ctx[0]);
if (dirty & /*naturalHeight*/ 2) set_data(t3, /*naturalHeight*/ ctx[1]);
},
i: noop,
o: noop,
d(detaching) {
if (detaching) detach(img);
if (detaching) detach(t0);
if (detaching) detach(t1);
if (detaching) detach(t2);
if (detaching) detach(t3);
mounted = false;
dispose();
}
};
}
function instance($$self, $$props, $$invalidate) {
let { naturalWidth = 0 } = $$props;
let { naturalHeight = 0 } = $$props;
function img_load_handler() {
naturalWidth = this.naturalWidth;
naturalHeight = this.naturalHeight;
$$invalidate(0, naturalWidth);
$$invalidate(1, naturalHeight);
}
$$self.$$set = $$props => {
if ('naturalWidth' in $$props) $$invalidate(0, naturalWidth = $$props.naturalWidth);
if ('naturalHeight' in $$props) $$invalidate(1, naturalHeight = $$props.naturalHeight);
};
return [naturalWidth, naturalHeight, img_load_handler];
}
class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, { naturalWidth: 0, naturalHeight: 1 });
}
}
export default Component;

@ -0,0 +1,8 @@
<script>
export let naturalWidth = 0;
export let naturalHeight = 0;
</script>
<img src="something.jpg" bind:naturalWidth bind:naturalHeight>
{naturalWidth} x {naturalHeight}
Loading…
Cancel
Save