SVGcode: تطبيق ويب تقدّمي (PWA) لتحويل الصور النقطية إلى رسومات متجه SVG

SVGcode هو تطبيق ويب تقدّمي يتيح لك تحويل الصور النقطية مثل JPG أو PNG أو GIF أو WebP أو AVIF وما إلى ذلك إلى رسومات متجهات بتنسيق SVG. وتستخدم واجهة برمجة التطبيقات File System Access API وواجهة برمجة التطبيقات Async Clipboard API وواجهة برمجة تطبيقات معالجة الملفات وتخصيص تراكب عناصر التحكم في النوافذ.

(إذا كنت تفضّل المشاهدة على القراءة، تتوفّر هذه المقالة أيضًا على شكل فيديو).

من الخط النقطي إلى المتجه

هل سبق لك إجراء تحجيم في صورة وكانت النتيجة متقطّعة وغير مُرضية؟ في حال حذف لذلك، من المحتمل أنك تعاملت مع تنسيق صورة نقطية مثل WebP أو PNG أو JPG.

تكبير الصورة النقطية يجعلها تبدو متقطّعة.

في التباين، الرسومات المتجهة هي صور يتم تحديدها بنقاط في نظام إحداثي. هذه يتم ربط النقاط بخطوط ومنحنيات لتكوين مضلّعات وأشكال أخرى. تحتوي رسومات المتجه الاستفادة من الرسومات النقطية في إمكانية تصغيرها أو تصغيرها إلى أي دقة بدون تقطيع.

زيادة حجم صورة متجه بدون فقدان الجودة.

إضافة SVGcode

لقد أنشأتُ تطبيق ويب تقدّمي (PWA) يُسمى SVGcode يمكنه مساعدتك في تحويل الصور النقطية إلى المتجهات. الائتمان الذي يستحق سداده: لم أخترع هذا. باستخدام SVGcode، أقف فقط على أداة سطر الأوامر التي تسمى Potrace بيتر سيلينغر لدي يتم تحويلها إلى استخدام تقنية Web Assembly، لذا يمكن استخدامها في تطبيق الويب.

لقطة شاشة لتطبيق SVGcode.
تطبيق SVGcode

استخدام SVGcode

أولاً، أود أن أوضح لك كيفية استخدام التطبيق. أبدأ بالصورة التشويقية لمؤتمر Chrome Dev Summit الذي نزّلته من قناة ChromiumDev على Twitter هذه صورة نقطية بتنسيق PNG السحب إلى تطبيق SVGcode. عندما أسقط الملف، يتتبع التطبيق لون الصورة حسب اللون، حتى تظهر نسخة متجهة من المدخلات. يمكنني الآن تكبير الصورة، وكما ترون، وتظل الحواف حادة. ولكن عند تكبير شعار Chrome، يمكنك أن ترى أن التتبع لم يكن مثالية، وخصوصًا الخطوط العريضة للشعار، والتي تبدو متقطعة بعض الشيء. يمكنني تحسين النتيجة من خلال قم بتخفيف نقع التتبع عن طريق منع نقاط تصل إلى خمس بكسلات على سبيل المثال.

تحويل صورة تم إفلاتها إلى تنسيق SVG

النشر بتنسيق SVGcode

من الخطوات المهمة للاتّجاه، وخاصةً بالنسبة إلى الصور الفوتوغرافية، إضافة خلفية للمدخل صورة لتقليل عدد الألوان. يسمح لي SVGcode بإجراء ذلك لكل قناة ألوان، والاطّلاع على الناتج عن SVG أثناء إجراء التغييرات. عندما أكون راضيًا عن النتيجة، يمكنني حفظ ملف SVG على القرص الثابت واستخدامها حيثما أريد.

إضافة الملصقات إلى صورة لتقليل عدد الألوان.

واجهات برمجة التطبيقات المستخدمة في رمز SVG

الآن وبعد أن تعرّفت على ميزات التطبيق، دعوني أعرض لك بعض واجهات برمجة التطبيقات التي تساعد في يحدث السحر.

تطبيق الويب التقدّمي

SVGcode هو تطبيق ويب تقدّمي قابل للتثبيت وبالتالي يكون مفعّلاً بالكامل بلا اتصال بالإنترنت. يعتمد التطبيق في صفحة نموذج Vanilla JS في Vite.js ويستخدم علامة تطبيق الويب التقدّمي Vite الإضافي، الذي ينشئ مشغّل خدمات تستخدم أداة Workbox.js ضمن الخيارات المتقدمة. تم تحديد مجموعة Workbox من المكتبات التي يمكنها أن تدعم عامل خدمة جاهز للإنتاج بالنسبة إلى تطبيقات الويب التقدّمية، هذا النمط قد لا يعمل بالضرورة مع كل التطبيقات، ولكن في حالة استخدام SVGcode، سيكون رائعًا.

تراكب عناصر التحكم في النوافذ

لزيادة مساحة الشاشة المتاحة، يستخدم SVGcode تخصيص العناصر المركّبة في النوافذ من خلال نقل القائمة الرئيسية إلى الأعلى إلى منطقة شريط العنوان. ستلاحظ أنّه تم تفعيل هذه الميزة في نهاية عملية التثبيت.

تثبيت SVGcode وتفعيل تخصيص Window Controls Overlay

File System Access API

لفتح ملفات صور الإدخال وحفظ ملفات SVG الناتجة، أستخدم File System Access API: هذا يسمح لي بالاحتفاظ بالرجوع إلى فتح الملفات والمتابعة من حيث توقفت، حتى بعد إعادة تحميل التطبيق. كلما ظهرت صورة يتم حفظه، يتم تحسينه عبر مكتبة svgo، الأمر الذي قد يستغرق لحظة، اعتمادًا على مدى تعقيد SVG. يجب استخدام إيماءة المستخدم لعرض مربّع حوار حفظ الملفات. من المهم لذا من المهم الحصول على مؤشر الملف قبل إجراء تحسين SVG (رسومات موجّهة يمكن تغيير حجمها)، لكي يعرف المستخدم لا يتم إيقاف إيماءة الرسومات الموجّهة التي يمكن تغيير حجمها (SVG) في الوقت الذي يصبح فيه ملف SVG المحسّن جاهزًا.

try {
  let svg = svgOutput.innerHTML;
  let handle = null;
  // To not consume the user gesture obtain the handle before preparing the
  // blob, which may take longer.
  if (supported) {
    handle = await showSaveFilePicker({
      types: [{description: 'SVG file', accept: {'image/svg+xml': ['.svg']}}],
    });
  }
  showToast(i18n.t('optimizingSVG'), Infinity);
  svg = await optimizeSVG(svg);
  showToast(i18n.t('savedSVG'));
  const blob = new Blob([svg], {type: 'image/svg+xml'});
  await fileSave(blob, {description: 'SVG file'}, handle);
} catch (err) {
  console.error(err.name, err.message);
  showToast(err.message);
}

السحب والإفلات

لفتح صورة مدخلات، يمكنني إما استخدام ميزة فتح الملف، أو، كما ذكرت أعلاه، سحب ملف الصورة وإفلاته في التطبيق. تعد ميزة فتح الملف واضحة جدًا، وأكثر مثير للاهتمام هو حالة السحب والإفلات. الأمر اللطيف في هذا الأمر هو أنه يمكنك وهي الحصول على مؤشر نظام الملفات من عنصر نقل البيانات من خلال getAsFileSystemHandle() . وكما ذكرنا سابقًا، يمكنني الاحتفاظ بهذا الاسم المعرِّف حتى يصبح جاهزًا بعد إعادة تحميل التطبيق.

document.addEventListener('drop', async (event) => {
  event.preventDefault();
  dropContainer.classList.remove('dropenter');
  const item = event.dataTransfer.items[0];
  if (item.kind === 'file') {
    inputImage.addEventListener(
      'load',
      () => {
        URL.revokeObjectURL(blobURL);
      },
      {once: true},
    );
    const handle = await item.getAsFileSystemHandle();
    if (handle.kind !== 'file') {
      return;
    }
    const file = await handle.getFile();
    const blobURL = URL.createObjectURL(file);
    inputImage.src = blobURL;
    await set(FILE_HANDLE, handle);
  }
});

للحصول على مزيد من التفاصيل، يمكنك الاطّلاع على المقالة حول File System Access API، بالإضافة إلى إذا كنت مهتمًا، يمكنك دراسة رمز مصدر SVGcode في src/js/filesystem.js

Async Clipboard API

يتم أيضًا دمج SVGcode بالكامل في حافظة نظام التشغيل عبر واجهة برمجة التطبيقات Async Clipboard API. يمكنك لصق الصور من مستكشف الملفات بنظام التشغيل في التطبيق إما بالنقر على زر لصق الصورة أو بالضغط على مفتاح الأوامر أو مفتاح Control زائد v في لوحة المفاتيح.

لصق صورة من مستكشف الملفات في رمز SVG.

أصبح بإمكان واجهة برمجة التطبيقات Async Clipboard API مؤخرًا التعامل مع صور SVG أيضًا، ما يتيح لك انسخ صورة SVG أيضًا والصقها في تطبيق آخر لإجراء مزيد من المعالجة.

نسخ صورة من تنسيق SVGcode إلى تنسيق SVGOMG
copyButton.addEventListener('click', async () => {
  let svg = svgOutput.innerHTML;
  showToast(i18n.t('optimizingSVG'), Infinity);
  svg = await optimizeSVG(svg);
  const textBlob = new Blob([svg], {type: 'text/plain'});
  const svgBlob = new Blob([svg], {type: 'image/svg+xml'});
  navigator.clipboard.write([
    new ClipboardItem({
      [svgBlob.type]: svgBlob,
      [textBlob.type]: textBlob,
    }),
  ]);
  showToast(i18n.t('copiedSVG'));
});

لمعرفة المزيد من المعلومات، يُرجى الاطّلاع على مقالة الحافظة غير المتزامنة أو الاطّلاع على الملف. src/js/clipboard.js

معالجة الملفات

من أكثر الميزات التي أفضلها رمز SVGcode هو مدى تكامله مع نظام التشغيل. على سبيل المثال، تثبيت تطبيق الويب التقدّمي (PWA)، يمكن أن يصبح معالج ملفات أو حتى معالج الملفات التلقائي لملفات الصور. هذا النمط يعني أنه عندما أكون في الباحث على جهاز macOS، يمكنني النقر بزر الماوس الأيمن على صورة وفتحها SVGcode. تُسمى هذه الميزة "معالجة الملفات" وتعمل استنادًا إلى خاصية file_handlers في بيان تطبيق الويب وقائمة انتظار التشغيل، يسمحان للتطبيق باستهلاك الملف الذي تم تمريره.

فتح ملف من سطح المكتب باستخدام تطبيق SVGcode المثبّت
window.launchQueue.setConsumer(async (launchParams) => {
  if (!launchParams.files.length) {
    return;
  }
  for (const handle of launchParams.files) {
    const file = await handle.getFile();
    if (file.type.startsWith('image/')) {
      const blobURL = URL.createObjectURL(file);
      inputImage.addEventListener(
        'load',
        () => {
          URL.revokeObjectURL(blobURL);
        },
        {once: true},
      );
      inputImage.src = blobURL;
      await set(FILE_HANDLE, handle);
      return;
    }
  }
});

لمزيد من المعلومات، يمكنك الاطّلاع على السماح لتطبيقات الويب المثبَّتة بأن تكون معالِجات الملفات وعرض رمز المصدر في. src/js/filehandling.js

المشاركة على الويب (الملفات)

ومن الأمثلة الأخرى على الدمج مع نظام التشغيل ميزة مشاركة التطبيق. بافتراض أنني أريد إجراء تعديلات على رسم SVG (رسومات موجّهة يمكن تغيير حجمها) باستخدام SVGcode، من بينها حفظ الملفّ، تشغيل تطبيق تعديل الرسومات الموجّهة التي يمكن تغيير حجمها (SVG)، ثم فتح ملف SVG من هناك. ومع ذلك، فإن التدفق الأكثر سلاسة هو تستخدم Web Share API التي تسمح بمشاركة الملفات مباشرةً. لذلك إذا تطبيق تعديل الرسومات الموجّهة التي يمكن تغيير حجمها (SVG) هو هدف مشاركة، ويمكنه تلقّي الملف مباشرةً بدون انحراف.

shareSVGButton.addEventListener('click', async () => {
  let svg = svgOutput.innerHTML;
  svg = await optimizeSVG(svg);
  const suggestedFileName =
    getSuggestedFileName(await get(FILE_HANDLE)) || 'Untitled.svg';
  const file = new File([svg], suggestedFileName, { type: 'image/svg+xml' });
  const data = {
    files: [file],
  };
  if (navigator.canShare(data)) {
    try {
      await navigator.share(data);
    } catch (err) {
      if (err.name !== 'AbortError') {
        console.error(err.name, err.message);
      }
    }
  }
});
مشاركة صورة SVG مع Gmail.

هدف المشاركة على الويب (الملفات)

بالعكس، يمكن أن يعمل SVGcode أيضًا كهدف مشاركة وتلقّي الملفات من التطبيقات الأخرى. إلى فإن التطبيق يحتاج إلى إعلام نظام التشغيل من خلال Web Share Target API أنواع البيانات التي يمكنها قبولها. يتم ذلك من خلال المخصص في بيان تطبيق الويب.

{
  "share_target": {
    "action": "https://svgco.de/share-target/",
    "method": "POST",
    "enctype": "multipart/form-data",
    "params": {
      "files": [
        {
          "name": "image",
          "accept": ["image/jpeg", "image/png", "image/webp", "image/gif"]
        }
      ]
    }
  }
}

المسار action غير موجود فعلاً، ولكن يتم التعامل معه فقط في fetch لعامل الخدمة المعالِج، الذي يمرر الملفات المستلمة لمعالجتها فعليًا في التطبيق.

self.addEventListener('fetch', (fetchEvent) => {
  if (
    fetchEvent.request.url.endsWith('/share-target/') &&
    fetchEvent.request.method === 'POST'
  ) {
    return fetchEvent.respondWith(
      (async () => {
        const formData = await fetchEvent.request.formData();
        const image = formData.get('image');
        const keys = await caches.keys();
        const mediaCache = await caches.open(
          keys.filter((key) => key.startsWith('media'))[0],
        );
        await mediaCache.put('shared-image', new Response(image));
        return Response.redirect('./?share-target', 303);
      })(),
    );
  }
});
مشاركة لقطة شاشة مع رمز SVGcode.

الخاتمة

حسنًا، كانت هذه جولة سريعة عبر بعض ميزات التطبيق المتقدمة في رمز SVG. آمل أن يكون هذا التطبيق أداة أساسية لتلبية احتياجات معالجة الصور إلى جانب تطبيقات رائعة أخرى مثل Squoosh أو SVGOMG.

يتوفّر SVGcode على svgco.de. هل ترى ما فعلته هناك؟ يمكنك مراجعة رمز المصدر الخاص بالأداة على GitHub لاحظ أنه نظرًا لأن Potrace مرخّصة من شركة GPC، وكذلك SVGcode. وبهذا، يكون المتجه سعيدًا! آمل أن يكون ملف SVGcode مفيدًا وبعض ميزاته يمكن أن تلهم تطبيقك التالي.

شكر وتقدير

تمت مراجعة هذه المقالة من قِبل جو ميدلي.