diff --git a/README.md b/README.md index 0c4909f8d..a61aaeb17 100644 --- a/README.md +++ b/README.md @@ -59,12 +59,20 @@ src | String | | (Required) URL for the original image. srcSet | String | | Default srcset attribute for a responsive original image. sizes | String | | Default sizes attribute for use with srcset. sources | Array | | A list of image sources for using the picture tag to serve the appropriate original image (see below for more details). +width | Number | | Width attribute for original image. +height | Number | | Height attribute for original image. +hasSpacer | Boolean | false | If true, gets the original image's aspect ratio based on the width and height props and creates a spacer to prevent cumulative layout shift. zoomSrc | String | | URL for the larger zoom image. Falls back to original image src if not defined. +zoomScale | Number | 1 | Multiplied against the natural width and height of the zoomed image. This will generally be a decimal (example, 0.9 for 90%). +zoomPreload | Boolean | false | If set to true, preloads the zoom image instead of waiting for mouseenter. alt | String | | Alternative text for the original image. moveType | String | pan | `pan` or `drag`. The user behavior for moving zoomed images on non-touch devices. +zoomType | String | click | `click` or `hover`. The zoom behavior for images. fadeDuration | Number | 150 | Fade transition time in milliseconds. If zooming in on transparent images, set this to `0` for best results. fullscreenOnMobile | Boolean | false | Enables fullscreen zoomed image on touch devices below a specified breakpoint. mobileBreakpoint | Number | 640 | The maximum breakpoint for fullscreen zoom image when fullscreenOnMobile is true. +hideCloseButton | Boolean | false | Hides the close button on touch devices. If set to true, zoom out is triggered by tap. +hideHint | Boolean | false | Hides the magnifying glass hint. className | String | | Custom classname for styling the component. afterZoomIn | Function | | Function to be called after zoom in. afterZoomOut | Function | | Function to be called after zoom out. diff --git a/demo/assets/unsplash3-large.jpg b/demo/assets/unsplash3-large.jpg new file mode 100644 index 000000000..cf333e43f Binary files /dev/null and b/demo/assets/unsplash3-large.jpg differ diff --git a/demo/assets/unsplash3.jpg b/demo/assets/unsplash3.jpg new file mode 100644 index 000000000..25444b711 Binary files /dev/null and b/demo/assets/unsplash3.jpg differ diff --git a/demo/src/App.vue b/demo/src/App.vue index 9912018a2..c955224fa 100644 --- a/demo/src/App.vue +++ b/demo/src/App.vue @@ -4,18 +4,33 @@

Pan Example

-
+

Drag Example

+
+
+

Zoom on Hover Example

+
@@ -28,6 +43,7 @@ export default { name: 'App', components: { InnerImageZoom - } + }, + props: ['srcs'] }; diff --git a/demo/src/index.js b/demo/src/index.js index e6b28e80b..e40ddfc63 100644 --- a/demo/src/index.js +++ b/demo/src/index.js @@ -4,5 +4,5 @@ import App from './App.vue'; Vue.config.productionTip = false; new Vue({ - render: (h) => h(App) + render: (h) => h(App, { props: { srcs: ['/assets/unsplash.jpg'] } }) }).$mount('#app'); diff --git a/src/InnerImageZoom/InnerImageZoom.vue b/src/InnerImageZoom/InnerImageZoom.vue index 0533a5126..42c335378 100644 --- a/src/InnerImageZoom/InnerImageZoom.vue +++ b/src/InnerImageZoom/InnerImageZoom.vue @@ -4,29 +4,54 @@ ref="img" v-bind:class="{ [className]: className, - 'iiz--drag': this.currentMoveType === 'drag' + 'iiz--drag': currentMoveType === 'drag' + }" + v-bind:style="{ + width: `${width}px` }" v-on="{ - touchstart: handleTouchStart, + touchstart: isZoomed ? () => {} : handleTouchStart, click: handleClick, mouseenter: isTouch ? () => {} : handleMouseEnter, mousemove: currentMoveType === 'drag' || !isZoomed ? () => {} : handleMouseMove, mouseleave: isTouch ? () => {} : handleMouseLeave }" > - + @@ -153,6 +165,10 @@ export default { type: String, default: 'pan' }, + zoomType: { + type: String, + default: 'click' + }, src: { type: String, required: true @@ -160,7 +176,15 @@ export default { srcSet: String, sizes: String, sources: Array, + width: Number, + height: Number, + hasSpacer: Boolean, zoomSrc: String, + zoomScale: { + type: Number, + default: 1 + }, + zoomPreload: Boolean, alt: String, fadeDuration: { type: Number, @@ -171,13 +195,15 @@ export default { type: Number, default: 640 }, + hideHint: Boolean, + hideCloseButton: Boolean, className: String, afterZoomIn: Function, afterZoomOut: Function }, data() { return { - isActive: false, + isActive: this.zoomPreload || false, isTouch: false, isZoomed: false, isFullscreen: false, @@ -194,11 +220,15 @@ export default { computed: { validSources: function () { return this.sources ? this.sources.filter((source) => source.srcSet) : []; + }, + createSpacer: function () { + return this.width && this.height && this.hasSpacer; } }, methods: { - handleMouseEnter() { + handleMouseEnter(e) { this.isActive = true; + this.zoomType === 'hover' && !this.isZoomed && this.handleClick(e); }, handleTouchStart() { this.isFullscreen = @@ -210,8 +240,10 @@ export default { }, handleClick(e) { if (this.isZoomed) { - if (!this.isTouch && !this.isDragging) { - this.zoomOut(); + if (this.isTouch) { + this.hideCloseButton && this.handleClose(); + } else { + !this.isDragging && this.zoomOut(); } return; @@ -221,15 +253,22 @@ export default { this.isActive = true; } - if (this.imgProps.isLoaded) { + if (this.imgProps.zoomImg) { this.zoomIn(e.pageX, e.pageY); } else { this.imgProps.onLoadCallback = this.zoomIn.bind(this, e.pageX, e.pageY); } }, handleLoad(e) { - this.imgProps.isLoaded = true; this.imgProps.zoomImg = e.target; + this.imgProps.zoomImg.setAttribute( + 'width', + this.imgProps.zoomImg.naturalWidth * this.zoomScale + ); + this.imgProps.zoomImg.setAttribute( + 'height', + this.imgProps.zoomImg.naturalHeight * this.zoomScale + ); this.imgProps.bounds = getBounds(this.$refs.img, false); this.imgProps.ratios = getRatios(this.imgProps.bounds, this.imgProps.zoomImg); @@ -368,7 +407,6 @@ export default { } }, setDefaults() { - this.imgProps.isLoaded = false; this.imgProps.onLoadCallback = null; this.imgProps.zoomImg = null; this.imgProps.bounds = {}; @@ -409,6 +447,7 @@ function getRatios(bounds, zoomImg) {