เนื้อหาเชิงโต้ตอบของ BBC ทำงานอย่างไรใน AMP, แอพ และเว็บ
เผยแพร่แล้ว: 2022-03-10ในทีม Visual Journalism ของ BBC เราผลิตเนื้อหาที่เป็นภาพที่น่าสนใจ มีส่วนร่วมและโต้ตอบได้ ตั้งแต่เครื่องคำนวณไปจนถึงการแสดงภาพรูปแบบการเล่าเรื่องรูปแบบใหม่
แต่ละแอปพลิเคชันมีความท้าทายเฉพาะตัวในการผลิตด้วยตัวของมันเอง แต่ยิ่งไปกว่านั้น เมื่อคุณพิจารณาว่าเราจำเป็นต้องปรับใช้โปรเจ็กต์ส่วนใหญ่ในภาษาต่างๆ มากมาย เนื้อหาของเราต้องใช้งานได้ไม่เฉพาะในเว็บไซต์ข่าวและกีฬาของ BBC แต่ในแอปที่เทียบเท่ากันบน iOS และ Android รวมถึงเว็บไซต์บุคคลที่สามที่ใช้เนื้อหา BBC
ตอนนี้ให้พิจารณาว่า มีแพลตฟอร์มใหม่ๆ เพิ่มขึ้นเรื่อยๆ เช่น AMP, Facebook Instant Articles และ Apple News แต่ละแพลตฟอร์มมีข้อจำกัดและกลไกการเผยแพร่ที่เป็นกรรมสิทธิ์ของตนเอง การสร้างเนื้อหาเชิงโต้ตอบที่ใช้งานได้ในสภาพแวดล้อมเหล่านี้เป็นความท้าทายที่แท้จริง ฉันจะอธิบายว่าเราแก้ปัญหาที่ BBC ได้อย่างไร
ตัวอย่าง: Canonical กับ AMP
ทั้งหมดนี้เป็นเพียงทฤษฎีเล็กน้อย จนกว่าคุณจะเห็นมันในการดำเนินการ ดังนั้น มาเจาะลึกเข้าไปในตัวอย่างกัน
นี่คือบทความของ BBC ที่มีเนื้อหา Visual Journalism:
นี่เป็นเวอร์ชันบัญญัติของบทความ กล่าวคือ เวอร์ชันเริ่มต้น ซึ่งคุณจะได้รับหากคุณไปยังบทความจากหน้าแรก
มาดูบทความเวอร์ชัน AMP กัน:
แม้ว่าเวอร์ชัน Canonical และ AMP จะเหมือนกัน แต่ แท้จริงแล้วเป็นปลายทางสองจุด ที่แตกต่างกันโดยมีพฤติกรรมต่างกัน:
- เวอร์ชันตามรูปแบบบัญญัติจะเลื่อนคุณไปยังประเทศที่คุณเลือกเมื่อคุณส่งแบบฟอร์ม
- เวอร์ชัน AMP ไม่เลื่อนให้คุณ เนื่องจากคุณไม่สามารถเลื่อนหน้าหลักจากภายใน AMP iframe
- เวอร์ชัน AMP แสดง iframe ที่ครอบตัดพร้อมปุ่ม "แสดงเพิ่มเติม" ทั้งนี้ขึ้นอยู่กับขนาดวิวพอร์ตและตำแหน่งการเลื่อน นี่คือคุณลักษณะของ AMP
เช่นเดียวกับเวอร์ชัน Canonical และ AMP ของบทความนี้ โปรเจ็กต์นี้ยังถูกส่งไปยังแอป News ซึ่งเป็นอีกแพลตฟอร์มหนึ่งที่มีความสลับซับซ้อนและข้อจำกัดของตัวเอง แล้ว เราจะสนับสนุนแพลตฟอร์มเหล่านี้ทั้งหมดได้อย่างไร?
เครื่องมือช่างเป็นกุญแจสำคัญ
เราไม่ได้สร้างเนื้อหาของเราตั้งแต่เริ่มต้น เรามีโครงนั่งร้านแบบ Yeoman ซึ่งใช้ Node เพื่อสร้างโครงการสำเร็จรูปด้วยคำสั่งเดียว
โปรเจ็กต์ใหม่มาพร้อมกับ Webpack, SASS, การปรับใช้ และโครงสร้างการจัดองค์ประกอบตั้งแต่แกะกล่อง ความเป็นสากลยังรวมอยู่ในโปรเจ็กต์ของเราโดยใช้ระบบการสร้างเทมเพลตของแฮนด์บาร์ Tom Maslen เขียนเกี่ยวกับสิ่งนี้โดยละเอียดในโพสต์ของเขา 13 เคล็ดลับสำหรับการออกแบบเว็บที่ตอบสนองได้หลายภาษา
ใช้งานได้ดีสำหรับการคอมไพล์สำหรับแพลตฟอร์มเดียว แต่ เราต้องรองรับหลายแพลตฟอร์ม มาเจาะลึกโค้ดกัน
ฝัง vs. สแตนด์อโลน
ใน Visual Journalism บางครั้งเราส่งออกเนื้อหาของเราใน iframe เพื่อให้สามารถ "ฝัง" ที่มีอยู่ในตัวเองในบทความได้โดยไม่ได้รับผลกระทบจากสคริปต์และการจัดรูปแบบทั่วโลก ตัวอย่างนี้เป็นแบบโต้ตอบของโดนัลด์ ทรัมป์ ที่ฝังอยู่ในตัวอย่างตามรูปแบบบัญญัติก่อนหน้าในบทความนี้
ในทางกลับกัน บางครั้งเราส่งออกเนื้อหาของเราในรูปแบบ HTML ดิบ เราทำสิ่งนี้ก็ต่อเมื่อเราสามารถควบคุมทั้งหน้าได้หรือถ้าเราต้องการการโต้ตอบการเลื่อนที่ตอบสนองจริงๆ เรียกเอาต์พุตเหล่านี้ว่า "embed" และ "standalone" ตามลำดับ
ลองนึกภาพว่าเราจะสร้าง "หุ่นยนต์จะรับงานของคุณหรือไม่" โต้ตอบได้ทั้งในรูปแบบ "ฝัง" และ "สแตนด์อโลน"
เนื้อหาทั้งสองเวอร์ชันจะใช้โค้ดส่วนใหญ่ร่วมกัน แต่จะมีความแตกต่างที่สำคัญบางประการในการใช้งาน JavaScript ระหว่างทั้งสองเวอร์ชัน
ตัวอย่างเช่น ดูที่ปุ่ม 'ค้นหาความเสี่ยงด้านระบบอัตโนมัติของฉัน' เมื่อผู้ใช้กดปุ่มส่ง พวกเขาควรจะเลื่อนไปที่ผลลัพธ์โดยอัตโนมัติ
โค้ดเวอร์ชัน "สแตนด์อโลน" อาจมีลักษณะดังนี้:
button.on('click', (e) => { window.scrollTo(0, resultsContainer.offsetTop); });
แต่ถ้าคุณสร้างสิ่งนี้เป็นเอาต์พุต "ฝัง" คุณรู้ว่าเนื้อหาของคุณอยู่ใน iframe ดังนั้นจะต้องเขียนโค้ดให้ต่างออกไป:
// inside the iframe button.on('click', () => { window.parent.postMessage({ name: 'scroll', offset: resultsContainer.offsetTop }, '*'); }); // inside the host page window.addEventListener('message', (event) => { if (event.data.name === 'scroll') { window.scrollTo(0, iframe.offsetTop + event.data.offset); } });
จะเกิดอะไรขึ้นหากแอปพลิเคชันของเราต้องแสดงแบบเต็มหน้าจอ ซึ่งง่ายพอหากคุณอยู่ในหน้า "สแตนด์อโลน":
document.body.className += ' fullscreen';
.fullscreen { position: fixed; top: 0; left: 0; right: 0; bottom: 0; }
หากเราพยายามทำสิ่งนี้จากภายใน "ฝัง" โค้ดเดียวกันนี้จะมีการปรับขนาดเนื้อหาเป็นความกว้างและความสูงของ iframe แทนที่จะเป็นวิวพอร์ต:
…ดังนั้น นอกเหนือจากการใช้สไตล์เต็มหน้าจอใน iframe แล้ว เราต้องส่งข้อความไปยังหน้าโฮสต์เพื่อใช้การจัดสไตล์กับ iframe:
// iframe window.parent.postMessage({ name: 'window:toggleFullScreen' }, '*'); // host page window.addEventListener('message', function () { if (event.data.name === 'window:toggleFullScreen') { document.getElementById(iframeUid).className += ' fullscreen'; } });
สิ่งนี้สามารถแปลเป็นรหัสปาเก็ตตี้ได้มากมายเมื่อคุณเริ่มรองรับหลายแพลตฟอร์ม:
button.on('click', (e) => { if (inStandalonePage()) { window.scrollTo(0, resultsContainer.offsetTop); } else { window.parent.postMessage({ name: 'scroll', offset: resultsContainer.offsetTop }, '*'); } });
ลองนึกภาพการทำสิ่งที่เทียบเท่ากับทุกๆ การโต้ตอบ DOM ที่มีความหมายในโครงการของคุณ เมื่อคุณสั่นสะท้านเสร็จแล้ว ให้ดื่มชาเพื่อผ่อนคลายและอ่านต่อ
สิ่งที่เป็นนามธรรมคือกุญแจสำคัญ
แทนที่จะบังคับให้นักพัฒนาของเราจัดการกับเงื่อนไขเหล่านี้ภายในโค้ดของพวกเขา เราได้สร้างเลเยอร์ที่เป็นนามธรรมระหว่างเนื้อหากับสภาพแวดล้อม เราเรียกเลเยอร์นี้ว่า 'ตัวห่อหุ้ม'
แทนที่จะสอบถาม DOM หรือเหตุการณ์เบราว์เซอร์ดั้งเดิมโดยตรง ตอนนี้เราสามารถพร็อกซีคำขอของเราผ่านโมดูล wrapper
ปเปอร์
import wrapper from 'wrapper'; button.on('click', () => { wrapper.scrollTo(resultsContainer.offsetTop); });
แต่ละแพลตฟอร์มมีการนำ wrapper ไปใช้โดยสอดคล้องกับอินเทอร์เฟซทั่วไปของเมธอด wrapper เสื้อคลุมห่อหุ้มเนื้อหาของเราและจัดการกับความซับซ้อนสำหรับเรา
การปรับใช้ฟังก์ชัน scrollTo
ของ wrapper แบบสแตนด์อโลนนั้นง่ายมาก โดยส่งอาร์กิวเมนต์ของเราโดยตรงไปที่ window.scrollTo
ภายใต้ประทุน
ตอนนี้ ให้ดูที่ wrapper แยกต่างหากที่ใช้ฟังก์ชันเดียวกันสำหรับ iframe:
Wrapper "ฝัง" ใช้อาร์กิวเมนต์เดียวกับในตัวอย่าง "สแตนด์อโลน" แต่จัดการค่าเพื่อพิจารณาออฟเซ็ต iframe หากไม่มีการเพิ่มนี้ เราจะเลื่อนผู้ใช้ของเราไปที่ใดที่หนึ่งโดยไม่ได้ตั้งใจ
รูปแบบกระดาษห่อ
การใช้ wrappers ส่งผลให้โค้ดสะอาดขึ้น อ่านง่ายขึ้น และสอดคล้องกันระหว่างโปรเจ็กต์ต่างๆ นอกจากนี้ยังช่วยให้มีการปรับให้เหมาะสมระดับไมโครเมื่อเวลาผ่านไป เนื่องจากเราทำการปรับปรุงส่วนเพิ่มในเครื่องห่อเพื่อให้วิธีการมีประสิทธิภาพและเข้าถึงได้มากขึ้น ดังนั้น โครงการของคุณสามารถได้รับประโยชน์จากประสบการณ์ของนักพัฒนาหลายคน
ดังนั้นเสื้อคลุมมีลักษณะอย่างไร?
โครงสร้างห่อหุ้ม
Wrapper แต่ละอันประกอบด้วยสามสิ่ง: เทมเพลต Handlebars, ไฟล์ wrapper JS และไฟล์ SASS ที่แสดงถึงสไตล์เฉพาะของ Wrapper นอกจากนี้ยังมีงานสร้างที่เกี่ยวโยงกับเหตุการณ์ที่เปิดเผยโดยโครงนั่งร้านพื้นฐาน เพื่อให้เสื้อคลุมแต่ละตัวมีหน้าที่ในการคอมไพล์ล่วงหน้าและการล้างข้อมูลของตัวเอง
นี่คือมุมมองที่เรียบง่ายของ Wrapper แบบฝัง:
embed-wrapper/ templates/ wrapper.hbs js/ wrapper.js scss/ wrapper.scss
นั่งร้านพื้นฐานของเราเผยให้เห็นเทมเพลตโครงการหลักของคุณเป็นบางส่วนของแฮนด์บาร์ ซึ่งใช้โดยเสื้อคลุม ตัวอย่างเช่น templates/wrapper.hbs
อาจมี:
<div class="bbc-news-vj-wrapper--embed"> {{>your-application}} </div>
scss/wrapper.scss
มีการกำหนดสไตล์เฉพาะของ wrapper ซึ่งโค้ดแอปพลิเคชันของคุณไม่จำเป็นต้องกำหนดเอง ตัวอย่างเช่น Wrapper แบบฝัง จำลองสไตล์ของ BBC News จำนวนมากใน iframe
สุดท้าย js/wrapper.js
มีการใช้งาน iframed ของ wrapper API โดยมีรายละเอียดด้านล่าง มันถูกจัดส่งแยกต่างหากไปยังโปรเจ็กต์ แทนที่จะคอมไพล์ด้วยโค้ดแอปพลิเคชัน — เราตั้งค่าสถานะ wrapper
เป็นโกลบอลในกระบวนการสร้าง Webpack ของเรา ซึ่งหมายความว่าแม้ว่าเราจะส่งแอปพลิเคชันของเราไปยังหลายแพลตฟอร์ม แต่เรารวบรวมโค้ดเพียงครั้งเดียว
Wrapper API
wrapper API สรุปการโต้ตอบที่สำคัญของเบราว์เซอร์จำนวนหนึ่ง นี่คือสิ่งที่สำคัญที่สุด:
scrollTo(int)
เลื่อนไปยังตำแหน่งที่กำหนดในหน้าต่างที่ใช้งานอยู่ Wrapper จะทำให้จำนวนเต็มที่ให้มาเป็น ปกติ ก่อนที่จะเรียกการเลื่อนเพื่อให้หน้าโฮสต์ถูกเลื่อนไปยังตำแหน่งที่ถูกต้อง
getScrollPosition: int
ส่งกลับตำแหน่งการเลื่อนปัจจุบัน (ปกติ) ของผู้ใช้ ในกรณีของ iframe นี่หมายความว่าตำแหน่งการเลื่อนที่ส่งผ่านไปยังแอปพลิเคชันของคุณนั้นเป็น ค่าลบ จริงๆ จนกว่า iframe จะอยู่ที่ด้านบนสุดของวิวพอร์ต สิ่งนี้มีประโยชน์อย่างยิ่งและช่วยให้เราทำสิ่งต่างๆ เช่น ทำให้องค์ประกอบเคลื่อนไหวได้ก็ต่อเมื่อองค์ประกอบนั้นปรากฏขึ้นเท่านั้น
onScroll(callback)
ให้เบ็ดในเหตุการณ์เลื่อน ใน Wrapper แบบสแตนด์อโลน สิ่งนี้จะเชื่อมโยงกับเหตุการณ์การเลื่อนแบบเนทีฟเป็นหลัก ใน Wrapper ที่ฝัง จะมีความล่าช้าเล็กน้อยในการรับเหตุการณ์การเลื่อน เนื่องจากมันถูกส่งผ่าน postMessage
viewport: {height: int, width: int}
วิธีการดึงข้อมูลความสูงและความกว้างของวิวพอร์ต (เนื่องจากมีการใช้งานแตกต่างกันมากเมื่อสอบถามจากภายใน iframe)
toggleFullScreen
ในโหมดสแตนด์อโลน เราซ่อนเมนู BBC และส่วนท้ายไม่ให้มองเห็นและตั้งค่า position: fixed
ในเนื้อหาของเรา ในแอพ News เราไม่ทำอะไรเลย — เนื้อหาเต็มหน้าจออยู่แล้ว สิ่งที่ซับซ้อนคือ iframe ซึ่งอาศัยการใช้สไตล์ทั้งภายในและภายนอก iframe ซึ่งประสานงานผ่าน postMessage
markPageAsLoaded
บอกผู้ห่อว่าเนื้อหาของคุณโหลดแล้ว นี่เป็นสิ่งสำคัญสำหรับเนื้อหาของเราในการทำงานในแอป News ซึ่งจะไม่พยายามแสดงเนื้อหาของเราต่อผู้ใช้จนกว่าเราจะแจ้งให้แอปทราบอย่างชัดเจนว่าเนื้อหาของเราพร้อม นอกจากนี้ยังลบสปินเนอร์การโหลดเนื้อหาในเวอร์ชันเว็บของเราด้วย
รายการห่อ
ในอนาคต เรานึกภาพการสร้าง Wrapper เพิ่มเติมสำหรับแพลตฟอร์มขนาดใหญ่ เช่น Facebook Instant Articles และ Apple News เราได้สร้าง wrappers หกรายการจนถึงปัจจุบัน:
Wrapper แบบสแตนด์อโลน
เวอร์ชันของเนื้อหาของเราที่ควรอยู่ในหน้าแบบสแตนด์อโลน มาพร้อมกับแบรนด์ BBC
Wrapper แบบฝัง
เวอร์ชัน iframe ของเนื้อหาของเรา ซึ่งปลอดภัยสำหรับนั่งอ่านในบทความหรือเผยแพร่ไปยังไซต์ที่ไม่ใช่ BBC เนื่องจากเรายังคงควบคุมเนื้อหา
แอมป์ แรปเปอร์
นี่คือปลายทางที่ดึงเข้ามาเป็น amp-iframe
ในหน้า AMP
Wrapper แอปข่าว
เนื้อหาของเราต้องทำการเรียกโปรโตคอล bbcvisualjournalism://
ที่เป็นกรรมสิทธิ์
เครื่องห่อแกน
มีเฉพาะ HTML — ไม่มี CSS หรือ JavaScript ของโครงการของเรา
JSON Wrapper
การแสดง JSON ของเนื้อหาของเรา สำหรับการแบ่งปันข้ามผลิตภัณฑ์ของ BBC
เครื่องพันสายไฟบนแท่น
เพื่อให้เนื้อหาของเราปรากฏบนไซต์ BBC เราจัดเตรียมเส้นทางเนมสเปซให้นักข่าว:
/include/[department]/[unique ID], eg
/include/visual-journalism/123-quiz
นักข่าวใส่ "เส้นทางรวม" นี้ไว้ใน CMS ซึ่งจะบันทึกโครงสร้างบทความลงในฐานข้อมูล ผลิตภัณฑ์และบริการทั้งหมดอยู่ปลายน้ำของกลไกการเผยแพร่นี้ แต่ละแพลตฟอร์มมีหน้าที่ในการเลือกรสชาติของเนื้อหาที่ต้องการและขอเนื้อหานั้นจากพร็อกซีเซิร์ฟเวอร์
สมมติว่าโดนัลด์ทรัมป์โต้ตอบจากก่อนหน้านี้ ที่นี่ เส้นทางรวมใน CMS คือ:
/include/newsspec/15996-trump-tracker/english/index
หน้าบทความตามรูปแบบบัญญัติรู้ว่าต้องการเนื้อหาเวอร์ชัน "ฝัง" ดังนั้นจึงผนวก /embed
ต่อท้ายเส้นทางรวม:
/include/newsspec/15996-trump-tracker/english/index
/embed
…ก่อนที่จะขอจากพร็อกซีเซิร์ฟเวอร์:
https://news.files.bbci.co.uk/include/newsspec/15996-trump-tracker/english/index/embed
ในทางกลับกัน หน้า AMP จะเห็นเส้นทางรวมและต่อท้าย /amp
:
/include/newsspec/15996-trump-tracker/english/index
/amp
ตัวแสดง AMP ใช้เวทย์มนตร์เล็กน้อยในการแสดงผล AMP HTML ซึ่งอ้างอิงเนื้อหาของเรา โดยดึงเวอร์ชัน /amp
เป็น iframe:
<amp-iframe src="https://news.files.bbci.co.uk/include/newsspec/15996-trump-tracker/english/index/amp" width="640" height="360"> <!-- some other AMP elements here --> </amp-iframe>
ทุกแพลตฟอร์มที่รองรับมีเนื้อหาในเวอร์ชันของตัวเอง:
/include/newsspec/15996-trump-tracker/english/index
/amp
/include/newsspec/15996-trump-tracker/english/index
/core
/include/newsspec/15996-trump-tracker/english/index
/envelope
...และอื่นๆ
โซลูชันนี้สามารถปรับขนาดเพื่อรวมประเภทแพลตฟอร์มเพิ่มเติมตามที่เกิดขึ้น
สิ่งที่เป็นนามธรรมเป็นเรื่องยาก
การสร้างสถาปัตยกรรมแบบ "เขียนครั้งเดียว ปรับใช้ได้ทุกที่" ฟังดูเป็นอุดมคติและเป็นเช่นนั้น เพื่อให้สถาปัตยกรรมของ wrapper ทำงานได้ เราต้องเข้มงวด มาก ในการทำงานภายในสิ่งที่เป็นนามธรรม ซึ่งหมายความว่าเราต้องต่อสู้กับสิ่งล่อใจที่จะ "ทำสิ่งที่แฮ็กนี้เพื่อให้ทำงานใน [ใส่ชื่อแพลตฟอร์มที่นี่]" เราต้องการให้เนื้อหาของเราไม่รับรู้ถึงสภาพแวดล้อมที่ส่งเข้ามาโดยสิ้นเชิง แต่พูดง่ายกว่าทำ
คุณสมบัติของแพลตฟอร์มนั้นยากต่อการกำหนดค่าอย่างเป็นนามธรรม
ก่อนแนวทางนามธรรมของเรา เราได้ควบคุมทุกแง่มุมของผลลัพธ์ของเราอย่างสมบูรณ์ ซึ่งรวมถึง ตัวอย่างเช่น มาร์กอัปของ iframe ของเรา หากเราจำเป็นต้องปรับแต่งสิ่งใดๆ ตามแต่ละโปรเจ็กต์ เช่น เพิ่มแอตทริบิวต์ title
ให้กับ iframe เพื่อเหตุผลในการเข้าถึง เราสามารถแก้ไขมาร์กอัปได้
ขณะนี้มาร์กอัปของแรปเปอร์แยกจากโปรเจ็กต์แล้ว วิธีเดียวในการกำหนดค่าก็คือการเปิดเผยตะขอในโครงนั่งร้านเอง เราสามารถทำได้ค่อนข้างง่ายสำหรับคุณสมบัติข้ามแพลตฟอร์ม แต่การเปิดเผย hook สำหรับแพลตฟอร์มเฉพาะจะทำลายสิ่งที่เป็นนามธรรม เราไม่ต้องการเปิดเผยตัวเลือกการกำหนดค่า 'ชื่อ iframe' ที่ใช้โดย wrapper เดียวเท่านั้น
เราสามารถตั้งชื่อคุณสมบัติให้กว้างขึ้นได้ เช่น title
แล้วใช้ค่านี้เป็นแอตทริบิวต์ title
iframe อย่างไรก็ตาม มันเริ่มเป็นเรื่องยากที่จะติดตามว่าสิ่งใดถูกใช้ที่ไหน และเราเสี่ยงที่จะสรุปการกำหนดค่าของเราจนไม่เข้าใจอีกเลย โดยทั่วไปแล้ว เราพยายามรักษาการกำหนดค่าของเราให้น้อยที่สุดเท่าที่จะทำได้ โดยตั้งค่าคุณสมบัติที่มีการใช้งานทั่วโลกเท่านั้น
พฤติกรรมของส่วนประกอบอาจซับซ้อน
บนเว็บ โมดูลเครื่องมือแชร์ของเราจะแยกปุ่มแชร์เครือข่ายสังคมที่สามารถคลิกได้ทีละรายการและเปิดข้อความการแชร์ที่สร้างไว้ล่วงหน้าในหน้าต่างใหม่
ในแอพ News เราไม่ต้องการแชร์ผ่านเว็บบนมือถือ หากผู้ใช้ติดตั้งแอปพลิเคชันที่เกี่ยวข้อง (เช่น Twitter) เราต้องการแชร์ในแอปเอง ตามหลักการแล้ว เราต้องการนำเสนอเมนูการแชร์สำหรับ iOS/Android ดั้งเดิมแก่ผู้ใช้ จากนั้นให้พวกเขาเลือกตัวเลือกการแชร์ก่อนที่เราจะเปิดแอปสำหรับพวกเขาด้วยข้อความแชร์ที่เติมไว้ล่วงหน้า เราสามารถเรียกเมนูการแชร์แบบเนทีฟจากแอปได้โดยการโทรไปยังโปรโตคอล bbcvisualjournalism://
ที่เป็นกรรมสิทธิ์
อย่างไรก็ตาม หน้าจอนี้จะถูกเรียกใช้ไม่ว่าคุณจะแตะ 'Twitter' หรือ 'Facebook' ในส่วน 'แชร์ผลลัพธ์ของคุณ' ดังนั้นผู้ใช้จึงจำเป็นต้องเลือกสองครั้ง ครั้งแรกในเนื้อหาของเรา และครั้งที่สองในป๊อปอัปดั้งเดิม
นี่เป็นการเดินทางของผู้ใช้ที่แปลก เราจึงต้องการลบไอคอนแชร์แต่ละรายการออกจากแอป News และแสดงปุ่มแชร์ทั่วไปแทน เราสามารถทำได้โดยการตรวจสอบอย่างชัดแจ้งว่ามีการใช้กระดาษห่อตัวใดอยู่ก่อนที่เราจะแสดงผลส่วนประกอบ
การสร้างเลเยอร์ wrapper abstraction ทำงานได้ดีสำหรับโครงการโดยรวม แต่เมื่อการเลือก wrapper ของคุณส่งผลต่อการเปลี่ยนแปลงในระดับ ส่วนประกอบ เป็นเรื่องยากมากที่จะรักษาสิ่งที่เป็นนามธรรมที่ชัดเจน ในกรณีนี้ เราสูญเสียสิ่งที่เป็นนามธรรมไปเล็กน้อย และเรามีตรรกะในการฟอร์กที่ยุ่งเหยิงในโค้ดของเรา โชคดีที่กรณีเหล่านี้มีอยู่ไม่มากนัก
เราจะจัดการกับคุณสมบัติที่ขาดหายไปได้อย่างไร
การรักษาความเป็นนามธรรมเป็นสิ่งที่ดีและดี รหัสของเราจะบอก wrapper ว่าต้องการให้แพลตฟอร์มทำอะไร เช่น "แสดงเต็มหน้าจอ" แต่ถ้าแพลตฟอร์มที่เราจัดส่งไม่สามารถแสดงแบบเต็มหน้าจอได้จริง ๆ ล่ะ?
กระดาษห่อหุ้มจะพยายามอย่างดีที่สุดที่จะไม่แตกหักเลย แต่ในท้ายที่สุด คุณต้องมีการออกแบบที่ถอยกลับไปใช้โซลูชันการทำงานได้อย่างสง่างามไม่ว่าวิธีการนั้นจะสำเร็จหรือไม่ก็ตาม เราต้องออกแบบเกมรับ
สมมติว่าเรามีส่วนผลลัพธ์ที่มีแผนภูมิแท่งอยู่บ้าง เรามักต้องการให้ค่าแผนภูมิแท่งอยู่ที่ศูนย์จนกว่าแผนภูมิจะถูกเลื่อนเข้าสู่มุมมอง ซึ่งเราจะทริกเกอร์แถบที่เคลื่อนไหวตามความกว้างที่ถูกต้อง
แต่ถ้าเราไม่มีกลไกที่จะขอเข้าไปในตำแหน่งเลื่อน - เช่นเดียวกับใน Wrapper AMP ของเรา - แถบจะอยู่ที่ศูนย์ตลอดไป ซึ่งเป็นประสบการณ์ที่ทำให้เข้าใจผิดอย่างทั่วถึง
เรากำลังพยายามนำวิธีการเพิ่มประสิทธิภาพแบบก้าวหน้ามาใช้ในการออกแบบของเรามากขึ้น ตัวอย่างเช่น เราสามารถจัดเตรียมปุ่มที่จะมองเห็นได้สำหรับทุกแพลตฟอร์มโดยค่าเริ่มต้น แต่จะซ่อนไว้หาก Wrapper รองรับการเลื่อน ด้วยวิธีนี้ หากการเลื่อนไม่สามารถเรียกภาพเคลื่อนไหวได้ ผู้ใช้ยังสามารถเรียกภาพเคลื่อนไหวด้วยตนเองได้
แผนสำหรับอนาคต
เราหวังว่าจะพัฒนา wrapper ใหม่สำหรับแพลตฟอร์มต่างๆ เช่น Apple News และ Facebook Instant Articles ตลอดจนเสนอแพลตฟอร์มใหม่ทั้งหมดเป็นเวอร์ชัน 'หลัก' ของเนื้อหาของเราตั้งแต่แกะกล่อง
นอกจากนี้เรายังหวังว่าจะได้รับการปรับปรุงให้ดีขึ้นเรื่อย ๆ การประสบความสำเร็จในด้านนี้หมายถึงการพัฒนาแนวรับ คุณไม่สามารถสรุปได้ว่าทุกแพลตฟอร์มในตอนนี้และในอนาคตจะรองรับการโต้ตอบที่กำหนด แต่ โปรเจ็กต์ที่ออกแบบมาอย่างดีควรจะสามารถถ่ายทอดข้อความหลัก ได้โดยไม่สะดุดกับอุปสรรคทางเทคนิคแรก
การทำงานภายในขอบเขตของกระดาษห่อหุ้มเป็นการเปลี่ยนกระบวนทัศน์เล็กน้อย และให้ความรู้สึกเหมือนอยู่ครึ่งทางในแง่ของการแก้ปัญหา ระยะยาว แต่จนกว่าอุตสาหกรรมจะเติบโตสู่มาตรฐานข้ามแพลตฟอร์ม ผู้เผยแพร่โฆษณาจะถูกบังคับให้เปิดตัวโซลูชันของตนเอง หรือใช้เครื่องมือเช่น Distro สำหรับการแปลงจากแพลตฟอร์มเป็นแพลตฟอร์ม มิฉะนั้นจะเพิกเฉยต่อส่วนต่างๆ ของผู้ชมทั้งหมด
ถือเป็นช่วงแรกๆ สำหรับเรา แต่จนถึงขณะนี้ เราประสบความสำเร็จอย่างมากในการใช้รูปแบบแรปเปอร์เพื่อสร้างเนื้อหาเพียงครั้งเดียว และนำเสนอไปยังแพลตฟอร์มมากมายที่ผู้ชมของเราใช้อยู่