كيف أنشأت Google تجربة متصلة لـ "وضع AI" الجديد باستخدام انتقالات العرض

تاريخ النشر: 28 أغسطس 2025

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

تسجيل لعملية بحث باستخدام "بحث Google"، والانتقال من نتائج البحث إلى "وضع AI" يستخدم الانتقال ميزة "عمليات انتقال العرض".

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

Browser Support

  • Chrome: 126.
  • Edge: 126.
  • Firefox: not supported.
  • Safari: 18.2.

Source

تغيير الوضع الراهن

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

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

لقد تبيّن لنا أنّ هذه الاستراتيجية ناجحة، وأعتقد أنّنا سنطبّقها على ميزات المتصفّح الجديدة الأخرى في المستقبل.

الصعوبات التي واجهناها وكيفية حلّها

وقت الاستجابة وحظر العرض وموقّتات مراقبة النظام

بشكل عام، يكون وقت الاستجابة الإضافي الذي يصاحب عمليات انتقال العرض في تطبيقات الصفحات المتعددة ضئيلاً بالنسبة إلى% 99 من حالات الاستخدام، خاصةً على الأجهزة الحديثة. ومع ذلك، يفرض "بحث Google" معايير عالية جدًا عندما يتعلّق الأمر بوقت الاستجابة، ونسعى جاهدين إلى توفير تجارب مستخدم تعمل بشكل جيد على جميع الأجهزة. بالنسبة إلينا، حتى بضع أجزاء من الثانية الإضافية مهمة، لذا كان علينا الاستثمار في كيفية تنفيذ عمليات الانتقال بين طرق العرض في المستندات المختلفة بشكلٍ صحيح بدون التأثير سلبًا في تجربة أي مستخدم.

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

<!-- Link tag in the <head> of the incoming document -->
<link blocking="render" href="#target-id" rel="expect">
<!-- Element you want to animate in the <body> of the incoming document -->
<div id="target-id">
  some content
</div>

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

يمكنك إجراء ذلك بسهولة باتّباع الخطوات التالية:

function unblockRendering() {
  const renderBlockingElements = document.querySelectorAll(
    'link[blocking=render]',
  );
  for (const element of renderBlockingElements) {
    element.remove();
  }
}

const timeToUnblockRendering = t - performance.now();

if (timeToUnblockRendering > 0) {
  setTimeout(unblockRendering, timeToUnblockRendering);
} else {
  unblockRendering();
}

حدود التغطية

المشكلة الأخرى التي واجهناها هي أنّ عمليات الانتقال بين طرق العرض المختلفة للمستندات في قاعدة navigation: auto تحدث على مستوى عام داخل المستند. لا تتوفّر طريقة مضمّنة لتحديد نطاق تفعيل انتقالات العرض بين المستندات ليشمل أهداف نقر معيّنة فقط. بما أنّ هذا التغيير كبير جدًا، لم نتمكّن من تفعيل انتقالات العرض بين المستندات على% 100 من عمليات التنقّل في &quot;بحث Google&quot;. كنّا بحاجة إلى طريقة لتفعيل أو إيقاف عمليات الانتقال بين طرق العرض في المستندات بشكل ديناميكي استنادًا إلى الميزة التي يتفاعل معها المستخدم. في حالتنا، فعّلنا هذه الإعدادات فقط عند التبديل من "وضع AI" وإليه. وقد فعلنا ذلك من خلال تعديل قاعدة at-rule الخاصة بالتنقّل آليًا استنادًا إلى العنصر المستهدف الذي تم النقر عليه.

في ما يلي طريقة لتبديل قاعدة view-transition at-rule:

let viewTransitionAtRule: HTMLElement | undefined;
const DISABLED_VIEW_TRANSITION = '@view-transition{navigation:none;}';
const ENABLED_VIEW_TRANSITION = '@view-transition{navigation:auto;}';

function getVtAtRule(): HTMLElement {
  if (!viewTransitionAtRule) {
    viewTransitionAtRule = document.createElement('style');
    document.head.append(viewTransitionAtRule);
  }
  return viewTransitionAtRule;
}

function disableVt() {
  getVtAtRule().textContent = DISABLED_VIEW_TRANSITION;
}

function enableVt() {
  getVtAtRule().textContent = ENABLED_VIEW_TRANSITION;
}

إيقاف مؤقت لعرض واجهة المستخدم والرسوم المتحركة المركّبة

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

const pseudoElement = `::view-transition-group(${name})`;
const animation = document
  .getAnimations()
  .find(
    (animation) =>
      (animation.effect as KeyframeEffect)?.pseudoElement === pseudoElement,
  );

يمكنك الاطّلاع على مزيد من المعلومات حول كتابة إطارات مفتاحية عالية الأداء لانتقالات العرض في تطبيق انتقالات العرض: التعامل مع الحظر الذي يتضمّن لقطة.

أمور أخرى يجب الانتباه إليها

من المشاكل الأكثر شيوعًا أنّ وضع علامات على العناصر باستخدام سمة view-transition-name في CSS يؤثّر في سياق التراص (مواصفات انتقالات العرض: القسم 2.1.1). كان هذا هو مصدر العديد من الأخطاء التي تطلّبت تعديل z-index لعناصر الحاوية.

يجب أيضًا الانتباه إلى أنّه قد لا يكون من المناسب إضافة قيم view-transition-name إلى العناصر تلقائيًا. يعمل الكثير من الأشخاص على "بحث Google". لمنع القيم view-transition-name التي يضبطها فريقنا على العناصر من التعارض مع القيم التي قد يستخدمها أشخاص من فِرق أخرى، استفدنا من أنواع انتقالات العرض لإضافة السمة view-transition-name بشكلٍ مشروط فقط أثناء نشاط نوع معيّن من انتقالات العرض.

مثال على رمز CSS لإضافة view-transition-name من the-element إلى عنصر فقط عندما يكون نوع انتقال العرض ai-mode نشطًا:

html:active-view-transition-type(ai-mode) {
  #target {
    view-transition-name: the-element;
  }
}

بعد تطبيق قواعد CSS هذه على جميع انتقالات العرض، يمكنك بعد ذلك تغيير نوع انتقال العرض الحالي بشكلٍ ديناميكي لأي عملية تنقّل خلال الحدثَين pageswap وpagereveal.

مثال على تعديل نوع انتقال العرض إلى ai-mode أثناء حدث pageswap

function updateViewTransitionTypes(
  event: ViewTransitionEvent,
  types: string[],
): void {
  event.viewTransition.types.clear();
  for (const type of types) {
    event.viewTransition.types.add(type);
  }
}

window.addEventListener(
  'pageswap',
  (e) => {
    updateViewTransitionTypes(
      e as ViewTransitionEvent,
      ['ai-mode'],
    );
  }
);

بهذه الطريقة، نتجنّب تعارض الأسماء ولا نلتقط لقطات غير ضرورية للعناصر التي لا تحتاج إلى ذلك عند الانتقال من "وضع AI" وإليه.

أخيرًا، لن تظهر أي مشاكل في سياق التجميع إلا أثناء انتقال العرض. لحلّ هذه المشاكل، يمكننا بعد ذلك استهداف قيم z-index للعناصر الزائفة التي تم إنشاؤها، بدلاً من تعديل قيم z-index للعناصر الأصلية بشكلٍ عشوائي لغرض وحيد هو حلّ هذه المشكلة عند استخدام عمليات الانتقال بين طرق العرض.

::view-transition-group(the-element) {
  z-index: 100;
}

الخطوات التالية

نخطّط لاستخدام عمليات الانتقال بين المشاهد في المستندات في "بحث Google"، بما في ذلك الدمج مع Navigation API بعد أن تصبح متاحة على جميع المتصفّحات. يُرجى متابعة أخبارنا لمعرفة الميزات التي سنطرحها قريبًا.