项目原始demo,不改动
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 
 

259 lines
7.5 KiB

  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. require("../../../src/components/VImg/VImg.sass");
  7. var _intersect = _interopRequireDefault(require("../../directives/intersect"));
  8. var _VResponsive = _interopRequireDefault(require("../VResponsive"));
  9. var _console = require("../../util/console");
  10. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  11. // Styles
  12. // Directives
  13. // Components
  14. // Utils
  15. var hasIntersect = typeof window !== 'undefined' && 'IntersectionObserver' in window;
  16. /* @vue/component */
  17. var _default2 = _VResponsive.default.extend({
  18. name: 'v-img',
  19. directives: {
  20. intersect: _intersect.default
  21. },
  22. props: {
  23. alt: String,
  24. contain: Boolean,
  25. eager: Boolean,
  26. gradient: String,
  27. lazySrc: String,
  28. options: {
  29. type: Object,
  30. // For more information on types, navigate to:
  31. // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
  32. default: function _default() {
  33. return {
  34. root: undefined,
  35. rootMargin: undefined,
  36. threshold: undefined
  37. };
  38. }
  39. },
  40. position: {
  41. type: String,
  42. default: 'center center'
  43. },
  44. sizes: String,
  45. src: {
  46. type: [String, Object],
  47. default: ''
  48. },
  49. srcset: String,
  50. transition: {
  51. type: [Boolean, String],
  52. default: 'fade-transition'
  53. }
  54. },
  55. data: function data() {
  56. return {
  57. currentSrc: '',
  58. image: null,
  59. isLoading: true,
  60. calculatedAspectRatio: undefined,
  61. naturalWidth: undefined
  62. };
  63. },
  64. computed: {
  65. computedAspectRatio: function computedAspectRatio() {
  66. return Number(this.normalisedSrc.aspect || this.calculatedAspectRatio);
  67. },
  68. normalisedSrc: function normalisedSrc() {
  69. return typeof this.src === 'string' ? {
  70. src: this.src,
  71. srcset: this.srcset,
  72. lazySrc: this.lazySrc,
  73. aspect: Number(this.aspectRatio || 0)
  74. } : {
  75. src: this.src.src,
  76. srcset: this.srcset || this.src.srcset,
  77. lazySrc: this.lazySrc || this.src.lazySrc,
  78. aspect: Number(this.aspectRatio || this.src.aspect)
  79. };
  80. },
  81. __cachedImage: function __cachedImage() {
  82. if (!(this.normalisedSrc.src || this.normalisedSrc.lazySrc)) return [];
  83. var backgroundImage = [];
  84. var src = this.isLoading ? this.normalisedSrc.lazySrc : this.currentSrc;
  85. if (this.gradient) backgroundImage.push("linear-gradient(".concat(this.gradient, ")"));
  86. if (src) backgroundImage.push("url(\"".concat(src, "\")"));
  87. var image = this.$createElement('div', {
  88. staticClass: 'v-image__image',
  89. class: {
  90. 'v-image__image--preload': this.isLoading,
  91. 'v-image__image--contain': this.contain,
  92. 'v-image__image--cover': !this.contain
  93. },
  94. style: {
  95. backgroundImage: backgroundImage.join(', '),
  96. backgroundPosition: this.position
  97. },
  98. key: +this.isLoading
  99. });
  100. /* istanbul ignore if */
  101. if (!this.transition) return image;
  102. return this.$createElement('transition', {
  103. attrs: {
  104. name: this.transition,
  105. mode: 'in-out'
  106. }
  107. }, [image]);
  108. }
  109. },
  110. watch: {
  111. src: function src() {
  112. // Force re-init when src changes
  113. if (!this.isLoading) this.init(undefined, undefined, true);else this.loadImage();
  114. },
  115. '$vuetify.breakpoint.width': 'getSrc'
  116. },
  117. mounted: function mounted() {
  118. this.init();
  119. },
  120. methods: {
  121. init: function init(entries, observer, isIntersecting) {
  122. // If the current browser supports the intersection
  123. // observer api, the image is not observable, and
  124. // the eager prop isn't being used, do not load
  125. if (hasIntersect && !isIntersecting && !this.eager) return;
  126. if (this.normalisedSrc.lazySrc) {
  127. var lazyImg = new Image();
  128. lazyImg.src = this.normalisedSrc.lazySrc;
  129. this.pollForSize(lazyImg, null);
  130. }
  131. /* istanbul ignore else */
  132. if (this.normalisedSrc.src) this.loadImage();
  133. },
  134. onLoad: function onLoad() {
  135. this.getSrc();
  136. this.isLoading = false;
  137. this.$emit('load', this.src);
  138. },
  139. onError: function onError() {
  140. (0, _console.consoleError)("Image load failed\n\n" + "src: ".concat(this.normalisedSrc.src), this);
  141. this.$emit('error', this.src);
  142. },
  143. getSrc: function getSrc() {
  144. /* istanbul ignore else */
  145. if (this.image) this.currentSrc = this.image.currentSrc || this.image.src;
  146. },
  147. loadImage: function loadImage() {
  148. var _this = this;
  149. var image = new Image();
  150. this.image = image;
  151. image.onload = function () {
  152. /* istanbul ignore if */
  153. if (image.decode) {
  154. image.decode().catch(function (err) {
  155. (0, _console.consoleWarn)("Failed to decode image, trying to render anyway\n\n" + "src: ".concat(_this.normalisedSrc.src) + (err.message ? "\nOriginal error: ".concat(err.message) : ''), _this);
  156. }).then(_this.onLoad);
  157. } else {
  158. _this.onLoad();
  159. }
  160. };
  161. image.onerror = this.onError;
  162. image.src = this.normalisedSrc.src;
  163. this.sizes && (image.sizes = this.sizes);
  164. this.normalisedSrc.srcset && (image.srcset = this.normalisedSrc.srcset);
  165. this.aspectRatio || this.pollForSize(image);
  166. this.getSrc();
  167. },
  168. pollForSize: function pollForSize(img) {
  169. var _this2 = this;
  170. var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100;
  171. var poll = function poll() {
  172. var naturalHeight = img.naturalHeight,
  173. naturalWidth = img.naturalWidth;
  174. if (naturalHeight || naturalWidth) {
  175. _this2.naturalWidth = naturalWidth;
  176. _this2.calculatedAspectRatio = naturalWidth / naturalHeight;
  177. } else {
  178. timeout != null && setTimeout(poll, timeout);
  179. }
  180. };
  181. poll();
  182. },
  183. genContent: function genContent() {
  184. var content = _VResponsive.default.options.methods.genContent.call(this);
  185. if (this.naturalWidth) {
  186. this._b(content.data, 'div', {
  187. style: {
  188. width: "".concat(this.naturalWidth, "px")
  189. }
  190. });
  191. }
  192. return content;
  193. },
  194. __genPlaceholder: function __genPlaceholder() {
  195. if (this.$slots.placeholder) {
  196. var placeholder = this.isLoading ? [this.$createElement('div', {
  197. staticClass: 'v-image__placeholder'
  198. }, this.$slots.placeholder)] : [];
  199. if (!this.transition) return placeholder[0];
  200. return this.$createElement('transition', {
  201. props: {
  202. appear: true,
  203. name: this.transition
  204. }
  205. }, placeholder);
  206. }
  207. }
  208. },
  209. render: function render(h) {
  210. var node = _VResponsive.default.options.render.call(this, h);
  211. node.data.staticClass += ' v-image'; // Only load intersect directive if it
  212. // will work in the current browser.
  213. if (hasIntersect) {
  214. node.data.directives = [{
  215. name: 'intersect',
  216. modifiers: {
  217. once: true
  218. },
  219. value: {
  220. handler: this.init,
  221. options: this.options
  222. }
  223. }];
  224. }
  225. node.data.attrs = {
  226. role: this.alt ? 'img' : undefined,
  227. 'aria-label': this.alt
  228. };
  229. node.children = [this.__cachedSizer, this.__cachedImage, this.__genPlaceholder(), this.genContent()];
  230. return h(node.tag, node.data, node.children);
  231. }
  232. });
  233. exports.default = _default2;
  234. //# sourceMappingURL=VImg.js.map