diff --git a/src/components/CldImage/CldImage.vue b/src/components/CldImage/CldImage.vue
index 67b2001..63c3bc1 100644
--- a/src/components/CldImage/CldImage.vue
+++ b/src/components/CldImage/CldImage.vue
@@ -4,10 +4,10 @@ import { compute } from '../../mixins/compute';
import { register } from '../../mixins/registerTransformation'
import { computePlaceholder } from '../../helpers/computeOptions'
import { getCldPlaceholder, isCldPlaceholder } from '../../helpers/findComponent'
-import {
- ACCESSIBILITY_TRANSFORMATIONS,
- PLACEHOLDER_TRANSFORMATIONS,
- COMPONENTS,
+import {
+ ACCESSIBILITY_TRANSFORMATIONS,
+ PLACEHOLDER_TRANSFORMATIONS,
+ COMPONENTS,
LAZY_LOADING,
IMAGE_CLASSES,
IMAGE_WITH_PLACEHOLDER_CSS,
@@ -17,6 +17,7 @@ import {
} from '../../constants';
import { size } from "../../mixins/size";
import { lazy } from "../../mixins/lazy";
+import {getDevicePixelRatio} from '../../utils/getDevicePixelRatio';
/**
* Deliver images and specify image transformations using the cld-image (CldImage) component,
@@ -49,7 +50,7 @@ export default {
},
/**
* **Deprecated**
- *
+ *
* The placeholder image to use while the image is loading. Possible values:
* - `"blur"` to use blur placeholder
* - `"lqip"` to use a low quality image
@@ -92,14 +93,14 @@ export default {
}
return (
-
+ />
)
},
renderComp(children) {
@@ -114,7 +115,13 @@ export default {
const lazyModeInvisible = this.hasLazyLoading && !this.visible
const options = this.computeURLOptions()
- const src = responsiveModeNoSize || lazyModeInvisible ? '' : this.cloudinary.url(this.publicId, this.toSnakeCase(options))
+ let src = responsiveModeNoSize || lazyModeInvisible ? '' : this.cloudinary.url(this.publicId, this.toSnakeCase(options));
+ // Update dpr_auto to dpr_1.0, 2.0 etc but only for responsive mode
+ // This matches the behaviour in other SDKs
+ if (this.responsive) {
+ src = src.replace(/\bdpr_(1\.0|auto)\b/g, 'dpr_' + getDevicePixelRatio(true));
+ }
+
const cldPlaceholder = getCldPlaceholder(children)
const cldPlaceholderType = cldPlaceholder ? (cldPlaceholder.componentOptions?.propsData?.type || 'blur') : ''
const placeholderType = cldPlaceholderType || this.placeholder
@@ -159,6 +166,6 @@ export default {
}
return this.renderComp(children)
- }
+ }
};
diff --git a/src/utils/getDevicePixelRatio.js b/src/utils/getDevicePixelRatio.js
new file mode 100644
index 0000000..ce4c5d6
--- /dev/null
+++ b/src/utils/getDevicePixelRatio.js
@@ -0,0 +1,15 @@
+export function getDevicePixelRatio(roundDpr) {
+ roundDpr = roundDpr == null ? true : roundDpr;
+ let dpr = (typeof window !== "undefined" && window !== null ? window.devicePixelRatio : void 0) || 1;
+ if (roundDpr) {
+ dpr = Math.ceil(dpr);
+ }
+ if (dpr <= 0 || dpr === (0/0)) {
+ dpr = 1;
+ }
+ let dprString = dpr.toString();
+ if (dprString.match(/^\d+$/)) {
+ dprString += '.0';
+ }
+ return dprString;
+}
diff --git a/tests/unit/Image/img.spec.js b/tests/unit/Image/img.spec.js
index 73b6c42..cf6890d 100644
--- a/tests/unit/Image/img.spec.js
+++ b/tests/unit/Image/img.spec.js
@@ -66,14 +66,15 @@ describe("Tests for CldImage", () => {
});
});
- it("Supports transformation props", () => {
+ it("Supports transformation props, dpr_auto should not be changed when non responsive", () => {
let {wrapper, imgSrc} = mountImageComponent({
cloudName: 'demo',
publicId: 'face_top',
- effect:'sepia'
+ effect:'sepia',
+ dpr: 'auto'
});
- expect(imgSrc).toBe(`http://res.cloudinary.com/demo/image/upload/e_sepia/face_top`);
+ expect(imgSrc).toBe(`http://res.cloudinary.com/demo/image/upload/dpr_auto,e_sepia/face_top`);
});
it("Cascades non-cloudinary configuration attributes to the HTML img tag", () => {
diff --git a/tests/unit/Image/img_responsive_boolean.spec.js b/tests/unit/Image/img_responsive_boolean.spec.js
index 3ef1ebf..60d3fc7 100644
--- a/tests/unit/Image/img_responsive_boolean.spec.js
+++ b/tests/unit/Image/img_responsive_boolean.spec.js
@@ -6,11 +6,14 @@ describe("CldImage::responsive", () => {
it("boolean true", async () => {
const wrapper = mount({
template: `
-
+
`,
components: { CldImage },
data() {
- return { responsive: true };
+ return {
+ responsive: true,
+ dpr: 'auto'
+ };
}
});
const image = wrapper.find('img');
@@ -21,7 +24,7 @@ describe("CldImage::responsive", () => {
await Vue.nextTick();
expect(image.attributes("src")).toEqual(
- `http://res.cloudinary.com/demo/image/upload/c_scale,w_100/face_top`
+ `http://res.cloudinary.com/demo/image/upload/c_scale,dpr_1.0,w_100/face_top`
);
});