@jjlmoya/utils-audiovisual 1.16.0 → 1.18.0
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/package.json +1 -1
- package/src/category/index.ts +2 -0
- package/src/entries.ts +4 -1
- package/src/index.ts +1 -0
- package/src/pages/[locale]/[slug].astro +28 -12
- package/src/tests/locale_completeness.test.ts +2 -36
- package/src/tests/shared-test-helpers.ts +56 -0
- package/src/tests/tool_exports.test.ts +34 -0
- package/src/tests/tool_validation.test.ts +2 -2
- package/src/tool/chromaticLens/bibliography.ts +12 -0
- package/src/tool/chromaticLens/chromatic-lens-color-palette-extraction-online.css +39 -39
- package/src/tool/chromaticLens/entry.ts +2 -0
- package/src/tool/chromaticLens/i18n/de.ts +1 -15
- package/src/tool/chromaticLens/i18n/en.ts +1 -15
- package/src/tool/chromaticLens/i18n/es.ts +1 -13
- package/src/tool/chromaticLens/i18n/fr.ts +1 -13
- package/src/tool/chromaticLens/i18n/id.ts +1 -15
- package/src/tool/chromaticLens/i18n/it.ts +1 -15
- package/src/tool/chromaticLens/i18n/ja.ts +1 -15
- package/src/tool/chromaticLens/i18n/ko.ts +1 -15
- package/src/tool/chromaticLens/i18n/nl.ts +1 -15
- package/src/tool/chromaticLens/i18n/pl.ts +1 -15
- package/src/tool/chromaticLens/i18n/pt.ts +1 -15
- package/src/tool/chromaticLens/i18n/ru.ts +1 -15
- package/src/tool/chromaticLens/i18n/sv.ts +1 -15
- package/src/tool/chromaticLens/i18n/tr.ts +1 -15
- package/src/tool/chromaticLens/i18n/zh.ts +1 -15
- package/src/tool/chromaticLens/seo.astro +1 -1
- package/src/tool/collageMaker/bibliography.ts +8 -0
- package/src/tool/collageMaker/entry.ts +2 -0
- package/src/tool/collageMaker/free-online-photo-collage-maker-professional-compositions.css +47 -47
- package/src/tool/collageMaker/i18n/de.ts +1 -11
- package/src/tool/collageMaker/i18n/en.ts +1 -11
- package/src/tool/collageMaker/i18n/es.ts +1 -9
- package/src/tool/collageMaker/i18n/fr.ts +1 -9
- package/src/tool/collageMaker/i18n/id.ts +1 -11
- package/src/tool/collageMaker/i18n/it.ts +1 -11
- package/src/tool/collageMaker/i18n/ja.ts +1 -11
- package/src/tool/collageMaker/i18n/ko.ts +1 -11
- package/src/tool/collageMaker/i18n/nl.ts +1 -11
- package/src/tool/collageMaker/i18n/pl.ts +1 -11
- package/src/tool/collageMaker/i18n/pt.ts +1 -11
- package/src/tool/collageMaker/i18n/ru.ts +1 -11
- package/src/tool/collageMaker/i18n/sv.ts +1 -11
- package/src/tool/collageMaker/i18n/tr.ts +1 -11
- package/src/tool/collageMaker/i18n/zh.ts +1 -11
- package/src/tool/collageMaker/seo.astro +1 -1
- package/src/tool/depthOfFieldCalculator/bibliography.astro +15 -0
- package/src/tool/depthOfFieldCalculator/bibliography.ts +20 -0
- package/src/tool/depthOfFieldCalculator/component.astro +341 -0
- package/src/tool/depthOfFieldCalculator/depth-of-field-calculator.css +417 -0
- package/src/tool/depthOfFieldCalculator/entry.ts +52 -0
- package/src/tool/depthOfFieldCalculator/i18n/de.ts +141 -0
- package/src/tool/depthOfFieldCalculator/i18n/en.ts +141 -0
- package/src/tool/depthOfFieldCalculator/i18n/es.ts +141 -0
- package/src/tool/depthOfFieldCalculator/i18n/fr.ts +141 -0
- package/src/tool/depthOfFieldCalculator/i18n/id.ts +141 -0
- package/src/tool/depthOfFieldCalculator/i18n/it.ts +141 -0
- package/src/tool/depthOfFieldCalculator/i18n/ja.ts +141 -0
- package/src/tool/depthOfFieldCalculator/i18n/ko.ts +141 -0
- package/src/tool/depthOfFieldCalculator/i18n/nl.ts +141 -0
- package/src/tool/depthOfFieldCalculator/i18n/pl.ts +141 -0
- package/src/tool/depthOfFieldCalculator/i18n/pt.ts +141 -0
- package/src/tool/depthOfFieldCalculator/i18n/ru.ts +141 -0
- package/src/tool/depthOfFieldCalculator/i18n/sv.ts +141 -0
- package/src/tool/depthOfFieldCalculator/i18n/tr.ts +141 -0
- package/src/tool/depthOfFieldCalculator/i18n/zh.ts +141 -0
- package/src/tool/depthOfFieldCalculator/index.ts +10 -0
- package/src/tool/depthOfFieldCalculator/logic.ts +91 -0
- package/src/tool/depthOfFieldCalculator/seo.astro +15 -0
- package/src/tool/exifCleaner/bibliography.ts +12 -0
- package/src/tool/exifCleaner/entry.ts +2 -0
- package/src/tool/exifCleaner/exif-metadata-cleaner-remove-gps-photo-privacy.css +36 -36
- package/src/tool/exifCleaner/i18n/de.ts +1 -15
- package/src/tool/exifCleaner/i18n/en.ts +1 -15
- package/src/tool/exifCleaner/i18n/es.ts +1 -15
- package/src/tool/exifCleaner/i18n/fr.ts +1 -15
- package/src/tool/exifCleaner/i18n/id.ts +1 -15
- package/src/tool/exifCleaner/i18n/it.ts +1 -15
- package/src/tool/exifCleaner/i18n/ja.ts +1 -15
- package/src/tool/exifCleaner/i18n/ko.ts +1 -15
- package/src/tool/exifCleaner/i18n/nl.ts +1 -15
- package/src/tool/exifCleaner/i18n/pl.ts +1 -15
- package/src/tool/exifCleaner/i18n/pt.ts +1 -15
- package/src/tool/exifCleaner/i18n/ru.ts +1 -15
- package/src/tool/exifCleaner/i18n/sv.ts +1 -15
- package/src/tool/exifCleaner/i18n/tr.ts +1 -15
- package/src/tool/exifCleaner/i18n/zh.ts +1 -15
- package/src/tool/exifCleaner/seo.astro +2 -5
- package/src/tool/imageCompressor/bibliography.ts +12 -0
- package/src/tool/imageCompressor/entry.ts +2 -0
- package/src/tool/imageCompressor/i18n/de.ts +1 -15
- package/src/tool/imageCompressor/i18n/en.ts +1 -15
- package/src/tool/imageCompressor/i18n/es.ts +1 -13
- package/src/tool/imageCompressor/i18n/fr.ts +1 -13
- package/src/tool/imageCompressor/i18n/id.ts +1 -15
- package/src/tool/imageCompressor/i18n/it.ts +1 -15
- package/src/tool/imageCompressor/i18n/ja.ts +1 -15
- package/src/tool/imageCompressor/i18n/ko.ts +1 -15
- package/src/tool/imageCompressor/i18n/nl.ts +1 -15
- package/src/tool/imageCompressor/i18n/pl.ts +1 -15
- package/src/tool/imageCompressor/i18n/pt.ts +1 -15
- package/src/tool/imageCompressor/i18n/ru.ts +1 -15
- package/src/tool/imageCompressor/i18n/sv.ts +1 -15
- package/src/tool/imageCompressor/i18n/tr.ts +1 -15
- package/src/tool/imageCompressor/i18n/zh.ts +1 -15
- package/src/tool/imageCompressor/online-image-compressor-reduce-file-size-no-quality-loss.css +71 -64
- package/src/tool/imageCompressor/seo.astro +1 -1
- package/src/tool/printQualityCalculator/bibliography.ts +12 -0
- package/src/tool/printQualityCalculator/entry.ts +2 -0
- package/src/tool/printQualityCalculator/i18n/de.ts +1 -15
- package/src/tool/printQualityCalculator/i18n/en.ts +1 -15
- package/src/tool/printQualityCalculator/i18n/es.ts +1 -13
- package/src/tool/printQualityCalculator/i18n/fr.ts +1 -13
- package/src/tool/printQualityCalculator/i18n/id.ts +1 -15
- package/src/tool/printQualityCalculator/i18n/it.ts +1 -15
- package/src/tool/printQualityCalculator/i18n/ja.ts +1 -15
- package/src/tool/printQualityCalculator/i18n/ko.ts +1 -15
- package/src/tool/printQualityCalculator/i18n/nl.ts +1 -15
- package/src/tool/printQualityCalculator/i18n/pl.ts +1 -15
- package/src/tool/printQualityCalculator/i18n/pt.ts +1 -15
- package/src/tool/printQualityCalculator/i18n/ru.ts +1 -15
- package/src/tool/printQualityCalculator/i18n/sv.ts +1 -15
- package/src/tool/printQualityCalculator/i18n/tr.ts +1 -15
- package/src/tool/printQualityCalculator/i18n/zh.ts +1 -15
- package/src/tool/printQualityCalculator/print-quality-calculator-pixels-to-cm-dpi.css +89 -81
- package/src/tool/printQualityCalculator/seo.astro +2 -5
- package/src/tool/privacyBlur/bibliography.ts +8 -0
- package/src/tool/privacyBlur/entry.ts +2 -0
- package/src/tool/privacyBlur/i18n/de.ts +1 -11
- package/src/tool/privacyBlur/i18n/en.ts +1 -11
- package/src/tool/privacyBlur/i18n/es.ts +1 -9
- package/src/tool/privacyBlur/i18n/fr.ts +1 -9
- package/src/tool/privacyBlur/i18n/id.ts +1 -11
- package/src/tool/privacyBlur/i18n/it.ts +1 -11
- package/src/tool/privacyBlur/i18n/ja.ts +1 -11
- package/src/tool/privacyBlur/i18n/ko.ts +1 -11
- package/src/tool/privacyBlur/i18n/nl.ts +1 -11
- package/src/tool/privacyBlur/i18n/pl.ts +1 -11
- package/src/tool/privacyBlur/i18n/pt.ts +1 -11
- package/src/tool/privacyBlur/i18n/ru.ts +1 -11
- package/src/tool/privacyBlur/i18n/sv.ts +1 -11
- package/src/tool/privacyBlur/i18n/tr.ts +1 -11
- package/src/tool/privacyBlur/i18n/zh.ts +1 -11
- package/src/tool/privacyBlur/online-privacy-editor-pixelate-blur-faces-photos.css +36 -36
- package/src/tool/privacyBlur/seo.astro +1 -1
- package/src/tool/subtitleSync/bibliography.ts +12 -0
- package/src/tool/subtitleSync/entry.ts +2 -0
- package/src/tool/subtitleSync/i18n/de.ts +1 -13
- package/src/tool/subtitleSync/i18n/en.ts +1 -13
- package/src/tool/subtitleSync/i18n/es.ts +1 -13
- package/src/tool/subtitleSync/i18n/fr.ts +1 -13
- package/src/tool/subtitleSync/i18n/id.ts +1 -13
- package/src/tool/subtitleSync/i18n/it.ts +1 -13
- package/src/tool/subtitleSync/i18n/ja.ts +1 -13
- package/src/tool/subtitleSync/i18n/ko.ts +1 -13
- package/src/tool/subtitleSync/i18n/nl.ts +1 -13
- package/src/tool/subtitleSync/i18n/pl.ts +1 -13
- package/src/tool/subtitleSync/i18n/pt.ts +1 -13
- package/src/tool/subtitleSync/i18n/ru.ts +1 -13
- package/src/tool/subtitleSync/i18n/sv.ts +1 -13
- package/src/tool/subtitleSync/i18n/tr.ts +1 -13
- package/src/tool/subtitleSync/i18n/zh.ts +1 -13
- package/src/tool/subtitleSync/seo.astro +1 -1
- package/src/tool/subtitleSync/synchronize-srt-subtitles-online-adjust-timing-free.css +43 -43
- package/src/tool/timelapseCalculator/bibliography.ts +20 -0
- package/src/tool/timelapseCalculator/entry.ts +2 -0
- package/src/tool/timelapseCalculator/i18n/de.ts +1 -21
- package/src/tool/timelapseCalculator/i18n/en.ts +1 -21
- package/src/tool/timelapseCalculator/i18n/es.ts +1 -21
- package/src/tool/timelapseCalculator/i18n/fr.ts +1 -21
- package/src/tool/timelapseCalculator/i18n/id.ts +1 -21
- package/src/tool/timelapseCalculator/i18n/it.ts +1 -21
- package/src/tool/timelapseCalculator/i18n/ja.ts +1 -21
- package/src/tool/timelapseCalculator/i18n/ko.ts +1 -21
- package/src/tool/timelapseCalculator/i18n/nl.ts +1 -21
- package/src/tool/timelapseCalculator/i18n/pl.ts +1 -21
- package/src/tool/timelapseCalculator/i18n/pt.ts +1 -21
- package/src/tool/timelapseCalculator/i18n/ru.ts +1 -21
- package/src/tool/timelapseCalculator/i18n/sv.ts +1 -21
- package/src/tool/timelapseCalculator/i18n/tr.ts +1 -21
- package/src/tool/timelapseCalculator/i18n/zh.ts +1 -21
- package/src/tool/timelapseCalculator/seo.astro +2 -5
- package/src/tool/timelapseCalculator/timelapse-hyperlapse-calculator-perfect-intervals.css +44 -42
- package/src/tool/tvDistance/bibliography.ts +12 -0
- package/src/tool/tvDistance/entry.ts +2 -0
- package/src/tool/tvDistance/i18n/de.ts +1 -13
- package/src/tool/tvDistance/i18n/en.ts +1 -13
- package/src/tool/tvDistance/i18n/es.ts +1 -13
- package/src/tool/tvDistance/i18n/fr.ts +1 -13
- package/src/tool/tvDistance/i18n/id.ts +1 -13
- package/src/tool/tvDistance/i18n/it.ts +1 -13
- package/src/tool/tvDistance/i18n/ja.ts +1 -13
- package/src/tool/tvDistance/i18n/ko.ts +1 -13
- package/src/tool/tvDistance/i18n/nl.ts +1 -13
- package/src/tool/tvDistance/i18n/pl.ts +1 -13
- package/src/tool/tvDistance/i18n/pt.ts +1 -13
- package/src/tool/tvDistance/i18n/ru.ts +1 -13
- package/src/tool/tvDistance/i18n/sv.ts +1 -13
- package/src/tool/tvDistance/i18n/tr.ts +1 -13
- package/src/tool/tvDistance/i18n/zh.ts +1 -13
- package/src/tool/tvDistance/seo.astro +1 -1
- package/src/tool/tvDistance/tv-viewing-distance-calculator-thx-4k-optimal-screen.css +56 -56
- package/src/tool/videoFrameExtractor/bibliography.ts +8 -0
- package/src/tool/videoFrameExtractor/entry.ts +2 -0
- package/src/tool/videoFrameExtractor/i18n/de.ts +1 -9
- package/src/tool/videoFrameExtractor/i18n/en.ts +1 -9
- package/src/tool/videoFrameExtractor/i18n/es.ts +1 -9
- package/src/tool/videoFrameExtractor/i18n/fr.ts +1 -8
- package/src/tool/videoFrameExtractor/i18n/id.ts +1 -9
- package/src/tool/videoFrameExtractor/i18n/it.ts +1 -8
- package/src/tool/videoFrameExtractor/i18n/ja.ts +1 -9
- package/src/tool/videoFrameExtractor/i18n/ko.ts +1 -9
- package/src/tool/videoFrameExtractor/i18n/nl.ts +1 -9
- package/src/tool/videoFrameExtractor/i18n/pl.ts +1 -9
- package/src/tool/videoFrameExtractor/i18n/pt.ts +1 -9
- package/src/tool/videoFrameExtractor/i18n/ru.ts +1 -9
- package/src/tool/videoFrameExtractor/i18n/sv.ts +1 -9
- package/src/tool/videoFrameExtractor/i18n/tr.ts +1 -9
- package/src/tool/videoFrameExtractor/i18n/zh.ts +1 -9
- package/src/tool/videoFrameExtractor/online-video-frame-extractor-capture-hd-stills.css +55 -55
- package/src/tool/videoFrameExtractor/seo.astro +1 -1
- package/src/tools.ts +2 -0
- package/src/types.ts +0 -2
- package/src/tool/chromaticLens/style.css +0 -308
- package/src/tool/collageMaker/style.css +0 -386
- package/src/tool/exifCleaner/style.css +0 -289
- package/src/tool/imageCompressor/style.css +0 -503
- package/src/tool/printQualityCalculator/style.css +0 -491
- package/src/tool/privacyBlur/style.css +0 -332
- package/src/tool/subtitleSync/style.css +0 -325
- package/src/tool/timelapseCalculator/style.css +0 -285
- package/src/tool/tvDistance/style.css +0 -435
- package/src/tool/videoFrameExtractor/style.css +0 -426
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography';
|
|
2
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
3
|
+
import type { DepthOfFieldUI, DepthOfFieldLocaleContent } from '../index';
|
|
4
|
+
|
|
5
|
+
const slug = 'alan-derinligi-hesaplama';
|
|
6
|
+
const title = 'Alan Derinliği Hesaplama: Tüm Kameralar İçin Gerçek Zamanlı DoF';
|
|
7
|
+
const description = 'Alan derinliğini, hiperfokal mesafeyi ve odak sınırlarını gerçek zamanlı hesaplayın. 1/3 durak diyafram hassasiyetiyle tüm sensörleri destekler.';
|
|
8
|
+
|
|
9
|
+
const ui: DepthOfFieldUI = {
|
|
10
|
+
title: 'Alan Derinliği Hesaplama',
|
|
11
|
+
paramsTitle: 'Parametreler',
|
|
12
|
+
sensorLabel: 'Kamera Sensörü',
|
|
13
|
+
moreLabel: 'Daha fazla sensör…',
|
|
14
|
+
apertureLabel: 'Diyafram',
|
|
15
|
+
focalLabel: 'Odak Uzaklığı',
|
|
16
|
+
distanceLabel: 'Obje Mesafesi',
|
|
17
|
+
metersLabel: 'm',
|
|
18
|
+
feetLabel: 'ft',
|
|
19
|
+
resultsTitle: 'Sonuçlar',
|
|
20
|
+
totalDofLabel: 'Toplam Alan Derinliği',
|
|
21
|
+
infiniteLabel: 'Sonsuz',
|
|
22
|
+
nearLimitLabel: 'Yakın Sınır',
|
|
23
|
+
farLimitLabel: 'Uzak Sınır',
|
|
24
|
+
hyperfocalLabel: 'Hiperfokal',
|
|
25
|
+
cocLabel: 'Bulanıklık Halkası',
|
|
26
|
+
cocUnit: 'mm',
|
|
27
|
+
showDetailsLabel: 'Teknik detayları göster',
|
|
28
|
+
hideDetailsLabel: 'Teknik detayları gizle',
|
|
29
|
+
errorBelowFocal: 'Obje mesafesi odak uzaklığından büyük olmalıdır.',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const faq: DepthOfFieldLocaleContent['faq'] = [
|
|
33
|
+
{
|
|
34
|
+
question: 'Alan derinliği nedir?',
|
|
35
|
+
answer: 'Alan derinliği (DoF), bir sahnedeki kabul edilebilir düzeyde net görünen mesafe aralığıdır. Diyafram, odak uzaklığı, obje mesafesi ve sensör boyutu tarafından belirlenir.',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
question: 'Hiperfokal mesafe nedir?',
|
|
39
|
+
answer: 'Hiperfokal mesafe, sonsuzdaki nesnelerin hala kabul edilebilir düzeyde net olduğu en yakın odaklama mesafesidir. Bu mesafeye odaklanmak alan derinliğini maksimize eder.',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
question: 'Daha geniş diyafram (küçük f-değeri) neden alan derinliğini azaltır?',
|
|
43
|
+
answer: 'Geniş diyafram, lensin daha büyük bir alanından ışık toplar, bu da odak dışı noktalar için bulanıklık halkasını büyüterek net alan derinliğini daraltır.',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
question: 'Sensör boyutu alan derinliğini nasıl etkiler?',
|
|
47
|
+
answer: 'Büyük sensörler daha yüksek bulanıklık halkası eşiği kullanır. Ancak eşdeğer bakış açılarında, büyük sensörler daha uzun odak uzaklığı gerektirdiği için genellikle daha sığ alan derinliği üretir.',
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const howTo: DepthOfFieldLocaleContent['howTo'] = [
|
|
52
|
+
{
|
|
53
|
+
name: 'Kamera sensörünüzü seçin',
|
|
54
|
+
text: 'Kamera gövdenize uygun olan sensör formatını seçin. Bu, hesaplamalarda kullanılacak bulanıklık halkası (CoC) değerini belirler.',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'Diyafram ve odak uzaklığını ayarlayın',
|
|
58
|
+
text: 'Diyaframı 1/3 durak adımlarla seçin. Odak uzaklığı sürgüsü, geniş açıda daha hassas ayar yapabilmeniz için logaritmik ölçek kullanır.',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'Obje mesafesini belirleyin',
|
|
62
|
+
text: 'Kamera ile ana objeniz arasındaki mesafeyi ayarlayın. İhtiyacınıza göre metre ve fit birimleri arasında geçiş yapın.',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'Sonuçları okuyun',
|
|
66
|
+
text: 'Odak Çubuğu, objenizin etrafındaki net bölgeyi görselleştirir. Yakın ve uzak sınırlar kabul edilebilir odak sınırlarını gösterir.',
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
const seo: DepthOfFieldLocaleContent['seo'] = [
|
|
71
|
+
{ type: 'title', text: 'Fotoğraf ve Sinemada Alan Derinliğini Anlamak', level: 2 },
|
|
72
|
+
{ type: 'paragraph', html: 'Alan derinliği, fotoğrafçılar ve sinemacılar için en güçlü yaratıcı araçlardan biridir. <strong>Sığ alan derinliği</strong> konuyu arka plandan ayırırken, <strong>geniş alan derinliği</strong> manzarayı net tutar.' },
|
|
73
|
+
|
|
74
|
+
{ type: 'title', text: 'Alan Derinliğini Kontrol Eden Üç Değişken', level: 3 },
|
|
75
|
+
{ type: 'table', headers: ['Değişken', 'Artış →', 'DoF Üzerindeki Etkisi'], rows: [
|
|
76
|
+
['Diyafram', 'f/1.4 → f/16', 'Daha geniş diyafram = daha sığ DoF'],
|
|
77
|
+
['Odak Uzaklığı', '24mm → 200mm', 'Daha uzun odak = aynı mesafede daha sığ DoF'],
|
|
78
|
+
['Obje Mesafesi', '1m → 10m', 'Daha uzak obje = daha geniş DoF'],
|
|
79
|
+
]},
|
|
80
|
+
|
|
81
|
+
{ type: 'title', text: 'Hiperfokal Mesafe: Maksimum Netlik', level: 3 },
|
|
82
|
+
{ type: 'paragraph', html: '<strong>Hiperfokal mesafeye</strong> odaklandığınızda, bu mesafenin yarısından sonsuza kadar her şey net görünür. Manzara fotoğrafçıları bu tekniği sıkça kullanır.' },
|
|
83
|
+
{ type: 'tip', title: 'Pratik ipucu', html: 'Sokak fotoğrafçılığı için odağınızı hiperfokal mesafeye ayarlayın. APS-C sensörde 35mm lens ve f/8 ile hiperfokal yaklaşık <strong>4 metredir</strong>: 2 metreden sonsuza her şey net olacaktır.' },
|
|
84
|
+
|
|
85
|
+
{ type: 'title', text: 'Sensör Boyutu ve Bulanıklık Halkası', level: 3 },
|
|
86
|
+
{ type: 'paragraph', html: '<strong>Bulanıklık halkası (CoC)</strong>, kabul edilebilir netliğin sınırıdır. Full Frame sensörde CoC 0.030mm iken akıllı telefonda ~0.006mm\'dir. Daha küçük CoC, daha katı netlik kriteri demektir.' },
|
|
87
|
+
{ type: 'stats', columns: 3, items: [
|
|
88
|
+
{ label: 'Full Frame', value: '0.030 mm', icon: 'mdi:camera' },
|
|
89
|
+
{ label: 'APS-C', value: '0.019 mm', icon: 'mdi:camera-outline' },
|
|
90
|
+
{ label: 'Akıllı Telefon', value: '0.006 mm', icon: 'mdi:cellphone' },
|
|
91
|
+
]},
|
|
92
|
+
|
|
93
|
+
{ type: 'title', text: 'Sinemada DoF: Odak Uzaklığı vs Sensör', level: 3 },
|
|
94
|
+
{ type: 'paragraph', html: 'Super 35 formatında çekim yapan sinemacılar, "sinematik görünüm" oluşturmak için genellikle perspektifi sıkıştıran uzun odak uzaklıklarını tercih ederler.' },
|
|
95
|
+
{ type: 'diagnostic', variant: 'success', title: 'Odak Dağılım Kuralı', icon: 'mdi:lightbulb-outline', badge: 'Profil Teknik', html: '3 metredeki bir obje için 50mm ve f/2.8 ile: Net alan objenin arkasında, önüne göre her zaman daha fazladır; oran yaklaşık <strong>2:1</strong>\'dir.' },
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
99
|
+
'@context': 'https://schema.org',
|
|
100
|
+
'@type': 'FAQPage',
|
|
101
|
+
mainEntity: faq.map((item) => ({
|
|
102
|
+
'@type': 'Question',
|
|
103
|
+
name: item.question,
|
|
104
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
105
|
+
})),
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const howToSchema: WithContext<HowTo> = {
|
|
109
|
+
'@context': 'https://schema.org',
|
|
110
|
+
'@type': 'HowTo',
|
|
111
|
+
name: title,
|
|
112
|
+
description,
|
|
113
|
+
step: howTo.map((step) => ({
|
|
114
|
+
'@type': 'HowToStep',
|
|
115
|
+
name: step.name,
|
|
116
|
+
text: step.text,
|
|
117
|
+
})),
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
121
|
+
'@context': 'https://schema.org',
|
|
122
|
+
'@type': 'SoftwareApplication',
|
|
123
|
+
name: title,
|
|
124
|
+
description,
|
|
125
|
+
applicationCategory: 'UtilitiesApplication',
|
|
126
|
+
operatingSystem: 'Web',
|
|
127
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
128
|
+
inLanguage: 'tr',
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const content: DepthOfFieldLocaleContent = {
|
|
132
|
+
slug,
|
|
133
|
+
title,
|
|
134
|
+
description,
|
|
135
|
+
ui,
|
|
136
|
+
seo,
|
|
137
|
+
faq,
|
|
138
|
+
bibliography,
|
|
139
|
+
howTo,
|
|
140
|
+
schemas: [faqSchema as any, howToSchema as any, appSchema],
|
|
141
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography';
|
|
2
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
3
|
+
import type { DepthOfFieldUI, DepthOfFieldLocaleContent } from '../index';
|
|
4
|
+
|
|
5
|
+
const slug = 'depth-of-field-calculator';
|
|
6
|
+
const title = '景深计算器:全相机实时景深计算';
|
|
7
|
+
const description = '实时计算景深、超焦距和焦点限制。支持所有传感器尺寸,具备 1/3 档光圈精度。';
|
|
8
|
+
|
|
9
|
+
const ui: DepthOfFieldUI = {
|
|
10
|
+
title: '景深计算器',
|
|
11
|
+
paramsTitle: '设定参数',
|
|
12
|
+
sensorLabel: '相机传感器',
|
|
13
|
+
moreLabel: '更多传感器…',
|
|
14
|
+
apertureLabel: '光圈值',
|
|
15
|
+
focalLabel: '焦距',
|
|
16
|
+
distanceLabel: '拍摄距离',
|
|
17
|
+
metersLabel: 'm',
|
|
18
|
+
feetLabel: 'ft',
|
|
19
|
+
resultsTitle: '计算结果',
|
|
20
|
+
totalDofLabel: '总景深',
|
|
21
|
+
infiniteLabel: '无穷远',
|
|
22
|
+
nearLimitLabel: '近景界限',
|
|
23
|
+
farLimitLabel: '远景界限',
|
|
24
|
+
hyperfocalLabel: '超焦距',
|
|
25
|
+
cocLabel: '弥散圆 (CoC)',
|
|
26
|
+
cocUnit: 'mm',
|
|
27
|
+
showDetailsLabel: '显示技术细节',
|
|
28
|
+
hideDetailsLabel: '隐藏技术细节',
|
|
29
|
+
errorBelowFocal: '拍摄距离必须大于焦距。',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const faq: DepthOfFieldLocaleContent['faq'] = [
|
|
33
|
+
{
|
|
34
|
+
question: '什么是景深?',
|
|
35
|
+
answer: '景深 (DoF) 是指场景中在最终图像里显得清晰的范围。它由光圈、焦距、拍摄距离和传感器尺寸决定。',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
question: '什么是超焦距?',
|
|
39
|
+
answer: '超焦距是指在对无穷远处的物体依然能保持清晰的情况下,最近的对焦距离。对焦在此距离可以最大化景深。',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
question: '为什么较大的光圈(较小的 f 值)会减小景深?',
|
|
43
|
+
answer: '较大的光圈通过镜头的更大区域收集光线,这增加了焦点外点的弥散圆大小,从而收窄了清晰范围。',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
question: '传感器尺寸如何影响景深?',
|
|
47
|
+
answer: '较大的传感器使用更大的弥散圆阈值。但在相同视角下,大传感器通常产生更浅的景深,因为它们需要更长的焦距。',
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const howTo: DepthOfFieldLocaleContent['howTo'] = [
|
|
52
|
+
{
|
|
53
|
+
name: '选择相机传感器',
|
|
54
|
+
text: '选择与您的相机机身匹配的传感器格式。这将设定计算中使用的弥散圆 (CoC) 值。',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: '设定光圈和焦距',
|
|
58
|
+
text: '以 1/3 档为增量选择光圈。焦距滑块采用对数刻度,便于在广角端进行精细调整。',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: '设定拍摄距离',
|
|
62
|
+
text: '设置相机与主主体之间的距离。根据需要切换米和英尺单位。',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: '查看结果',
|
|
66
|
+
text: '对焦条可视化主体周围的清晰区域。近景和远景界限显示了精确的焦点边界。',
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
const seo: DepthOfFieldLocaleContent['seo'] = [
|
|
71
|
+
{ type: 'title', text: '深入理解摄影与电影中的景深', level: 2 },
|
|
72
|
+
{ type: 'paragraph', html: '景深是摄影师和摄像师最强大的创意工具之一。<strong>浅景深</strong>可以将主体从干扰背景中分离,而<strong>深景深</strong>则能让整个风景从前景到地平线保持清晰。' },
|
|
73
|
+
|
|
74
|
+
{ type: 'title', text: '控制景深的三大变量', level: 3 },
|
|
75
|
+
{ type: 'table', headers: ['变量', '变化趋势 →', '对景深的影响'], rows: [
|
|
76
|
+
['光圈', 'f/1.4 → f/16', '光圈越大 = 景深越浅'],
|
|
77
|
+
['焦距', '24mm → 200mm', '焦距越长 = 景深越浅(同一距离下)'],
|
|
78
|
+
['拍摄距离', '1m → 10m', '主体越远 = 景深越深'],
|
|
79
|
+
]},
|
|
80
|
+
|
|
81
|
+
{ type: 'title', text: '超焦距:实现最大清晰度', level: 3 },
|
|
82
|
+
{ type: 'paragraph', html: '当您对焦在<strong>超焦距</strong>时,从该距离的一半到无穷远的一切都会显得清晰。风景摄影师常用此技术确保前景和远山同时清晰。' },
|
|
83
|
+
{ type: 'tip', title: '实践建议', html: '对于街头摄影,将焦点设为超焦距。在 APS-C 上使用 35mm 镜头并设置 f/8 时,超焦距约为 <strong>4 米</strong>:从 2 米到无穷远的一切都将保持清晰。' },
|
|
84
|
+
|
|
85
|
+
{ type: 'title', text: '传感器尺寸与弥散圆', level: 3 },
|
|
86
|
+
{ type: 'paragraph', html: '<strong>弥散圆 (CoC)</strong> 是定义“清晰度”的阈值。全画幅传感器的 CoC 为 0.030mm,而智能手机约为 0.006mm。CoC 值越小意味着清晰度要求越严格。' },
|
|
87
|
+
{ type: 'stats', columns: 3, items: [
|
|
88
|
+
{ label: '全画幅', value: '0.030 mm', icon: 'mdi:camera' },
|
|
89
|
+
{ label: 'APS-C', value: '0.019 mm', icon: 'mdi:camera-outline' },
|
|
90
|
+
{ label: '智能手机', value: '0.006 mm', icon: 'mdi:cellphone' },
|
|
91
|
+
]},
|
|
92
|
+
|
|
93
|
+
{ type: 'title', text: '电影中的景深:焦距 vs. 传感器', level: 3 },
|
|
94
|
+
{ type: 'paragraph', html: '在 Super 35(接近 APS-C)上拍摄的电影人经常使用较长焦距来压缩透视,这也会收窄景深,营造出“电影感”。大光圈 85mm 是经典人像选择。' },
|
|
95
|
+
{ type: 'diagnostic', variant: 'success', title: '焦点分布规律', icon: 'mdi:lightbulb-outline', badge: '专家技法', html: '对于 3 米处的主体,使用 50mm f/2.8 全画幅拍摄:主体后的清晰区域总是比主体前大,比例约为 <strong>2:1</strong>。' },
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
99
|
+
'@context': 'https://schema.org',
|
|
100
|
+
'@type': 'FAQPage',
|
|
101
|
+
mainEntity: faq.map((item) => ({
|
|
102
|
+
'@type': 'Question',
|
|
103
|
+
name: item.question,
|
|
104
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
105
|
+
})),
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const howToSchema: WithContext<HowTo> = {
|
|
109
|
+
'@context': 'https://schema.org',
|
|
110
|
+
'@type': 'HowTo',
|
|
111
|
+
name: title,
|
|
112
|
+
description,
|
|
113
|
+
step: howTo.map((step) => ({
|
|
114
|
+
'@type': 'HowToStep',
|
|
115
|
+
name: step.name,
|
|
116
|
+
text: step.text,
|
|
117
|
+
})),
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
121
|
+
'@context': 'https://schema.org',
|
|
122
|
+
'@type': 'SoftwareApplication',
|
|
123
|
+
name: title,
|
|
124
|
+
description,
|
|
125
|
+
applicationCategory: 'UtilitiesApplication',
|
|
126
|
+
operatingSystem: 'Web',
|
|
127
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
128
|
+
inLanguage: 'zh',
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const content: DepthOfFieldLocaleContent = {
|
|
132
|
+
slug,
|
|
133
|
+
title,
|
|
134
|
+
description,
|
|
135
|
+
ui,
|
|
136
|
+
seo,
|
|
137
|
+
faq,
|
|
138
|
+
bibliography,
|
|
139
|
+
howTo,
|
|
140
|
+
schemas: [faqSchema as any, howToSchema as any, appSchema],
|
|
141
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ToolDefinition, AudiovisualToolEntry } from '../../types';
|
|
2
|
+
import { depthOfFieldCalculator } from './entry';
|
|
3
|
+
export * from './entry';
|
|
4
|
+
|
|
5
|
+
export const DEPTH_OF_FIELD_CALCULATOR_TOOL: ToolDefinition = {
|
|
6
|
+
entry: depthOfFieldCalculator as unknown as AudiovisualToolEntry,
|
|
7
|
+
Component: () => import('./component.astro'),
|
|
8
|
+
SEOComponent: () => import('./seo.astro'),
|
|
9
|
+
BibliographyComponent: () => import('./bibliography.astro'),
|
|
10
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
|
|
2
|
+
export interface SensorPreset {
|
|
3
|
+
key: string;
|
|
4
|
+
label: string;
|
|
5
|
+
shortLabel: string;
|
|
6
|
+
coc: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const SENSOR_PRESETS: SensorPreset[] = [
|
|
10
|
+
{ key: 'ff', label: 'Full Frame (35mm)', shortLabel: 'FF', coc: 0.030 },
|
|
11
|
+
{ key: 'apsc-canon', label: 'APS-C Canon', shortLabel: 'APS-C', coc: 0.019 },
|
|
12
|
+
{ key: 'apsc', label: 'APS-C Nikon / Sony', shortLabel: 'APS-N', coc: 0.020 },
|
|
13
|
+
{ key: 'mft', label: 'Micro Four Thirds', shortLabel: 'MFT', coc: 0.015 },
|
|
14
|
+
{ key: '1inch', label: '1" Sensor', shortLabel: '1"', coc: 0.011 },
|
|
15
|
+
{ key: 'phone', label: 'Smartphone', shortLabel: 'Phone', coc: 0.006 },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
export const QUICK_SENSOR_KEYS = ['ff', 'apsc-canon', 'mft', 'phone'];
|
|
19
|
+
|
|
20
|
+
export const F_STOPS: number[] = [
|
|
21
|
+
1.0, 1.1, 1.2, 1.4, 1.6, 1.8,
|
|
22
|
+
2.0, 2.2, 2.5, 2.8, 3.2, 3.5,
|
|
23
|
+
4.0, 4.5, 5.0, 5.6, 6.3, 7.1,
|
|
24
|
+
8.0, 9.0, 10, 11, 13, 14, 16, 18, 20, 22,
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
export interface DoFResult {
|
|
28
|
+
hyperfocal: number;
|
|
29
|
+
nearLimit: number;
|
|
30
|
+
farLimit: number;
|
|
31
|
+
totalDoF: number;
|
|
32
|
+
isInfinite: boolean;
|
|
33
|
+
hasError: boolean;
|
|
34
|
+
errorCode: 'BELOW_FOCAL' | null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function calculateDoF(
|
|
38
|
+
subjectMetres: number,
|
|
39
|
+
focalMm: number,
|
|
40
|
+
aperture: number,
|
|
41
|
+
cocMm: number,
|
|
42
|
+
): DoFResult {
|
|
43
|
+
const fM = focalMm / 1000;
|
|
44
|
+
const cM = cocMm / 1000;
|
|
45
|
+
|
|
46
|
+
if (subjectMetres <= fM) {
|
|
47
|
+
return { hyperfocal: 0, nearLimit: 0, farLimit: 0, totalDoF: 0, isInfinite: false, hasError: true, errorCode: 'BELOW_FOCAL' };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const H = (fM * fM) / (aperture * cM) + fM;
|
|
51
|
+
const nearLimit = (subjectMetres * (H - fM)) / (H + subjectMetres - 2 * fM);
|
|
52
|
+
const isInfinite = subjectMetres >= H;
|
|
53
|
+
const farLimit = isInfinite ? Infinity : (subjectMetres * (H - fM)) / (H - subjectMetres);
|
|
54
|
+
const totalDoF = isInfinite ? Infinity : farLimit - nearLimit;
|
|
55
|
+
|
|
56
|
+
return { hyperfocal: H, nearLimit, farLimit, totalDoF, isInfinite, hasError: false, errorCode: null };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const LOG_FOCAL_MIN = Math.log(8);
|
|
60
|
+
const LOG_FOCAL_MAX = Math.log(800);
|
|
61
|
+
const LOG_SUBJECT_MIN = Math.log(0.5);
|
|
62
|
+
const LOG_SUBJECT_MAX = Math.log(200);
|
|
63
|
+
|
|
64
|
+
export function sliderToFocal(index: number, steps: number): number {
|
|
65
|
+
const t = index / (steps - 1);
|
|
66
|
+
return Math.round(Math.exp(LOG_FOCAL_MIN + t * (LOG_FOCAL_MAX - LOG_FOCAL_MIN)));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function focalToSlider(focal: number, steps: number): number {
|
|
70
|
+
const t = (Math.log(focal) - LOG_FOCAL_MIN) / (LOG_FOCAL_MAX - LOG_FOCAL_MIN);
|
|
71
|
+
return Math.round(t * (steps - 1));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function sliderToSubject(index: number, steps: number): number {
|
|
75
|
+
const t = index / (steps - 1);
|
|
76
|
+
return Math.exp(LOG_SUBJECT_MIN + t * (LOG_SUBJECT_MAX - LOG_SUBJECT_MIN));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function subjectToSlider(subject: number, steps: number): number {
|
|
80
|
+
const t = (Math.log(subject) - LOG_SUBJECT_MIN) / (LOG_SUBJECT_MAX - LOG_SUBJECT_MIN);
|
|
81
|
+
return Math.round(t * (steps - 1));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function formatDistance(metres: number, useFeet: boolean): string {
|
|
85
|
+
if (!isFinite(metres)) return '∞';
|
|
86
|
+
const value = useFeet ? metres * 3.28084 : metres;
|
|
87
|
+
const unit = useFeet ? 'ft' : 'm';
|
|
88
|
+
if (value >= 1000) return `${(value / 1000).toFixed(1)} km`;
|
|
89
|
+
if (value < 1) return `${(value * 100).toFixed(0)} cm`;
|
|
90
|
+
return value >= 10 ? `${value.toFixed(1)} ${unit}` : `${value.toFixed(2)} ${unit}`;
|
|
91
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { SEORenderer } from '@jjlmoya/utils-shared';
|
|
3
|
+
import { depthOfFieldCalculator } from './index';
|
|
4
|
+
import type { KnownLocale } from '../../types';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
locale?: KnownLocale;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { locale = 'en' } = Astro.props;
|
|
11
|
+
const content = await depthOfFieldCalculator.i18n[locale]?.();
|
|
12
|
+
if (!content) return null;
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
{content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { BibliographyEntry } from '../../types';
|
|
2
|
+
|
|
3
|
+
export const bibliography: BibliographyEntry[] = [
|
|
4
|
+
{
|
|
5
|
+
name: "Exchangeable Image File Format (EXIF) - Wikipedia",
|
|
6
|
+
url: "https://de.wikipedia.org/wiki/Exchangeable_Image_File_Format",
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
name: "W3C - Metadaten in Bildern",
|
|
10
|
+
url: "https://www.w3.org/community/image-metadata/",
|
|
11
|
+
},
|
|
12
|
+
];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
.ec-root {
|
|
2
2
|
--ec-bg: #fff;
|
|
3
3
|
--ec-bg-elevated: #f8fafc;
|
|
4
4
|
--ec-border: #e2e8f0;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
margin: 0 auto;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
.theme-dark .ec-root {
|
|
18
18
|
--ec-bg: #18181b;
|
|
19
19
|
--ec-bg-elevated: #27272a;
|
|
20
20
|
--ec-border: #3f3f46;
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
--ec-shadow: rgba(0, 0, 0, 0.3);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
.ec-card {
|
|
30
30
|
background: var(--ec-bg);
|
|
31
31
|
border: 1px solid var(--ec-border);
|
|
32
32
|
border-radius: 3rem;
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
overflow: hidden;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
.ec-drop {
|
|
40
40
|
padding: 4rem 2rem;
|
|
41
41
|
border: 3px dashed var(--ec-border);
|
|
42
42
|
border-radius: 2.5rem;
|
|
@@ -49,13 +49,13 @@
|
|
|
49
49
|
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
.ec-drop:hover,
|
|
53
|
+
.ec-drop-active {
|
|
54
54
|
border-color: var(--ec-accent);
|
|
55
55
|
background: var(--ec-accent-alpha-hover);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
.ec-drop-icon {
|
|
59
59
|
width: 6rem;
|
|
60
60
|
height: 6rem;
|
|
61
61
|
background: var(--ec-accent-alpha);
|
|
@@ -66,19 +66,19 @@
|
|
|
66
66
|
color: var(--ec-accent);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
.ec-drop-icon svg {
|
|
70
70
|
width: 3rem;
|
|
71
71
|
height: 3rem;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
.ec-title {
|
|
75
75
|
font-size: 2.5rem;
|
|
76
76
|
font-weight: 950;
|
|
77
77
|
color: var(--ec-text);
|
|
78
78
|
margin: 0;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
.ec-subtitle {
|
|
82
82
|
font-size: 1.15rem;
|
|
83
83
|
color: var(--ec-text-muted);
|
|
84
84
|
max-width: 500px;
|
|
@@ -86,14 +86,14 @@
|
|
|
86
86
|
font-weight: 700;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
.ec-badges {
|
|
90
90
|
display: flex;
|
|
91
91
|
gap: 1rem;
|
|
92
92
|
flex-wrap: wrap;
|
|
93
93
|
justify-content: center;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
.ec-badge {
|
|
97
97
|
padding: 0.6rem 1.25rem;
|
|
98
98
|
background: var(--ec-bg-elevated);
|
|
99
99
|
border-radius: 2rem;
|
|
@@ -105,13 +105,13 @@
|
|
|
105
105
|
gap: 0.5rem;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
.ec-badge svg {
|
|
109
109
|
width: 1rem;
|
|
110
110
|
height: 1rem;
|
|
111
111
|
flex-shrink: 0;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
.ec-processing {
|
|
115
115
|
padding: 5rem;
|
|
116
116
|
display: flex;
|
|
117
117
|
flex-direction: column;
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
gap: 1.5rem;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
.ec-spinner {
|
|
124
124
|
width: 4rem;
|
|
125
125
|
height: 4rem;
|
|
126
126
|
border: 4px solid var(--ec-accent-alpha);
|
|
@@ -129,45 +129,45 @@
|
|
|
129
129
|
animation: ec-spin 0.8s linear infinite;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
.ec-processing-text {
|
|
133
133
|
font-weight: 800;
|
|
134
134
|
color: var(--ec-text);
|
|
135
135
|
margin: 0;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
.ec-result {
|
|
139
139
|
padding: 2.5rem;
|
|
140
140
|
display: flex;
|
|
141
141
|
flex-direction: column;
|
|
142
142
|
animation: ec-slide-up 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
|
|
145
|
+
.ec-result-layout {
|
|
146
146
|
display: grid;
|
|
147
147
|
grid-template-columns: 1fr 1fr;
|
|
148
148
|
gap: 3rem;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
@media (max-width: 800px) {
|
|
152
|
-
|
|
152
|
+
.ec-result-layout {
|
|
153
153
|
grid-template-columns: 1fr;
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
|
|
157
|
+
.ec-preview-col {
|
|
158
158
|
display: flex;
|
|
159
159
|
flex-direction: column;
|
|
160
160
|
gap: 1.5rem;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
|
|
163
|
+
.ec-preview-img {
|
|
164
164
|
width: 100%;
|
|
165
165
|
border-radius: 1.5rem;
|
|
166
166
|
box-shadow: 0 20px 50px var(--ec-shadow);
|
|
167
167
|
display: block;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
|
|
170
|
+
.ec-metadata {
|
|
171
171
|
background: var(--ec-bg-elevated);
|
|
172
172
|
border: 1px solid var(--ec-border);
|
|
173
173
|
border-radius: 1.25rem;
|
|
@@ -178,7 +178,7 @@
|
|
|
178
178
|
justify-content: center;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
|
|
181
|
+
.ec-no-metadata {
|
|
182
182
|
display: flex;
|
|
183
183
|
align-items: center;
|
|
184
184
|
justify-content: center;
|
|
@@ -187,14 +187,14 @@
|
|
|
187
187
|
text-align: center;
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
|
|
190
|
+
.ec-metadata-title {
|
|
191
191
|
color: var(--ec-accent);
|
|
192
192
|
font-weight: 700;
|
|
193
193
|
margin-bottom: 1rem;
|
|
194
194
|
font-size: 0.9rem;
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
|
|
197
|
+
.ec-metadata-list {
|
|
198
198
|
list-style: none;
|
|
199
199
|
padding: 0;
|
|
200
200
|
margin: 0;
|
|
@@ -203,7 +203,7 @@
|
|
|
203
203
|
gap: 0.75rem;
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
|
|
206
|
+
.ec-metadata-list li {
|
|
207
207
|
display: flex;
|
|
208
208
|
justify-content: space-between;
|
|
209
209
|
gap: 1rem;
|
|
@@ -212,21 +212,21 @@
|
|
|
212
212
|
color: var(--ec-text);
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
-
|
|
215
|
+
.ec-metadata-list li span:first-child {
|
|
216
216
|
font-weight: 700;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
-
|
|
219
|
+
.ec-metadata-list li span:last-child {
|
|
220
220
|
color: var(--ec-text-muted);
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
|
|
223
|
+
.ec-actions-col {
|
|
224
224
|
display: flex;
|
|
225
225
|
flex-direction: column;
|
|
226
226
|
gap: 1.5rem;
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
|
|
229
|
+
.ec-btn {
|
|
230
230
|
padding: 1.25rem;
|
|
231
231
|
border-radius: 1.5rem;
|
|
232
232
|
font-weight: 950;
|
|
@@ -240,29 +240,29 @@
|
|
|
240
240
|
transition: all 0.2s;
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
|
|
243
|
+
.ec-btn svg {
|
|
244
244
|
width: 1.25rem;
|
|
245
245
|
height: 1.25rem;
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
|
|
248
|
+
.ec-btn-primary {
|
|
249
249
|
background: var(--ec-accent);
|
|
250
250
|
color: #fff;
|
|
251
251
|
box-shadow: 0 15px 35px -10px var(--ec-accent);
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
-
|
|
254
|
+
.ec-btn-primary:hover {
|
|
255
255
|
transform: translateY(-2px);
|
|
256
256
|
box-shadow: 0 20px 45px -10px var(--ec-accent);
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
-
|
|
259
|
+
.ec-btn-secondary {
|
|
260
260
|
background: var(--ec-bg-elevated);
|
|
261
261
|
border: 1px solid var(--ec-border);
|
|
262
262
|
color: var(--ec-text);
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
-
|
|
265
|
+
.ec-btn-secondary:hover {
|
|
266
266
|
border-color: var(--ec-accent);
|
|
267
267
|
color: var(--ec-accent);
|
|
268
268
|
}
|
|
@@ -286,4 +286,4 @@
|
|
|
286
286
|
opacity: 1;
|
|
287
287
|
transform: translateY(0);
|
|
288
288
|
}
|
|
289
|
-
}
|
|
289
|
+
}
|