itube-specs 0.0.970 → 0.0.971
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/card/model-mini.vue +6 -2
- package/components/info/main.vue +3 -0
- package/components/search/item.vue +1 -0
- package/composables/use-test-model-images.ts +9 -1
- package/package.json +1 -1
- package/runtime/utils/converters/convert-model-to-round-card.ts +3 -2
- package/types/card-info.d.ts +2 -0
- package/types/model-card.d.ts +3 -0
- package/types/search-top-models.d.ts +1 -0
|
@@ -56,13 +56,17 @@ const props = defineProps<{
|
|
|
56
56
|
const fallbackImage = '/img/model-placeholder.webp';
|
|
57
57
|
const imageError = ref(false);
|
|
58
58
|
|
|
59
|
+
/** Аватар 48px, крупнее мелкой ступени сюда не надо: при DPR3 нужно всего 144. */
|
|
59
60
|
const currentImage = computed(() => {
|
|
60
61
|
if (imageError.value) return fallbackImage;
|
|
61
|
-
return props.card.primaryImageUrl || props.card.thumbUrl || fallbackImage;
|
|
62
|
+
return props.card.primaryImageSmallUrl || props.card.primaryImageUrl || props.card.thumbUrl || fallbackImage;
|
|
62
63
|
});
|
|
63
64
|
|
|
64
65
|
const currentImageUrls = computed(() => (imageError.value ? undefined : props.card.primaryImageUrls));
|
|
65
|
-
const currentAvifSrc = computed(() =>
|
|
66
|
+
const currentAvifSrc = computed(() => {
|
|
67
|
+
if (imageError.value) return undefined;
|
|
68
|
+
return props.card.primaryImageSmallAvifUrl || props.card.primaryImageAvifUrl;
|
|
69
|
+
});
|
|
66
70
|
</script>
|
|
67
71
|
|
|
68
72
|
<style lang="scss">
|
package/components/info/main.vue
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
<UiImg
|
|
16
16
|
v-if="card.img"
|
|
17
17
|
:src="currentImage"
|
|
18
|
+
:avif-src="currentAvifSrc"
|
|
18
19
|
:image-urls="currentImageUrls"
|
|
19
20
|
:alt="title"
|
|
20
21
|
:sizes="IMG_SIZES"
|
|
@@ -217,6 +218,8 @@ const IMG_SIZES = `auto, (max-width: ${CSS_BREAKPOINTS.sm - 1}px) 80px, 96px`;
|
|
|
217
218
|
|
|
218
219
|
const currentImageUrls = computed(() => (imageError.value ? undefined : props.card.imgUrls));
|
|
219
220
|
|
|
221
|
+
const currentAvifSrc = computed(() => (imageError.value ? undefined : props.card.imgAvifUrl));
|
|
222
|
+
|
|
220
223
|
function getParameter(name: string) {
|
|
221
224
|
return props.card.parameters?.find(p => p.name === name)?.values?.[ 0 ]?.name;
|
|
222
225
|
}
|
|
@@ -2,6 +2,8 @@ export interface ITestModelPortrait {
|
|
|
2
2
|
primaryImageUrl: string;
|
|
3
3
|
thumbUrl: string;
|
|
4
4
|
primaryImageAvifUrl?: string;
|
|
5
|
+
primaryImageSmallUrl?: string;
|
|
6
|
+
primaryImageSmallAvifUrl?: string;
|
|
5
7
|
}
|
|
6
8
|
|
|
7
9
|
const PORTRAIT_COUNT = 16;
|
|
@@ -13,6 +15,10 @@ const PORTRAIT_COUNT = 16;
|
|
|
13
15
|
* - `?img=webp` — только webp, без avif-ветки;
|
|
14
16
|
* - без параметра — avif q63 4:4:4 через `<picture>`, фолбэк webp `-q 85 -m 6 -pass 10 -sharp_yuv`.
|
|
15
17
|
*
|
|
18
|
+
* Две ширины: 640w в карточку сетки и 300w во всё мелкое — круглые аватары, мини-карточки,
|
|
19
|
+
* подсказки поиска. 300w закрывает их с запасом даже при DPR3 (круглому нужно 288) и весит
|
|
20
|
+
* 8.5 KB против 40.6 у полного файла. Выбирает не браузер, а компонент: srcset мы не ставим.
|
|
21
|
+
*
|
|
16
22
|
* Качество ступеней подобрано по равной ошибке в высоких частотах: webp q85 даёт 0.00405,
|
|
17
23
|
* avif q63 — 0.00399. Вес при этом 645 против 434 KB на 16 картинок, то есть avif легче на
|
|
18
24
|
* треть при том же качестве. Разрыв держится на всём диапазоне, от точки не зависит.
|
|
@@ -41,8 +47,10 @@ export function useTestModelImages() {
|
|
|
41
47
|
|
|
42
48
|
return {
|
|
43
49
|
primaryImageUrl: `${base}-q85.webp`,
|
|
44
|
-
thumbUrl: `${base}-q85.webp`,
|
|
50
|
+
thumbUrl: `${base}-300-q85.webp`,
|
|
51
|
+
primaryImageSmallUrl: `${base}-300-q85.webp`,
|
|
45
52
|
primaryImageAvifUrl: format === 'webp' ? undefined : `${base}-q63.avif`,
|
|
53
|
+
primaryImageSmallAvifUrl: format === 'webp' ? undefined : `${base}-300-q63.avif`,
|
|
46
54
|
};
|
|
47
55
|
});
|
|
48
56
|
|
package/package.json
CHANGED
|
@@ -5,9 +5,10 @@ import { convertString } from './convert-string';
|
|
|
5
5
|
export function convertModelToRoundCard(model: IModelCard): IRoundCard {
|
|
6
6
|
return {
|
|
7
7
|
title: model.title,
|
|
8
|
-
|
|
8
|
+
// Круглому аватару крупнее мелкой ступени не нужно: 96px при DPR3 просит 288.
|
|
9
|
+
primaryImageUrl: model.primaryImageSmallUrl || model.primaryImageUrl || model.thumbUrl || '',
|
|
9
10
|
primaryImageUrls: model.primaryImageUrls,
|
|
10
|
-
primaryImageAvifUrl: model.primaryImageAvifUrl,
|
|
11
|
+
primaryImageAvifUrl: model.primaryImageSmallAvifUrl || model.primaryImageAvifUrl,
|
|
11
12
|
videosCount: model.videosCount,
|
|
12
13
|
link: `/models/${convertString().toSlug(model.title)}`,
|
|
13
14
|
};
|
package/types/card-info.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export interface ICardInfo {
|
|
|
8
8
|
description: string;
|
|
9
9
|
videosCount: number;
|
|
10
10
|
img?: string;
|
|
11
|
+
/** Тот же кадр в avif. Есть — рендерится через `<picture>`, `img` фолбэком. */
|
|
12
|
+
imgAvifUrl?: string;
|
|
11
13
|
/** Ладдер портрета под srcset. Нет — рендерится один `img`. */
|
|
12
14
|
imgUrls?: IModelImageUrls;
|
|
13
15
|
guid?: string;
|
package/types/model-card.d.ts
CHANGED
|
@@ -7,6 +7,9 @@ export interface IModelCard {
|
|
|
7
7
|
primaryImageUrl?: string;
|
|
8
8
|
/** Тот же портрет в avif. Есть — карточка отдаёт его через `<picture>`, webp фолбэком. */
|
|
9
9
|
primaryImageAvifUrl?: string;
|
|
10
|
+
/** Мелкая ступень 300w: круглые аватары, мини-карточки, подсказки поиска. */
|
|
11
|
+
primaryImageSmallUrl?: string;
|
|
12
|
+
primaryImageSmallAvifUrl?: string;
|
|
10
13
|
/** Ладдер портрета под srcset. Нет — карточка рендерит один `primaryImageUrl`. */
|
|
11
14
|
primaryImageUrls?: IModelImageUrls;
|
|
12
15
|
guid: string;
|