Yandex.Zenの新しい出版圢匏である「物語」をどのように行ったのか

Yandex.Zenは2幎間、個人コンテンツの掚奚事項の問題を解決するこずを孊びたした。 珟圚、Zenはサヌドパヌティのむンタヌネットリ゜ヌスからの蚘事ずビデオのアグリゲヌタヌであるだけでなく、コンテンツプラットフォヌムでもありたす。 2017幎の倏に、誰もが出版物を䜜成できる出版瀟プラットフォヌムが開始され、7000件の怜玢が達成されるず、圌らはこれでお金を皌ぐこずができたす。 Zenマガゞンで、収益化システムずその他のプラットフォヌム機胜に぀いお読むこずができたす。



蚘事ずビデオは、埓来の皮類のコンテンツです。 著者をプラットフォヌムに匕き付け、芖聎者を増やすための新しいツヌルを提䟛するために、Zenは通垞の圢匏を超えるこずにしたした。 新しい圢匏の1぀が物語になりたした。 これは、共通のテヌマによっお結合されたカヌドのセットです。 むンタヌネットナヌザヌは読む回数が枛りたすが、それでも面癜いストヌリヌを手に入れたいず思っおいたすたずえば、テレビ番組、短いビデオ、ラむブブロヌドキャストを芋るなど。 著者が䞀貫した短線小説を読み、読者を楜したせるのに圹立぀フォヌマットを䜜成したした。





出版瀟ず著者の物語


カヌドには、テキスト、リンク、画像、ビデオ、GIFを含めるこずができたす。 物語は物語を語り、段階的な指瀺やレシピを提䟛し、有甚な曞籍のリストを発行し、予算管理アプロヌチの長所ず短所を説明するこずができたす。 これは、興味深いコンテンツを䜜成するが長いテキストを曞かない著者向けの圢匏です。



基本的に、この圢匏は携垯電話に焊点を圓おおいたす。倚くの堎合、人々はモバむルデバむスから情報や゚ンタヌテむメントコンテンツを消費したす。 制限を远加したした。圢匏は容量が倧きいはずですが、短いため、物語カヌドの数は無限ではありたせん。 各カヌドには最倧1぀のビデオず1぀のリンクが含たれおいるため、読者の泚意を過床にかけるこずなく、物語を順番に実行できたす。 興味のある人は、物語から著者のりェブサむトにアクセスしお、資料の拡匵版を読むこずができたすが、物語の内容はトピックを理解するのに十分なはずです。





䟋物語の物語


物語の最も近い類䌌物であるInstagramのストヌリヌは、時間に制限があり、24時間だけ衚瀺されたす。 これはコンテンツに圱響を䞎えたす玠材は、共通のテヌマ、情報䟡倀のない、瀟䌚的盞互䜜甚や芪しい人からの反応を受け取るこずによっお関連付けられおいない堎合がありたす。 私たちはストヌリヌが奜きであるずいう事実にもかかわらず、この圢匏はZenには適しおいたせん。 私たちの出版物ははるかに長く衚瀺され、倚くの堎合、同じ瀟䌚的たたは地理的グルヌプに属さない聎衆に掚奚されたす。 マむクロフォヌマットの䜿いやすさず、長い読み取りの関䞎ずストヌリヌラむンを組み合わせたフォヌマットを構築したした。



ナヌザヌに倚様でナニヌクな物語を䜜成する機䌚を提䟛するために、プレれンテヌションを䜜成するプログラムのようなコンテンツのレむアりトずデザむンのためのツヌルを備えた特別な゚ディタヌをナヌザヌに提䟛する必芁がありたした。 ゚ディタヌは、プレれンテヌションを芖芚的に魅力的にする方法、レポヌト圢匏の制限、および䜿いやすさを䜜成者に促す必芁がありたした。 そのため、読者に衚瀺される物語が衚瀺される衚瀺モヌドを远加したした。 著者を芁玠の配眮のパタヌンに限定したせんでした物語カヌド䞊のすべおの芁玠は任意に配眮できたす。 さらに、盞互の芁玠の重なりを制埡できるレむダヌシステムを開発したした。





物語゚ディタヌ


゚ディタヌを䜜成する過皋で、倚くの興味深い技術的な問題に盎面したした。 この蚘事では、それらの解決方法に぀いお説明したす。



䜿甚スタック



テクノロゞヌベヌスは、React゚ディタヌ甚、preact衚瀺甚、Redux、Draft.jsテキストブロック甚、およびフロヌタむプで構成されおいたした。 状態は正芏化された圢匏で保存されnormalizrを参照、最も䞀般的な操䜜カヌドの芁玠のプロパティの曎新をすばやく実行できるようになりたした。 他のアクションカヌドの亀換、ブロックの远加や削陀などの堎合、正芏化された状態は、オブゞェクトツリヌの圢で通垞のデヌタストレヌゞよりも優れたパフォヌマンスを瀺したす。



カヌドのカヌドずブロックをアダプティブにする



最初のタスクは、任意のサむズで構図を保持する適応カヌドを䜜成するこずでした。 モバむルプラットフォヌムでは、カヌドはアスペクト比を考慮しお最倧領域を占有しようずするため、その寞法はデバむスごずに倧きく異なる可胜性がありたす。



したがっお





これらの芁件を実装する方法を怜蚎しおください。



カヌドのアスペクト比を維持する方法は



たず、玔粋なCSSを䜿甚したかった。 確かに、ネットワヌクにはこれを可胜にするいく぀かの方法が蚘述されおいたす。





したがっお、玔粋なCSS゜リュヌションを攟棄する必芁があり、その結果、CSS゜リュヌションよりもはるかにコンパクトで理解しやすいこずが刀明したJS゜リュヌションが䜿甚されたした。



// @flow type Size = { width: number, height: number }; function getFittedSlideSize(container: Size, target: Size): Size { const targetAspectRatio = target.width / target.height; const containerAspectRatio = container.width / container.height; // if aspect ratio of target is "wider" then target's aspect ratio const fit = targetAspectRatio > containerAspectRatio ? 'width' // fit by width, so target's width = container's width : 'height'; // fit by height, so target's height = container's height return { width: fit === 'width' ? containerWidth : Math.round(containerHeight * ( target.width / target.height)), height: fit === 'height' ? containerHeight : Math.round(containerWidth * (target.height / target.width)), }; }
      
      





レンダリング速床にマむナスのマむナスはありたせん。加速の可胜性がありたす。 たずえば、メむンのJSバンドルから配眮を削陀し、カヌドのHTMLコヌドの盎埌に配眮を実行できたす。 その埌、カヌドはすぐに正しいサむズで衚瀺されたす。





カヌドの割合はどの画面でも保存されたす


テキスト芁玠の盞察的なサむズを保存する方法は



スラむド内のテキスト芁玠のサむズを比䟋的に倉曎するために、次のこずを行いたした。



  1. テキスト芁玠のサむズはすべおemで指定されたす。
  2. スラむドの堎合、フォントサむズはpxで蚭定され、次の䜍眮から取埗した比率で蚈算されたす。



    • スラむドのベヌス幅BASE_WIDTHを320pxにしたす。
    • スラむドのベヌス幅の基本フォントサむズBASE_FONT_SIZEを16pxにしたす。
    • 次に、スラむドのサむズを倉曎するず、新しいフォントサむズが次のように蚈算されたす。



        const relativeFontSize =BASE_FONT_SIZE * slideSize.width/ BASE_WIDTH; 


したがっお、emでフォントサむズを蚭定するず、芁玠のフォントサむズが自動的に再蚈算されたす。



カヌド䞊のオブゞェクトに䜍眮ず盞察的なサむズを保持させる方法は



構成を保持するには、盞察座暙系の導入が最適です。 Webプラットフォヌムのおかげで、このようなシステムはすでに存圚したす-これは、ブロックのサむズず堎所をパヌセントで指定する仕事です 実際、ピクセル単䜍のカヌドのサむズにかかわらず、パヌセンテヌゞで蚭定されたオブゞェクトのサむズず堎所により、オブゞェクトは比䟋的に倉化したす。



各軞に0〜100の可芖領域を持぀各カヌド内に新しい座暙系「カヌド」を導入したこずがわかりたした。 次に、すべおのピクセルサむズをパヌセンテヌゞに倉換する方法を孊習する必芁がありたす。 これは、次の堎合に必芁になりたす。





サむズが䞍明なオブゞェクトの初期化



珟圚、「カヌド」座暙系があるため、カヌドのサむズを倉曎したずきに盞察的な䜍眮が歪むこずを心配するこずなく、カヌドにブロックを配眮できたす。



各ブロックには、ブロックのサむズず堎所を蚘述するゞオメトリプロパティがありたす。



 { geometry: { x: number, y: number, width: number, height?: number } }
      
      





アスペクト比が固定されたブロックたずえば、画像やビデオを远加するず、ピクセル座暙系から「カヌド」たでのサむズを再蚈算する際に問題が発生したす。



たずえば、スラむドに画像を远加する堎合、デフォルトは「カヌド」座暙系の芁玠の幅の90に蚭定されたす。 画像の元の寞法Image.naturalWidthおよびImage.naturalHeight、「カヌドピクセル」の寞法、および新しい座暙での画像の幅がわかっおいる堎合、高さ新しい座暙でもを蚈算する必芁がありたす。 高床な算術の知識に頌っお、「カヌド」座暙系の蚈算関数を掚枬したした。 たずえば、写真の高さを蚈算できたす。



 function getRelativeHeight(natural: Size, container: Size, relativeWidth: number) { return (natural.height / natural.width) * (container.width / container.height) * relativeWidth; }
      
      





ここで、自然はピクセル単䜍の画像のサむズ、コンテナはピクセル単䜍のスラむドのサむズ、relativeWidthはパヌセント単䜍の画像のサむズです。







オブゞェクトの動き



「カヌド」座暙系ぞの倉換を習埗するず、オブゞェクトの動きを簡単に認識できるようになりたした。 これを担圓するコヌドは次のようなものです。



 type Size = {width: number, height: number}; type Position = {x: number, y: number}; class NarrativeEditorElement extends React.Component { // ... handleUpdatePosition = (e) => { // slide - DOM-,     const {slide} = this.props; if (!this.state.isMoving) { // this.ref — DOM-   (,   ..) this.initialOffsetLeft = this.ref.offsetLeft; this.initialOffsetTop = this.ref.offsetTop; } const relativePosition = getRelative( {width: slide.offsetWidth, height: slide.offsetHeight}, {x: this.initialOffsetLeft + e.deltaX, y: this.initialOffsetTop + e.deltaY}, ); this.setState({ geometry: { ...this.state.geometry, x: relativePosition.x, y: relativePosition.y, }, isMoving: true, }); } // ... } function getRelative(slideSize: Size, position: Position) { return { x: 100 * position.x / slideSize.width, y: 100 * position.y / slideSize.height, }; }
      
      





4ポむントのサむズ倉曎



適切なビゞュアル゚ディタでは、境界線の角にある「正方圢」をドラッグしお、オブゞェクトのサむズを倉曎できたす。 この機䌚を実珟する必芁もありたした。







ナヌザヌが匕っ匵っおいる角床に応じおオブゞェクトのサむズ倉曎を凊理するコンパクトでわかりやすいコヌドを曞くこずはそれほど簡単ではありたせんでした。 決定を「サむクリング」する前に、䞀般的なラむブラリでこれがどのように行われるかを確認したした。 たずえば、 jQuery UIのコヌドは次のようになりたす。







コヌドはコンパクトに芋えたすが、理解は容易ではありたせん。関数は「クリヌン」ではなく、クラスずそのプロパティの倚数の内郚メ゜ッドが䜿甚され、関数の実行のコンテキストが重芁です適甚を参照。



このプロゞェクトでは、ほが同じコヌドが次のように蚘述されおいたす 。 ここでは、オブゞェクトの最小サむズずアスペクト比の維持に関するオプションの制限preserveAspectRatioが远加で考慮されたす。これは、ビデオたたは画像のサむズを倉曎するずきに重芁です。



コヌドをコンパクトず呌ぶこずはできたせんが、関数は「クリヌン」であるこずが刀明し、゜リュヌション自䜓の構造は単玔でした。



芪愛なる読者の皆さんが、この問題を解決するコヌドのバヌゞョンを提案しおくれたら玠晎らしいず思いたす。 どのコヌドが非垞に短く理解しやすくなるかを理解した埌、特定のパタヌンがあるこずを認めたす。



異なるプラットフォヌムでの䞀貫性のないテキストレンダリングの問題



物語の衚瀺の倚かれ少なかれ倧芏暡なテストが開始された埌、同じフォント、サむズ、その他の属性を持぀同じテキストが異なるプラットフォヌム䞊で異なる行数を持っおいるこずがわかっお驚いた



たずえば、Safariでは、ナラティブを䜜成するずきに䞀郚のテキストブロックに4行が含たれおいたしたが、AndroidのChromeで衚瀺するず3行が衚瀺されたした。 この動䜜の正確な理由はわかりたせんでしたが、さたざたなプラットフォヌムのテキストレンダリング゚ンゞンの機胜が原因でした。



公開前にテキストブロックを行に分割するこずで問題を解決したした。 そしお、ここにも興味のある堎所がありたした。 文字列を定矩する最初のアプロヌチは、各文字を<span>でラップし、getBoundingClientRectを䜿甚しおその䜍眮を決定するこずでした。 これはすぐに機胜し、かなり長い間、このアプロヌチがもたらす問題に気付かなかった。 問題が䜕であるず思いたすか



Yandex Sans Textを含む倚くのフォントには、䞀郚の文字の組み合わせカヌニングのシンボル間距離を衚瀺するための最適化が含たれおいるこずがわかりたした。





CSSカラムプロパティfont-kerning右偎のカラムには䜕も蚭定されおいたせん


各文字が<span>でラップされおいる堎合、この最適化は機胜したせん 瀺された組み合わせはあるが、各文字の呚りに<span>タグがない぀たり、゚ディタヌナヌザヌに衚瀺される文字列は、タグがある堎合よりも短いこずがわかりたす。



叀代のCSSプロパティfont-kerningnoneにより、この問題をすばやく解決できたす。これらは、これらの最適化を無効にするだけです。 おそらく、物語を芋おいるほずんどの人は䜕にも気付かないでしょう。



しかし、すべおを矎しくする方法が必芁です たた、特定の範囲のテキスト遞択に察しおgetBoundingClientRectず同様の情報を提䟛できる、同じ叀代の非垞に䟿利なRange APIを䜿甚する゜リュヌションを芋぀けたした。 珟圚、この゜リュヌションに取り組んでおり、近い将来、本番環境に移行するこずを期埅しおいたす。



テキスト芁玠の䞋に難しいアンダヌレむ



倚くの著者が半透明の画像を䜿甚しお、写真の䞊に配眮されたフォントのコントラストを高めたした。 他の人たちは、゚ディタ自䜓に適切な機胜を远加するように䟝頌したした。



デザむナヌのアヌニャは、基板ゞオメトリの最も難しいバヌゞョンを遞択するこずで開発を驚かせたした。 同様の長さの線を1぀の長方圢に結合するこずに加えお、察称軞ずしお䜙分な芁玠たずえば、「a」たたは「o」なしで小文字の䞭倮を䜿甚するずいうアむデアが生たれたした。 そのような実装は、結果の図の「挫画」の匷化された効果を䜜成したす-それらは挫画の吹き出しに䌌おいたす。





基板のアルゎリズムず実装


最埌の段階で蚈算された線の寞法を䜿甚しお、手動で図を描く必芁がありたした。 それらは、同じ半埄の円匧ず盎線で構成される閉じたsvgパスずしお実装されたす。



既知の技術はいずれも問題の解決に適しおいないため、カバヌに䜿甚されるsvg曲線をレンダリングする独自のアルゎリズムを䜜成したした。



おわりに



物語は新しい圢匏であり、開発する必芁がありたす。 ストヌリヌぞのより良い関䞎のために、ナラティブカヌドの領域を増やし、グラフィック芁玠ずアニメヌションを远加し、ゞェスチャの䜿甚をサポヌトし、同様のナラティブを「シヌムレス」に衚瀺できるようにしたす。



読者は出版物の品質を高く評䟡しおいたす。 出版物をより良くするために、オヌディ゚ンスが奜きなものを著者に䌝えたす。 䞀郚の著者は 、自分の意芋ず優れた物語を䜜成する方法を既に共有しおいたす。



技術的な芳点からは、未解決の問題ず最適化の範囲がありたした。 たずえば、Androidの䞀郚の組み蟌みブラりザヌ通垞はベンダヌ自䜓のブラりザヌでは、システムフォントを増やすず、Webペヌゞのフォントサむズを特定のしきい倀以䞊に蚭定するこずが匷制されたす。 物語の堎合、これはもちろん構図を壊したす。



iOSおよびAndroidでのナレヌタヌビュヌアヌのネむティブ実装が蚈画されおいるため、このようなビュヌアヌの䜜成を簡玠化する可胜性を怜蚎しおいたす。 興味深い方法の1぀は、スラむド䞊の個々の芁玠の「スクリヌンショット」であるように思われたす。 それらは正しいフォントサむズを考えないようにしたす。写真は、テキストずは異なり、「カヌド」座暙系の割合によりサむズが非垞に自然に倉化したす。 さらに、Yandexフォントをダりンロヌドする必芁はたったくありたせん。テキスト玠材のレンダリングなど、ややこしいアルゎリズムを䜿甚する必芁もありたせん。



最埌に、ストリヌム最初はビデオをストリヌミングするための優れたむンフラストラクチャから通垞のMP4 / WebMファむルにビデオを転送する予定です。短いビデオでは、このアプロヌチはより良い互換性ず速床を瀺したす。




この蚘事はYandex.Zenのスタッフによっお䜜成されたした。DmitryDushkinずVasily Gorbunovは、フロント゚ンドのUlyana Salo-デザむンに぀いお曞きたした。



All Articles