Ð¡Ð¸Ð½Ñ ÑонизаÑÐ¸Ñ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи ÑлеменÑа Ñ Intersection Observer API
Intersection Observer API позволÑÐµÑ Ð² аÑинÑ
Ñонном Ñежиме ÑведомлÑÑÑ Ð¿Ñиложение о Ñом, ÑÑо какой-Ñо инÑеÑеÑÑÑÑий Ð½Ð°Ñ ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð² Ñой или иной ÑÑепени пеÑекÑÑл ÑодиÑелÑÑкий или дÑÑгой ÑлеменÑ, в Ñом ÑиÑле Document. Ð ÑÑой ÑÑаÑÑе Ð¼Ñ Ð¿Ð¾ÑÑÑоим пÑÐ¸Ð¼ÐµÑ Ð±Ð»Ð¾Ð³Ð°, в коÑоÑом в DOM динамиÑеÑки вÑÑÑаиваÑÑÑÑ ÑекламнÑе блоки. ÐаÑем, Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Intersection Observer API, Ð¼Ñ Ð²ÑÑÑним, ÑколÑко вÑемени показÑваеÑÑÑ ÐºÐ°Ð¶Ð´Ð°Ñ Ð¾ÑделÑÐ½Ð°Ñ Ñеклама полÑзоваÑелÑ. Ðогда ÑÐ°ÐºÐ°Ñ Ñеклама показÑваеÑÑÑ Ð´Ð¾Ð»ÑÑе, Ñем Ð¾Ð´Ð½Ñ Ð¼Ð¸Ð½ÑÑÑ, Ð¼Ñ Ð·Ð°Ð¼ÐµÐ½Ñем ÐµÑ Ð½Ð° новÑÑ.
ХоÑÑ Ð¼Ð½Ð¾Ð³Ð¸Ðµ ÑлеменÑÑ Ð² наÑем пÑимеÑе Ñлабо ÑвÑÐ·Ð°Ð½Ñ Ñ ÑеалÑнÑм миÑом, ÑÑого бÑÐ´ÐµÑ Ð´Ð¾ÑÑаÑоÑно Ð´Ð»Ñ Ð¿Ð¾Ð½Ð¸Ð¼Ð°Ð½Ð¸Ñ API. Ð ÑеалÑном миÑе ÑÑаÑÑи ÑаÑе вÑего оÑлиÑаÑÑÑÑ Ð¼ÐµÐ¶Ð´Ñ Ñобой и Ñ ÑанÑÑÑÑ Ð½Ðµ в клиенÑе, а загÑÑжаÑÑÑÑ Ð¸Ð· Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ ; да и Ñеклама не ÑоÑÑÐ¾Ð¸Ñ Ð¸Ð· одной ÑолÑко ÑÑÑоÑки ÑекÑÑа.
ÐÑÑÑ Ð²Ð°Ð¶Ð½Ð°Ñ Ð¿ÑиÑина, поÑÐµÐ¼Ñ Ð¼Ñ Ð¸ÑполÑзÑем оÑÑлеживание видимоÑÑи ÑекламÑ. ÐÑÑло Ñак, ÑÑо наиболее ÑаÑÑое ÑпоÑÑебление Flash или ÑкÑипÑов в Web Ñекламе нÑжно Ð´Ð»Ñ Ñого, ÑÑÐ¾Ð±Ñ Ð¾ÑениваÑÑ ÑÑÑекÑивноÑÑÑ ÑекламÑ, а знаÑиÑ, ÐµÑ ÑÑоимоÑÑÑ. Ðез Intersection Observer API ÑÑа задаÑа ÑвелаÑÑ Ð±Ñ Ðº повÑемеÑÑÐ½Ð¾Ð¼Ñ Ð¿ÑÐ¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ setTimeout и setInterval Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ оÑделÑной ÑекламÑ. Такие ÑÐµÑ Ð½Ð¸ÐºÐ¸ могÑÑ Ð´ÑамаÑиÑеÑки ÑÑ ÑдÑиÑÑ Ð¿ÑоизводиÑелÑноÑÑÑ ÑÑÑаниÑÑ. ÐÑполÑзование API в ÑÑом ÑлÑÑае Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ð¸Ñ Ð±ÑаÑзеÑÑ Ð²Ð·ÑÑÑ Ð½Ð° ÑÐµÐ±Ñ Ð¾Ð±ÑабоÑÐºÑ Ñложной логики и не ÑолÑко ÑÑкоÑÐ¸Ñ Ð¿Ñиложение, но и ÑпаÑÑÑ Ð²Ð°Ñ Ð¾Ñ Ð¾Ñибок, коÑоÑÑе обÑзаÑелÑно поÑвÑÑÑÑ Ð¿Ñи иÑполÑзовании setTimeout / setInterval.
ÐаÑнÑм!
Создадим ÑайÑ
>СÑÑÑкÑÑÑа пÑиложениÑ: HTML
СÑÑÑкÑÑÑа Web-пÑиложений не оÑÐµÐ½Ñ Ñложна. ÐÑ Ð±Ñдем иÑполÑзоваÑÑ CSS Grid Ð´Ð»Ñ ÑÑилизаÑии и макеÑиÑованиÑ, Ñак ÑÑо вÑÑ Ð´Ð¾ÑÑаÑоÑно оÑевидно:
<div class="wrapper">
<header>
<h1>A Fake Blog</h1>
<h2>Showing Intersection Observer in action!</h2>
</header>
<aside>
<nav>
<ul>
<li><a href="#link1">A link</a></li>
<li><a href="#link2">Another link</a></li>
<li><a href="#link3">One more link</a></li>
</ul>
</nav>
</aside>
<main></main>
</div>
ÐÑо загоÑовка Ð´Ð»Ñ Ð¿ÑиложениÑ. РвеÑÑ
ней ÑаÑÑи пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð½Ð°Ñ
одиÑÑÑ Ð±Ð»Ð¾Ðº <header>. Ðиже - Ð±Ð¾ÐºÐ¾Ð²Ð°Ñ Ð¿Ð°Ð½ÐµÐ»Ñ <aside>, Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð½Ð°Ñ ÑÑÑлками. Ð Ñамом конÑе ÑÑÑÑкÑÑÑÑ - оÑновное Ñело пÑиложениÑ. ÐÑиложение ÑÑаÑÑÑÐµÑ Ñ Ð¿ÑÑÑÑм ÑлеменÑом <main> - он бÑÐ´ÐµÑ Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½ позже Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ JavaScript.
СÑилизаÑÐ¸Ñ Ð¿ÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ CSS
ÐоÑле опÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÑÑÑÑкÑÑÑÑ Ð¿ÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¼Ñ Ð¿ÐµÑÐµÑ Ð¾Ð´Ð¸Ð¼ к ÑÑилизаÑии. ÐавайÑе ÑаÑÑмоÑÑим каждÑй ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð¿Ð¾ оÑделÑноÑÑи.
ÐÑнова
ÐÑ ÑоздаÑм ÑÑили Ð´Ð»Ñ <body> и <main> Ñак, ÑÑÐ¾Ð±Ñ Ð¾Ð¿ÑеделиÑÑ ÑоновÑй ÑÐ²ÐµÑ Ð¸ ÑеÑоÑнÑÑ ÑиÑÑемÑ.
body {
font-family: "Open Sans", "Arial", "Helvetica", sans-serif;
background-color: aliceblue;
}
.wrapper {
display: grid;
grid-template-columns: auto minmax(min-content, 1fr);
grid-template-rows: auto minmax(min-content, 1fr);
max-width: 700px;
margin: 0 auto;
background-color: aliceblue;
}
ÐÐ»ÐµÐ¼ÐµÐ½Ñ Ð¿ÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ <body> ÑконÑигÑÑиÑован Ñак, ÑÑÐ¾Ð±Ñ Ð¸ÑполÑзоваÑÑ Ð¾Ð±ÑеÑпоÑÑебимÑй ÑÑиÑÑ Ð¸Ð· ÑемейÑÑва sans-serif и ÑÐ²ÐµÑ "aliceblue" в каÑеÑÑве Ñона. ÐлаÑÑ "wrapper" обоÑаÑÐ¸Ð²Ð°ÐµÑ Ð²ÑÑ Ð¿Ñиложение, вклÑÑÐ°Ñ header, sidebar и body content.
ÐбÑÑÑка опÑеделÑÐµÑ Ñакже CSS Grid ÑеÑкÑ, как ÑеÑÐºÑ Ð¸Ð· двÑÑ ÐºÐ¾Ð»Ð¾Ð½Ð¾Ðº и двÑÑ ÑÑÑок. ÐеÑÐ²Ð°Ñ ÐºÐ¾Ð»Ð¾Ð½ÐºÐ° (ÑÐ°Ð·Ð¼ÐµÑ Ð²ÑÑиÑлÑеÑÑÑ Ð°Ð²ÑомаÑиÑеÑки на оÑнове конÑенÑа) иÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð±Ð¾ÐºÐ¾Ð²Ð¾Ð¹ панели, а вÑоÑÐ°Ñ ÐºÐ¾Ð»Ð¾Ð½ÐºÐ° (бÑÐ´ÐµÑ Ð¸ÑполÑзоваÑÑÑÑ Ð´Ð»Ñ Ð¾Ñновного ÑодеÑжимого) Ð¸Ð¼ÐµÐµÑ ÑиÑинÑ, доÑÑаÑоÑнÑÑ, ÑÑÐ¾Ð±Ñ Ð²Ð¼ÐµÑÑиÑÑ ÑодеÑжимое и занÑÑÑ Ð²ÑÑ Ð´Ð¾ÑÑÑпнÑÑ Ð¿Ð»Ð¾ÑадÑ.
ÐеÑÐ²Ð°Ñ ÑÑÑока бÑÐ´ÐµÑ Ð¸ÑполÑзована Ð´Ð»Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ° ÑайÑа. РазмеÑÑ ÑÑÑок опÑеделÑÑÑÑÑ ÑÑ Ð¾Ð¶Ð¸Ð¼ обÑазом - ÑÐ°Ð·Ð¼ÐµÑ Ð¿ÐµÑвой вÑÑиÑлÑеÑÑÑ Ð½Ð° оÑнове конÑенÑа, а вÑоÑой - Ð·Ð°Ð½Ð¸Ð¼Ð°ÐµÑ Ð²ÑÑ Ð´Ð¾ÑÑÑпной пÑоÑÑÑанÑÑво, но не менÑÑе ÑазмеÑа, Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾Ð³Ð¾ Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ð° ÑодеÑжимого.
ШиÑина обÑÑÑки заÑикÑиÑована - 700px, Ñак ÑÑо ÐµÑ ÑÐ°Ð·Ð¼ÐµÑ Ð±ÑÐ´ÐµÑ Ñдобен Ð´Ð»Ñ Ð¿ÑедÑÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿ÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð² MDN.
The wrapper's width is fixed at 700px so that it will fit in the available space when presented inline on MDN below.
Ðаголовок
Ðаголовок доÑÑаÑоÑно пÑоÑÑ, Ñак как в наÑем пÑимеÑе он ÑодеÑÐ¶Ð¸Ñ Ð½ÐµÐ±Ð¾Ð»ÑÑой ÑекÑÑ.
header {
grid-column: 1 / -1;
grid-row: 1;
background-color: aliceblue;
}
ÐнаÑение grid-row Ñавно 1, Ñак как Ð¼Ñ Ñ
оÑим помеÑÑиÑÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²Ð¾Ðº в веÑÑ
нÑÑ ÑÑÑÐ¾ÐºÑ ÑеÑоÑной ÑиÑÑемÑ. Ðолее инÑеÑеÑно иÑполÑзование grid-column; ÐÑ ÑказÑваем здеÑÑ, ÑÑо блок Ð·Ð°Ð½Ð¸Ð¼Ð°ÐµÑ Ð¿ÑоÑÑÑанÑÑво Ñ Ð¿ÐµÑвой колонки до пеÑвой Ñ ÐºÐ¾Ð½Ñа (Ñо еÑÑÑ Ð¿Ð¾Ñледней).
ÐÐ¾ÐºÐ¾Ð²Ð°Ñ Ð¿Ð°Ð½ÐµÐ»Ñ
ÐÐ¾ÐºÐ¾Ð²Ð°Ñ Ð¿Ð°Ð½ÐµÐ»Ñ Ð¸ÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ð° ÑÑÑлок на дÑÑгие ÑÑÑаниÑÑ Ð¿ÑиложениÑ. Ðи одна из ниÑ
не бÑÐ´ÐµÑ ÑабоÑаÑÑ Ð² наÑем пÑимеÑе. ÐÑÑ Ð±Ð¾ÐºÐ¾Ð²Ð°Ñ Ð¿Ð°Ð½ÐµÐ»Ñ Ð½Ñжна, ÑÑÐ¾Ð±Ñ Ð¿ÑоÑÑо пÑиблизиÑÑ Ð²Ð½ÐµÑний вид пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ðº ÑеалÑÐ½Ð¾Ð¼Ñ Ð±Ð»Ð¾Ð³Ñ. ÐÐ¾ÐºÐ¾Ð²Ð°Ñ Ð¿Ð°Ð½ÐµÐ»Ñ ÑоздаÑÑÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÑлеменÑа <aside>.
aside {
grid-column: 1;
grid-row: 2;
background-color: cornsilk;
padding: 5px 10px;
}
aside ul {
padding-left: 0;
}
aside ul li {
list-style: none;
}
aside ul li a {
text-decoration: none;
}
Ðажно оÑмеÑиÑÑ, ÑÑо знаÑение grid-column здеÑÑ ÑÑÑановлено в 1 Ð´Ð»Ñ Ñого, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð¼ÐµÑÑиÑÑ Ð¿Ð°Ð½ÐµÐ»Ñ Ð² левÑÑ ÑаÑÑÑ ÑкÑана. ÐÑли Ð²Ñ Ð¿Ð¾Ð¼ÐµÐ½ÑеÑе ÑÑо знаÑение на "-1", Ñо Ð¿Ð°Ð½ÐµÐ»Ñ Ð¿ÐµÑемеÑÑиÑÑÑ Ð²Ð¿Ñаво, однако, в ÑÑом ÑлÑÑае, вам понадобиÑÑÑ Ð½ÐµÐ¼Ð½Ð¾Ð³Ð¾ измениÑÑ ÑÑили внÑÑÑенниÑ
ÑлеменÑов. ÐнаÑение grid-row Ñавно 2, ÑÑÐ¾Ð±Ñ Ð±Ð¾ÐºÐ¾Ð²Ð°Ñ Ð¿Ð°Ð½ÐµÐ»Ñ Ð·Ð°Ð½Ñла облаÑÑÑ Ð²Ð´Ð¾Ð»Ñ Ð¾Ð±Ð»Ð°ÑÑи конÑенÑа.
ÐблаÑÑÑ ÐºÐ¾Ð½ÑенÑа
ÐонÑÐµÐ½Ñ Ð±ÑÐ´ÐµÑ ÑодеÑжаÑÑÑÑ Ð² ÑлеменÑе <main>.
main {
grid-column: 2;
grid-row: 2;
margin: 0;
margin-left: 16px;
font-size: 16px;
}
ÐÐ»Ð°Ð²Ð½Ð°Ñ Ð¾ÑобенноÑÑÑ Ð·Ð´ÐµÑÑ - конÑÐµÐ½Ñ Ð·Ð°Ð½Ð¸Ð¼Ð°ÐµÑ Ð²ÑоÑÑÑ ÐºÐ¾Ð»Ð¾Ð½ÐºÑ Ð¸ вÑоÑÑÑ ÑÑÑокÑ.
СÑаÑÑи
ÐÐ°Ð¶Ð´Ð°Ñ ÑÑаÑÑÑ ÑоÑÑÐ¾Ð¸Ñ Ð¸Ð· ÑлеменÑа <article>:
article {
background-color: white;
padding: 6px;
}
article:not(:last-child) {
margin-bottom: 8px;
}
article h2 {
margin-top: 0;
}
ÐÑи ÑÑили ÑоздаÑÑ Ð¾Ð±Ð»Ð°ÑÑÑ Ñ Ð±ÐµÐ»Ñм Ñоном Ñ Ð½ÐµÐ±Ð¾Ð»ÑÑими оÑÑÑÑпами как внÑÑÑи облаÑÑи, Ñак и Ð¼ÐµÐ¶Ð´Ñ Ð¾Ð±Ð»Ð°ÑÑÑми.
РекламнÑе блоки
ÐаконеÑ, ÑекламнÑе блоки. ÐÑжно замеÑиÑÑ, ÑÑо каждÑй оÑделÑнÑй ÑекламнÑй блок Ð¼Ð¾Ð¶ÐµÑ Ð¸Ð·Ð¼ÐµÐ½ÑÑÑ Ñвои ÑÑили динамиÑеÑки (Ð¼Ñ Ñвидим ÑÑо позже):
.ad {
height: 96px;
padding: 6px;
border-color: #555;
border-style: solid;
border-width: 1px;
}
.ad:not(:last-child) {
margin-bottom: 8px;
}
.ad h2 {
margin-top: 0;
}
.ad div {
position: relative;
float: right;
padding: 0 4px;
height: 20px;
width: 120px;
font-size: 14px;
bottom: 30px;
border: 1px solid black;
background-color: rgba(255, 255, 255, 0.5);
}
ÐдеÑÑ Ð½ÐµÑ Ð½Ð¸ÐºÐ°ÐºÐ¾Ð¹ магии. ÐÑоÑÑой CSS.
СовмеÑаем Ñ JavaScript
ÐеÑейдÑм к JavaScript-кодÑ, коÑоÑÑй вÑÑ Ð¾Ð¶Ð¸Ð²Ð¸Ñ. ÐаÑнÑм Ñ Ð³Ð»Ð¾Ð±Ð°Ð»ÑнÑÑ Ð¿ÐµÑеменнÑÑ :
let contentBox;
let nextArticleID = 1;
let visibleAds = new Set();
let previouslyVisibleAds = null;
let adObserver;
let refreshIntervalID = 0;
ÐÐ¾Ñ ÑÑо здеÑÑ Ð¸ÑполÑзÑеÑÑÑ:
contentBox-
СÑÑлка на ÑлеменÑ
<main>. ÐÑо меÑÑо, кÑда Ð¼Ñ Ð±Ñдем вÑÑавлÑÑÑ ÑÑаÑÑи и ÑекламÑ. nextArticleID-
ÐÐ°Ð¶Ð´Ð°Ñ ÑÑаÑÑÑ Ð¿Ð¾Ð»ÑÑÐ°ÐµÑ ÑникалÑнÑй ÑиÑÑовой ID. ÐÑа пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»ÑÐµÑ Ð¿Ð¾Ð½ÑÑÑ, какой ÑледÑÑÑий ID иÑполÑзоваÑÑ.
visibleAds-
SetиÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð¾ÑÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ ÑекÑÑÐ¸Ñ Ð²Ð¸Ð´Ð¸Ð¼ÑÑ Ð½Ð° ÑкÑане ÑекламнÑÑ Ð±Ð»Ð¾ÐºÐ¾Ð². previouslyVisibleAds-
ÐÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð²Ñеменного Ñ ÑÐ°Ð½ÐµÐ½Ð¸Ñ ÑпиÑка ÑекламнÑÑ Ð±Ð»Ð¾ÐºÐ¾Ð² в Ñо вÑемÑ, как докÑÐ¼ÐµÐ½Ñ Ð½ÐµÐ²Ð¸Ð´Ð¸Ð¼ (напÑимеÑ, еÑли полÑзоваÑÐµÐ»Ñ Ð¿ÐµÑеклÑÑилÑÑ Ð½Ð° дÑÑгой Ñаб)
adObserver-
СодеÑÐ¶Ð¸Ñ ÑкземплÑÑ
IntersectionObserver, иÑполÑзÑемÑй Ð´Ð»Ñ Ð²ÑÑиÑÐ»ÐµÐ½Ð¸Ñ Ð½Ð°Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ÑекламнÑÑ Ð±Ð»Ð¾ÐºÐ¾Ð² и гÑÐ°Ð½Ð¸Ñ ÑлеменÑа<main>. refreshIntervalID-
ÐеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð´Ð»Ñ Ñ ÑÐ°Ð½ÐµÐ½Ð¸Ñ ID инÑеÑвала, коÑоÑÑй возвÑаÑаеÑÑÑ ÑÑнкÑией
setInterval(). ÐÑÐ¾Ñ Ð¸Ð½ÑеÑвал бÑÐ´ÐµÑ Ð¸ÑполÑзоваÑÑÑÑ Ð´Ð»Ñ Ð·Ð°Ð¿ÑÑка пеÑиодиÑеÑÐºÐ¸Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ð¹ ÑекламнÑÑ Ð±Ð»Ð¾ÐºÐ¾Ð².
УÑÑановка
ÐÐ»Ñ Ð¿ÐµÑвиÑного запÑÑка пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¼Ñ Ð²Ñзовем ÑÑнкÑÐ¸Ñ startup():
window.addEventListener("load", startup, false);
function startup() {
contentBox = document.querySelector("main");
document.addEventListener("visibilitychange", handleVisibilityChange, false);
let observerOptions = {
root: null,
rootMargin: "0px",
threshold: [0.0, 0.75],
};
adObserver = new IntersectionObserver(intersectionCallback, observerOptions);
buildContents();
refreshIntervalID = window.setInterval(handleRefreshInterval, 1000);
}
ÐнаÑале Ð¼Ñ Ð¿Ð¾Ð»ÑÑаем ÑÐ»ÐµÐ¼ÐµÐ½Ñ <main>, в коÑоÑÑй можем вÑÑавлÑÑÑ ÑодеÑжимое. ÐаÑем Ð¼Ñ ÑÑÑанавливаем обÑабоÑÑик на ÑобÑÑие . ÐÑо ÑобÑÑие ÑÑабаÑÑваеÑ, когда докÑÐ¼ÐµÐ½Ñ Ð¼ÐµÐ½ÑÐµÑ ÑоÑÑоÑние Ð¼ÐµÐ¶Ð´Ñ Ð²Ð¸Ð´Ð¸Ð¼/невидим, напÑимеÑ, когда полÑзоваÑÐµÐ»Ñ Ð¿ÐµÑеклÑÑаеÑÑÑ Ð¼ÐµÐ¶Ð´Ñ Ñабами. Intersection Observer API не должен заÑÑиÑÑваÑÑ Ð¿ÐµÑеÑеÑение Ñ ÑлеменÑом Main, еÑли полÑзоваÑÐµÐ»Ñ Ð½Ðµ бÑÐ´ÐµÑ Ð² ÑÑо вÑÐµÐ¼Ñ ÑмоÑÑеÑÑ Ð½Ð° вкладкÑ. Таким обÑазом, Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¾ÑÑанавливаÑÑ Ð½Ð°Ñи ÑаймеÑÑ ÐºÐ°Ð¶Ð´Ñй Ñаз, когда полÑзоваÑÐµÐ»Ñ ÑÑ
Ð¾Ð´Ð¸Ñ Ñо ÑÑÑаниÑÑ. С помоÑÑÑ ÑÑого обÑабоÑÑика.
ÐаÑем Ð¼Ñ ÑÑÑанавливаем паÑамеÑÑÑ Ð´Ð»Ñ IntersectionObserver. ÐаÑамеÑÑÑ Ð¾Ð¿ÑеделÑÑÑ, ÑÑо IntersectionObserver должен оÑÑлеживаÑÑ Ð¿ÐµÑекÑÑÑÐ¸Ñ Ñ Ð¾Ð±Ð»Ð°ÑÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи докÑменÑа (паÑамеÑÑ root в знаÑении null). У Ð½Ð°Ñ Ð½ÐµÑ Ð¾ÑÑÑÑпов Ð´Ð»Ñ Ð¼Ð¾Ð´Ð¸ÑикаÑии коÑневой облаÑÑи; Ð¼Ñ Ñ
оÑим оÑÑлеживаÑÑ Ñовпадение гÑÐ°Ð½Ð¸Ñ ÑлеменÑов и видимого докÑменÑа именно Ð´Ð»Ñ Ñелей обнаÑÑÐ¶ÐµÐ½Ð¸Ñ Ð¿ÐµÑекÑÑÑий.
ÐаÑамеÑÑ "поÑог" (threshold) ÑодеÑÐ¶Ð¸Ñ Ð¼Ð°ÑÑив Ñо знаÑениÑми 0.0 и 0.75; ÐÑо заÑÑÐ°Ð²Ð¸Ñ Ð¾Ð±ÑабоÑÑик вÑзÑваÑÑÑÑ ÐºÐ°Ð¶Ð´Ñй Ñаз, когда Ñелевой ÑÐ»ÐµÐ¼ÐµÐ½Ñ ÑÑановиÑÑÑ Ð¿Ð¾Ð»Ð½Ð¾ÑÑÑÑ Ð¾Ð±ÑÑнÑÑ Ð¸Ð»Ð¸ ÑолÑко наÑÐ¸Ð½Ð°ÐµÑ Ð²ÑÑ
одиÑÑ Ð¸Ð· Ð·Ð¾Ð½Ñ Ð¿ÐµÑекÑÑÑÐ¸Ñ (коÑÑÑиÑÐ¸ÐµÐ½Ñ Ð¿ÐµÑекÑÑÑÐ¸Ñ 0.0) или пÑоÑ
Ð¾Ð´Ð¸Ñ Ð¿Ð¾Ñог в 75% видимоÑÑи в обоиÑ
напÑавлениÑÑ
(коÑÑÑиÑÐ¸ÐµÐ½Ñ Ð¿ÐµÑекÑÑÑÐ¸Ñ 0.75).
ÐаблÑдаÑÐµÐ»Ñ adObserver ÑоздаÑÑÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑоÑа IntersectionObserver. РаÑгÑменÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑоÑа Ð¼Ñ Ð¿ÐµÑедаÑм колбÑк-ÑÑнкÑÐ¸Ñ (intersectionCallback) и Ñанее опÑеделÑннÑй обÑÐµÐºÑ Ð¿Ð°ÑамеÑÑов.
ÐоÑле ÑÑого Ð¼Ñ Ð²ÑзÑваем ÑÑнкÑÐ¸Ñ buildContents(). ÐÑ Ð¼Ñ Ð½Ð°Ð¿Ð¸Ñем ÑÑÑÑ Ð¿Ð¾Ð·Ð¶Ðµ. ФÑнкÑÐ¸Ñ Ð³ÐµÐ½ÐµÑиÑÑÐµÑ Ð¸ вÑÑавлÑÐµÑ Ð² конÑÐµÐ¹Ð½ÐµÑ ÑÑаÑÑи и ÑекламнÑе блоки.
РконÑе Ð¼Ñ ÑÑÑанавливаем инÑеÑвал, коÑоÑÑй каждÑÑ ÑекÑÐ½Ð´Ñ Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑ Ð¿ÑовеÑÐºÑ - нÑжно ли ÑÑо-Ñо обновиÑÑ. Ðам Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ вÑоÑое обновление, Ñак как в каждом оÑделÑном Ñекламном блоке Ð¼Ñ Ð¿Ð¾ÐºÐ°Ð·Ñваем ÑаймеÑ. Ð ÑеалÑном пÑиложении ÑÑо не понадобиÑÑÑ.
ÐбÑабоÑка Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи докÑменÑа
ÐавайÑе ÑаÑÑмоÑÑим обÑабоÑÑик ÑобÑÑÐ¸Ñ . ÐÑо ÑобÑÑие ÑÑабаÑÑваеÑ, когда докÑÐ¼ÐµÐ½Ñ ÑÑановиÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼ или невидим. Ðак пÑавило, ÑÑо ÑлÑÑаеÑÑÑ, когда полÑзоваÑÐµÐ»Ñ Ð¿ÐµÑеклÑÑаеÑÑÑ Ð¼ÐµÐ¶Ð´Ñ Ñабами. Так как Intersection Observer оÑÑÐ»ÐµÐ¶Ð¸Ð²Ð°ÐµÑ ÑолÑко пеÑекÑÑÑÐ¸Ñ ÑлеменÑа Ñ ÐºÐ¾ÑневÑм ÑлеменÑом, нам Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ оÑделÑно позабоÑиÑÑÑÑ Ð¾ деÑекÑии видимоÑÑи докÑменÑа. ÐÐ»Ñ ÑÑого Ð¼Ñ Ð¸ÑполÑзÑем Page Visibility API.
function handleVisibilityChange() {
if (document.hidden) {
if (!previouslyVisibleAds) {
previouslyVisibleAds = visibleAds;
visibleAds = [];
previouslyVisibleAds.forEach(function (adBox) {
updateAdTimer(adBox);
adBox.dataset.lastViewStarted = 0;
});
}
} else {
previouslyVisibleAds.forEach(function (adBox) {
adBox.dataset.lastViewStarted = performance.now();
});
visibleAds = previouslyVisibleAds;
previouslyVisibleAds = null;
}
}
Так как ÑобÑÑие Ñамо по Ñебе не ÑказÑваеÑ, ÑÑал ли докÑÐ¼ÐµÐ½Ñ Ð²Ð¸Ð´Ð¸Ð¼Ñм или, наобоÑоÑ, невидимÑм, Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð²ÑÑÑнÑÑ Ð¿ÑовеÑиÑÑ ÑвойÑÑво document.hidden. Ð ÑеоÑии, ÑÑо ÑобÑÑие Ð¼Ð¾Ð¶ÐµÑ ÑÑабоÑаÑÑ Ð½ÐµÑколÑко Ñаз, поÑÑÐ¾Ð¼Ñ Ð½Ð°Ð¼ нÑжно обÑабаÑÑваÑÑ ÑолÑко Ñе ÑекламнÑе блоки, ÑÑÑÑ ÐºÐ¾ÑоÑÑÑ
еÑÑ Ð½Ðµ бÑл пÑиоÑÑановлен.
ÐÐ»Ñ Ð¾ÑÑановки ÑаймеÑов нам нÑжно ÑдалиÑÑ ÑÑÑлки на ÑекламнÑе блоки из коллекÑии visibleAds и помеÑиÑÑ Ð¸Ñ
как неакÑивнÑе. ЧÑÐ¾Ð±Ñ ÑÑо ÑделаÑÑ, Ð¼Ñ Ð½Ð°Ñинаем Ñ ÑоÑ
ÑÐ°Ð½ÐµÐ½Ð¸Ñ ÑÑÑлок на ÑекÑÑие видимÑе ÑлеменÑÑ Ð² пеÑеменнÑÑ previouslyVisibleAds. ÐÑо нÑжно, ÑÑÐ¾Ð±Ñ Ð² далÑнейÑем можно бÑло воÑÑÑановиÑÑ ÑÑÑÑÑики Ð´Ð»Ñ ÑÑиÑ
блоков. Так Ð¼Ñ ÑказÑваем пÑиложениÑ, ÑÑо ÑÑÑ ÑÐµÐºÐ»Ð°Ð¼Ñ Ð½Ðµ надо ÑÑиÑаÑÑ Ð°ÐºÑивной. ÐаÑем, еÑли полÑзоваÑÐµÐ»Ñ Ð²ÐµÑнÑлÑÑ Ð² докÑменÑ, Ð¼Ñ Ð²ÑзÑваем ÑÑнкÑÐ¸Ñ updateAdTimer() Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ оÑложенного ÑлеменÑа. ÐÑа ÑÑнкÑÐ¸Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÑÐµÑ Ð¾Ð±Ñее вÑÐµÐ¼Ñ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи ÑлеменÑа. ÐоÑле ÑÑого Ð¼Ñ Ð¿ÑиÑваиваем пеÑеменной dataset.lastViewStarted знаÑение 0, ÑÑо ознаÑаеÑ, ÑÑо ÑÐ°Ð¹Ð¼ÐµÑ Ð½Ðµ запÑÑен.
ÐÑли докÑÐ¼ÐµÐ½Ñ ÑÑал видимÑм, Ð¼Ñ Ð²ÑполнÑем обÑаÑнÑй пÑоÑеÑÑ: ÑнаÑала Ð¼Ñ Ð¿ÑоÑ
одим ÑеÑез коллекÑÐ¸Ñ previouslyVisibleAds. ÐÐ»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ÑлеменÑа Ð¼Ñ Ð¿ÑиÑваиваем dataset.lastViewStarted знаÑение, ÑооÑвеÑÑÑвÑÑÑее ÑекÑÑÐµÐ¼Ñ Ð²Ñемени докÑменÑа (в миллиÑекÑндаÑ
Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñа ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð´Ð¾ÐºÑменÑа). ÐÑо вÑÐµÐ¼Ñ Ð¼Ð¾Ð¶Ð½Ð¾ ÑзнаÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Ð¼ÐµÑода performance.now(). ÐаÑем Ð¼Ñ Ð¿ÑиÑваиваем пеÑеменной visibleAds закеÑиÑованное Ñанее знаÑение previouslyVisibleAds, Ñ Ð¾Ð±Ð½Ñлением поÑледней пеÑеменной. ТепеÑÑ ÑекламнÑе блоки пеÑезапÑÑÐµÐ½Ñ Ð¸ наÑÑÑоенÑ, Ñак ÑÑо вÑÐµÐ¼Ñ Ð¿ÑоÑÑÐ¾Ñ Ð½Ðµ бÑÐ´ÐµÑ ÑÑиÑÑваÑÑÑÑ.
ÐбÑабоÑÑик изменений наложениÑ
ÐÑи каждой иÑеÑаÑии в бÑаÑзеÑном event loop, каждÑй наблÑдаÑÐµÐ»Ñ IntersectionObserver пÑовеÑÑеÑ, не пÑоÑÑл ли какой-либо из ÑлеменÑов-Ñелей ÑеÑез поÑоговÑе знаÑÐµÐ½Ð¸Ñ Ð½Ð°Ð±Ð»ÑдаÑелÑ. ÐÐ»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ наблÑдаÑÐµÐ»Ñ ÑпиÑок ÑакиÑ
Ñелей ÑобиÑаеÑÑÑ Ð² один ÑпиÑок и оÑпÑавлÑеÑÑÑ Ð² колбÑк-ÑÑнкÑÐ¸Ñ Ð½Ð°Ð±Ð»ÑдаÑелÑ. ÐаждÑй ÑÐ»ÐµÐ¼ÐµÐ½Ñ ÑпиÑка - ÑÑо IntersectionObserverEntry обÑекÑ. РнаÑем пÑиложении intersectionCallback() вÑглÑÐ´Ð¸Ñ Ñак:
function intersectionCallback(entries) {
entries.forEach(function (entry) {
let adBox = entry.target;
if (entry.isIntersecting) {
if (entry.intersectionRatio >= 0.75) {
adBox.dataset.lastViewStarted = entry.time;
visibleAds.add(adBox);
}
} else {
visibleAds.delete(adBox);
if (
entry.intersectionRatio === 0.0 &&
adBox.dataset.totalViewTime >= 60000
) {
replaceAd(adBox);
}
}
});
}
Ðак Ð¼Ñ Ñпоминали Ñанее, колбÑк-ÑÑнкÑÐ¸Ñ IntersectionObserver полÑÑÐ°ÐµÑ Ð½Ð° вÑ
од маÑÑив ÑлеменÑов, коÑоÑÑе акÑивиÑовали наблÑдаÑелÑ. РнаÑей ÑÑнкÑии Ð¼Ñ Ð¸ÑеÑиÑÑемÑÑ Ð¿Ð¾ ÑÑÐ¾Ð¼Ñ Ð¼Ð°ÑÑивÑ. ÐÑли ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð¿ÐµÑеÑекаеÑÑÑ Ñ ÐºÐ¾ÑневÑм ÑлеменÑом, Ð¼Ñ Ð·Ð½Ð°ÐµÐ¼, ÑÑо он ÑÑал видимÑм. ÐÑли он ÑÑановиÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ñм более, Ñем на 75%, Ð¼Ñ ÑÑиÑаем, ÑÑо Ñеклама видима и Ð¼Ñ Ð·Ð°Ð¿ÑÑкаем ÑаймеÑ, вÑÑÑавлÑÑ Ð·Ð½Ð°Ñение dataset.lastViewStarted ÑавнÑм вÑемени Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ð°ÑамеÑÑа пеÑекÑÑÑÐ¸Ñ entry.time. ÐаÑем Ð¼Ñ Ð´Ð¾Ð±Ð°Ð²Ð»Ñем ÑекламнÑй блок в Ð½Ð°Ð±Ð¾Ñ visibleAds.
ÐÑли ÑекламнÑй блок ÑÑ
Ð¾Ð´Ð¸Ñ Ð¸Ð· Ð·Ð¾Ð½Ñ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи, Ð¼Ñ ÑдалÑем его из Ð½Ð°Ð±Ð¾Ñ Ð²Ð¸Ð´Ð¸Ð¼ÑÑ
ÑлеменÑов. ÐаÑем, в завиÑимоÑÑи Ð¾Ñ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ entry.ratio, Ð¼Ñ Ð»Ð¸Ð±Ð¾ менÑем ÑекламÑ, либо ÑÑавим на паÑзÑ. Так, еÑли знаÑение Ñавно 0.0 и Ñеклама Ñже бÑла видна минимÑм минÑÑÑ, Ð¼Ñ Ð²ÑзÑваем ÑÑнкÑÐ¸Ñ replaceAd() . Ð ÑÑом ÑлÑÑае полÑзоваÑÐµÐ»Ñ Ð²Ð¸Ð´Ð¸Ñ ÑазнÑе ÑекламнÑе блоки, но Ñама Ñеклама менÑеÑÑÑ Ð½ÐµÐ·Ð°Ð¼ÐµÑно Ð´Ð»Ñ Ð¿Ð¾Ð»ÑзоваÑелÑ.
ÐбÑабоÑка пеÑиодиÑеÑкий ÑобÑÑий
ÐаждÑÑ ÑекÑÐ½Ð´Ñ Ñ Ð½Ð°Ñ ÑÑабаÑÑÐ²Ð°ÐµÑ Ð¸Ð½ÑеÑвал handleRefreshInterval(), коÑоÑÑй Ð¼Ñ Ð·Ð°Ð´Ð°Ð»Ð¸ в ÑÑнкÑии startup(). ÐÐ»Ð°Ð²Ð½Ð°Ñ Ð·Ð°Ð´Ð°Ñа ÑÑого инÑеÑвала - обновлÑÑÑ ÑаймеÑÑ ÐºÐ°Ð¶Ð´ÑÑ ÑекÑÐ½Ð´Ñ Ð¸ пеÑеÑиÑовÑваÑÑ Ð·Ð½Ð°Ñение ÑаймеÑов.
function handleRefreshInterval() {
let redrawList = [];
visibleAds.forEach(function (adBox) {
let previousTime = adBox.dataset.totalViewTime;
updateAdTimer(adBox);
if (previousTime != adBox.dataset.totalViewTime) {
redrawList.push(adBox);
}
});
if (redrawList.length) {
window.requestAnimationFrame(function (time) {
redrawList.forEach(function (adBox) {
drawAdTimer(adBox);
});
});
}
}
ÐаÑÑив redrawList иÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ñ
ÑÐ°Ð½ÐµÐ½Ð¸Ñ ÑпиÑка ÑекламнÑÑ
блоков, коÑоÑÑе Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð¿ÐµÑеÑиÑÐ¾Ð²Ð°Ð½Ñ Ð² ÑледÑÑÑем Ñикле пеÑеÑиÑовки. ÐÑо нÑжно, Ñак как ÑаймеÑÑ ÑекÑÑиÑ
ÑекламнÑÑ
блоков не вÑегда ÑовпадаÑÑ Ñ ÑеалÑнÑми Ñаймингами из-за пÑоÑиÑ
ÑиÑÑемнÑÑ
пÑоÑеÑÑов. Ðли из-за Ñого, ÑÑо Ð²Ñ Ñказали в каÑеÑÑве инÑеÑвала пÑомежÑÑок не в 1000мÑ.
ÐаÑем, Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ видимого Ñекламного блока, Ð¼Ñ ÑоÑ
ÑанÑем знаÑение dataset.totalViewTime (колиÑеÑÑво миллиÑекÑнд, коÑоÑое ÑекÑÑÐ°Ñ Ñеклама бÑла видима Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñа поÑледнего Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÑÑого знаÑениÑ). ÐоÑле ÑÑого вÑзÑваем ÑÑнкÑÐ¸Ñ updateAdTimer() Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ñемени. ÐÑли оно изменилоÑÑ, Ð¼Ñ Ð²ÑÑавлÑем ÑекламнÑй блок в ÑпиÑок redrawList. Таким обÑазом, пÑи обÑабоÑке ÑледÑÑÑего кадÑа пÑиложение знаеÑ, ÑÑо нÑжно пеÑеÑиÑоваÑÑ.
Ð, наконеÑ, еÑли ÑÑÑеÑÑвÑÐµÑ Ñ
оÑÑ Ð¾Ð´Ð¸Ð½ ÑлеменÑ, коÑоÑÑй нÑжно пеÑеÑиÑоваÑÑ, Ð¼Ñ Ð±Ñдем иÑполÑзÑем requestAnimationFrame(), ÑÑÐ¾Ð±Ñ Ð¾ÑложиÑÑ Ð¾ÑÑиÑÐ¾Ð²ÐºÑ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ÑлеменÑа на ÑÐ¾Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ, когда бÑÐ´ÐµÑ ÑоÑмиÑоваÑÑÑÑ ÑледÑÑÑий кадÑ.
Ðбновление ÑаймеÑа видимоÑÑи ÑекламÑ
Ранее Ð¼Ñ Ñже видели, ÑÑо еÑли нам нÑжно обновиÑÑ Ð¾Ð±Ñее вÑÐµÐ¼Ñ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи ÑÐµÐºÐ»Ð°Ð¼Ñ - Ð¼Ñ Ð²ÑзÑваем ÑÑнкÑÐ¸Ñ updateAdTimer(). ÐÑа ÑÑнкÑÐ¸Ñ Ð¿ÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð² каÑеÑÑве аÑгÑменÑа обÑÐµÐºÑ HTMLDivElement.
function updateAdTimer(adBox) {
let lastStarted = adBox.dataset.lastViewStarted;
let currentTime = performance.now();
if (lastStarted) {
let diff = currentTime - lastStarted;
adBox.dataset.totalViewTime =
parseFloat(adBox.dataset.totalViewTime) + diff;
}
adBox.dataset.lastViewStarted = currentTime;
}
ÐÐ»Ñ Ð¾ÑÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð²Ñемени видимоÑÑи ÑлеменÑа Ð¼Ñ Ð¸ÑполÑзÑем два data-аÑÑибÑÑа на каждом Ñекламном блоке:
lastViewStarted-
ÐÑÐµÐ¼Ñ Ð² миллиÑекÑÐ½Ð´Ð°Ñ Ð¾ÑноÑиÑелÑно пеÑвонаÑалÑной загÑÑзки ÑÑÑаниÑÑ Ð´Ð¾ моменÑа, когда ÑÑÑÑÑик Ñекламного блока бÑл обновлÑн или блок ÑÑал невидим. ÐÑли знаÑение Ñавно нÑÐ»Ñ - блок не бÑл видим в поÑледний Ñаз, когда пÑовеÑÑлÑÑ.
totalViewTime-
ÐбÑее вÑÐµÐ¼Ñ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи Ñекламного блока.
ÐнаÑение ÑÑиÑ
аÑÑибÑÑов можно полÑÑиÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ HTMLElement.dataset. ÐнаÑÐµÐ½Ð¸Ñ - ÑÑÑоки, но Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе конвеÑÑиÑоваÑÑ Ð¸Ñ
в ÑиÑла. ФакÑиÑеÑки, JavaScript Ð´ÐµÐ»Ð°ÐµÑ ÑÑо авÑомаÑиÑеÑки, но нам вÑÑ Ñавно пÑидÑÑÑÑ Ð² одном меÑÑе ÑделаÑÑ ÑÑо вÑÑÑнÑÑ.
ФÑнкÑÐ¸Ñ Ð½Ð°ÑинаеÑÑÑ Ñ Ð²ÑÑÑÐ½ÐµÐ½Ð¸Ñ Ð²Ñемени, когда пÑоиÑÑ
одила поÑледнÑÑ Ð¿ÑовеÑка видимоÑÑи ÑÐµÐºÐ»Ð°Ð¼Ñ (adBox.dataset.lastViewStarted). ÐÑ Ñакже полÑÑаем ÑекÑÑее вÑÐµÐ¼Ñ Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñа ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð´Ð¾ÐºÑменÑа Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ performance.now() currentTime.
ÐÑли вÑÐµÐ¼Ñ Ð¿Ð¾Ñледней пÑовеÑки lastStarted не Ñавно нÑÐ»Ñ - ÑÑо знаÑиÑ, ÑÑо ÑÐ°Ð¹Ð¼ÐµÑ ÑейÑÐ°Ñ Ñже запÑÑен. Ð ÑÑом ÑлÑÑае Ð¼Ñ Ð²ÑÑиÑлÑем ÑазниÑÑ Ð¼ÐµÐ¶Ð´Ñ ÑекÑÑим вÑеменем и вÑеменем ÑÑаÑÑа пÑовеÑки. ÐÑо знаÑение покажеÑ, ÑколÑко Ñеклама бÑла видима Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñа поÑледнего ÑÑаÑÑа деÑекÑии. ÐаÑем ÑÑо знаÑение пÑибавлÑем к Ñже имеÑÑемÑÑÑ totalViewTime. ÐбÑаÑиÑе внимание не вÑзов parseFloat(): Ñак как вÑе знаÑÐµÐ½Ð¸Ñ Ð¸Ð· Dataset - ÑÑÑоки, JavaScript пÑÑаеÑÑÑ ÑоединиÑÑ ÑÑÑоки вмеÑÑо Ñого, ÑÑÐ¾Ð±Ñ Ð¿ÑоÑÑммиÑоваÑÑ ÑиÑла.
РконÑе Ð¼Ñ Ð¿ÑиÑваиваем lastViewStarted ÑекÑÑее знаÑение. ÐÑо делаеÑÑÑ Ð²Ð½Ðµ завиÑимоÑÑи Ð¾Ñ Ñого, бÑл ли ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð²Ð¸Ð´Ð¸Ð¼ во вÑÐµÐ¼Ñ Ð²Ñзова ÑÑнкÑии или Ð½ÐµÑ - ÑÑо позволÑÐµÑ ÑаймеÑÑ ÑекламнÑÑ
блоков ÑÑабаÑÑваÑÑ Ð²Ñегда, когда ÑÑа ÑÑнкÑÐ¸Ñ Ð²ÑзÑваеÑÑÑ. ÐÑо Ð¸Ð¼ÐµÐµÑ ÑмÑÑл, поÑÐ¾Ð¼Ñ ÑÑо вÑзов Ð¼Ð¾Ð¶ÐµÑ ÑÑабоÑаÑÑ Ñовно в ÑÐ¾Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ, когда Ñеклама ÑолÑко поÑвилаÑÑ.
ÐоказÑваем ÑÐ°Ð¹Ð¼ÐµÑ ÑекламÑ
ÐнÑÑÑи каждого Ñекламного блока Ð¼Ñ Ð¾ÑобÑажаем ÑекÑÑее знаÑение обÑего вÑемени видимоÑÑи в ÑоÑмаÑе мин:Ñек. ÐÐ»Ñ ÑÑого Ð¼Ñ Ð¿ÐµÑедаÑм в ÑÑнкÑÐ¸Ñ drawAdTimer конÑейнеÑ:
function drawAdTimer(adBox) {
let timerBox = adBox.querySelector(".timer");
let totalSeconds = adBox.dataset.totalViewTime / 1000;
let sec = Math.floor(totalSeconds % 60);
let min = Math.floor(totalSeconds / 60);
timerBox.innerText = min + ":" + sec.toString().padStart(2, "0");
}
ФÑнкÑÐ¸Ñ Ð½Ð°Ñ
Ð¾Ð´Ð¸Ñ Ð²Ð½ÑÑÑи пеÑеданного конÑейнеÑа блок Ñ ÐºÐ»Ð°ÑÑом timer. ÐаÑем забиÑÐ°ÐµÑ Ð´Ð°Ð½Ð½Ñе о ÑекÑÑем обÑем вÑемени видимоÑÑи блока. С помоÑÑÑ Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð½Ð° 1000, 60 и 60 Ð¼Ñ Ð¿ÑеобÑазÑем ÑезÑлÑÑÐ°Ñ Ð² нÑжнÑй ÑоÑÐ¼Ð°Ñ (миллиÑекÑÐ½Ð´Ñ -> ÑекÑÐ½Ð´Ñ -> минÑÑÑ / ÑекÑндÑ)
ÐеÑод String.padStart() иÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ñого, ÑÑÐ¾Ð±Ñ ÑбедиÑÑÑÑ, ÑÑо ÑиÑло ÑекÑнд вÑегда ÑоÑÑоÑÑ Ð¸Ð· двÑÑ
ÑиÑÑ.
СÑÑоим ÑодеÑжимое ÑÑÑаниÑÑ
ФÑнкÑÐ¸Ñ buildContents() вÑзÑваеÑÑÑ Ð¿Ñи ÑÑаÑÑе пÑиложениÑ. Ðна ÑоÑмиÑÑÐµÑ Ñело ÑÑаÑÑи и добавлÑÐµÑ ÑекламнÑе блоки:
let loremIpsum =
"<p>Lorem ipsum dolor sit amet, consectetur adipiscing" +
" elit. Cras at sem diam. Vestibulum venenatis massa in tincidunt" +
" egestas. Morbi eu lorem vel est sodales auctor hendrerit placerat" +
" risus. Etiam rutrum faucibus sem, vitae mattis ipsum ullamcorper" +
" eu. Donec nec imperdiet nibh, nec vehicula libero. Phasellus vel" +
" malesuada nulla. Aliquam sed magna aliquam, vestibulum nisi at," +
" cursus nunc.</p>";
function buildContents() {
for (let i = 0; i < 5; i++) {
contentBox.appendChild(createArticle(loremIpsum));
if (!(i % 2)) {
loadRandomAd();
}
}
}
ÐеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ loremIpsum ÑодеÑÐ¶Ð¸Ñ ÑекÑÑ, коÑоÑÑй Ð¼Ñ Ð¸ÑполÑзÑем как Ñело ÑÑаÑÑи. РазÑмееÑÑÑ, в ÑеалÑном миÑе Ð²Ñ Ð±ÑдеÑе забиÑаÑÑ ÑÑаÑÑи из какой-Ñо Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
. Ðо ÑÑо Ñема дÑÑгой ÑÑаÑÑи, поÑÑÐ¾Ð¼Ñ Ð¼Ñ Ð¿Ð¾Ñли пÑоÑÑÑм пÑÑÑм.
buildContents() ÑоздаÑÑ ÑÑÑаниÑÑ Ñ Ð¿ÑÑÑÑ ÑÑаÑÑÑми. ÐÐ°Ð¶Ð´Ð°Ñ Ð½ÐµÑÑÑÐ½Ð°Ñ ÑÑаÑÑÑ ÑодеÑÐ¶Ð¸Ñ ÑекламнÑе блоки. СÑаÑÑи бÑдÑÑ Ð²ÑÑÐ°Ð²Ð»ÐµÐ½Ñ Ð² блок конÑенÑа <main>. поÑле Ñого, как бÑÐ´ÐµÑ Ð²Ñзван меÑод createArticle(), коÑоÑÑй Ð¼Ñ ÑазбеÑÑм позже.
РекламнÑе блоки ÑоздаÑÑÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÑÑнкÑии loadRandomAd(). ÐÑа ÑÑнкÑÐ¸Ñ ÑоздаÑÑ Ð¸ вÑÑавлÑÐµÑ Ð±Ð»Ð¾ÐºÐ¸ одновÑеменно. Ðак Ð¼Ñ Ñвидим позже, ÑÑа же ÑÑнкÑÐ¸Ñ Ð¼Ð¾Ð¶ÐµÑ Ð¸ замениÑÑ Ñже ÑÑÑеÑÑвÑÑÑÑÑ ÑекламÑ. Ðо пока ÑÑо пÑоÑÑо добавим ÑÐµÐºÐ»Ð°Ð¼Ñ Ð² ÑÑÑеÑÑвÑÑÑий ÑекÑÑ.
СоздаÑм ÑÑаÑÑÑ
ÐÐ»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÑлеменÑа ÑÑаÑÑи <article> и ÐµÑ ÑодеÑжимого Ð¼Ñ Ð¸ÑполÑзÑем ÑÑнкÑÐ¸Ñ createArticle(), коÑоÑÐ°Ñ Ð² каÑеÑÑве вÑ
однÑÑ
даннÑÑ
пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ ÑÑÑокÑ-ÑекÑÑ ÑÑаÑÑи.
function createArticle(contents) {
let articleElem = document.createElement("article");
articleElem.id = nextArticleID;
let titleElem = document.createElement("h2");
titleElem.id = nextArticleID;
titleElem.innerText = "Article " + nextArticleID + " title";
articleElem.appendChild(titleElem);
articleElem.innerHTML += contents;
nextArticleID += 1;
return articleElem;
}
СпеÑва, ÑÐ»ÐµÐ¼ÐµÐ½Ñ <article> ÑоздаÑÑÑÑ Ð¸ ÐµÐ¼Ñ Ð¿ÑиÑваиваеÑÑÑ ÑникалÑнÑй ID nextArticleID (ÑÑо пÑоÑÑо ÑÑÑÑÑик Ð¾Ñ Ð½ÑÐ»Ñ Ð´Ð¾ беÑконеÑноÑÑи). ÐаÑем Ð¼Ñ ÑоздаÑм и добавлÑем ÑÐ»ÐµÐ¼ÐµÐ½Ñ <h2> Ð´Ð»Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ° и пÑименÑем HTML из пеÑеменной contents. ÐаконеÑ, Ð¼Ñ ÑвелиÑиваем знаÑение nextArticleID (Ñаким обÑазом, ÑледÑÑÑий ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð¿Ð¾Ð»ÑÑÐ¸Ñ ÑникалÑнÑй ID) и возвÑаÑаем ÑÐ»ÐµÐ¼ÐµÐ½Ñ ÑÑаÑÑи обÑаÑно.
Создание Ñекламного блока
ФÑнкÑÐ¸Ñ loadRandomAd() имиÑиÑÑÐµÑ Ð·Ð°Ð³ÑÑÐ·ÐºÑ ÑÐµÐºÐ»Ð°Ð¼Ñ Ð¸ ÐµÑ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ðµ на ÑÑÑаниÑÑ. ÐÑли Ð²Ñ Ð½Ðµ ÑказÑваеÑе знаÑение Ð´Ð»Ñ replaceBox, ÑоздаÑÑÑÑ Ð¸ пÑименÑеÑÑÑ Ð½Ð¾Ð²Ñй конÑÐµÐ¹Ð½ÐµÑ Ð´Ð»Ñ ÑекламÑ. ÐÑли Ð²Ñ Ñказали replaceBox, ÑÑÐ¾Ñ ÐºÐ¾Ð½ÑÐµÐ¹Ð½ÐµÑ ÑаÑÑмаÑÑиваеÑÑÑ, как Ñже ÑÑÑеÑÑвÑÑÑий ÑлеменÑ. ÐмеÑÑо ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾, ÑÑÑеÑÑвÑÑÑий ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð¸Ð·Ð¼ÐµÐ½ÑеÑÑÑ, ÑÑÐ¾Ð±Ñ ÑодеÑжаÑÑ Ð°ÐºÑÑалÑнÑе даннÑе. ÐÑо Ð¿Ð¾Ð¼Ð¾Ð³Ð°ÐµÑ Ð¸Ð·Ð±ÐµÐ¶Ð°ÑÑ ÑиÑка неÑÑÑекÑивной пеÑеÑиÑовки ÑлеменÑов, еÑли Ð²Ñ ÑнаÑала бÑдеÑе ÑдалÑÑÑ ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð¸Ð· DOM, а заÑем вÑÑавлÑÑÑ Ð½Ð¾Ð²Ñй.
function loadRandomAd(replaceBox) {
let ads = [
{
bgcolor: "#cec",
title: "Eat Green Beans",
body: "Make your mother proudâthey're good for you!",
},
{
bgcolor: "aquamarine",
title: "MillionsOfFreeBooks.whatever",
body: "Read classic literature online free!",
},
{
bgcolor: "lightgrey",
title: "3.14 Shades of Gray: A novel",
body: "Love really does make the world go round...",
},
{
bgcolor: "#fee",
title: "Flexbox Florist",
body: "When life's layout gets complicated, send flowers.",
},
];
let adBox, title, body, timerElem;
let ad = ads[Math.floor(Math.random() * ads.length)];
if (replaceBox) {
adObserver.unobserve(replaceBox);
adBox = replaceBox;
title = replaceBox.querySelector(".title");
body = replaceBox.querySelector(".body");
timerElem = replaceBox.querySelector(".timer");
} else {
adBox = document.createElement("div");
adBox.className = "ad";
title = document.createElement("h2");
body = document.createElement("p");
timerElem = document.createElement("div");
adBox.appendChild(title);
adBox.appendChild(body);
adBox.appendChild(timerElem);
}
adBox.style.backgroundColor = ad.bgcolor;
title.className = "title";
body.className = "body";
title.innerText = ad.title;
body.innerHTML = ad.body;
adBox.dataset.totalViewTime = 0;
adBox.dataset.lastViewStarted = 0;
timerElem.className = "timer";
timerElem.innerText = "0:00";
if (!replaceBox) {
contentBox.appendChild(adBox);
}
adObserver.observe(adBox);
}
ÐнаÑале Ð¼Ñ Ð¾Ð¿ÑеделÑем маÑÑив ads. ÐÑÐ¾Ñ Ð¼Ð°ÑÑив ÑодеÑÐ¶Ð¸Ñ Ð´Ð°Ð½Ð½Ñе, необÑ
одимÑе Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÑекламнÑÑ
блоков. Ð ÑеалÑном пÑиложении, конеÑно, Ð¼Ñ Ð±Ñдем загÑÑжаÑÑ ÑÑи даннÑе из Ð±Ð°Ð·Ñ Ð¸Ð»Ð¸, ÑÑо более веÑоÑÑно, из Ñекламного ÑеÑвиÑа, коÑоÑÑй бÑÐ´ÐµÑ Ð¸ÑполÑзоваÑÑ ÐºÐ°ÐºÐ¾Ð¹-Ñо API. Тем не менее, наÑа пÑоÑÑÐ°Ñ Ð·Ð°Ð´Ð°Ñа ÑеÑаеÑÑÑ: каждÑй ÑекламнÑй блок пÑедÑÑавлен ÑÑÐµÐ¼Ñ ÑвойÑÑвами: ÑоновÑм ÑвеÑом (bgcolor), заголовком (title) и ÑекÑÑовÑм ÑодеÑжимÑм (body).
ÐаÑем Ð¼Ñ Ð¾Ð¿ÑеделÑем неÑколÑко пеÑеменнÑÑ :
adBox-
ÐпÑеделÑÐµÑ ÐºÐ¾Ð½ÑейнеÑ, ÑодеÑжаÑий ÑекламÑ. ÐÐ½Ð¾Ð²Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð½Ñе ÑекламнÑе блоки бÑдÑÑ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ñ Ðº ÑÑÑаниÑе Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ
Document.createElement(). Ðогда замеÑаеÑÑÑ ÑÑÑеÑÑвÑÑÑÐ°Ñ Ñеклама, в ÑÑой пеÑеменной Ñказан ÑÐ»ÐµÐ¼ÐµÐ½Ñ (replaceBox). title-
СодеÑÐ¶Ð¸Ñ ÑÑÑÐ»ÐºÑ Ð½Ð° ÑлеменÑ
<h2>. body-
СодеÑÐ¶Ð¸Ñ ÑÑÑÐ»ÐºÑ Ð½Ð° ÑлеменÑ
<p>. timerElem-
СодеÑÐ¶Ð¸Ñ ÑÑÑÐ»ÐºÑ Ð½Ð° ÑÐ»ÐµÐ¼ÐµÐ½Ñ ÑаймеÑа
<div>.
СлÑÑайнÑй ÑекламнÑй блок вÑÑиÑлÑеÑÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Math.floor(Math.random() * ads.length). РезÑлÑÑÐ°Ñ ÑÑой ÑÑнкÑии - Ñелое ÑиÑло Ð¼ÐµÐ¶Ð´Ñ 0 и макÑималÑнÑм колиÑеÑÑвом ÑекламнÑÑ
блоков. СооÑвеÑÑÑвÑÑÑий ÑекламнÑй блок ÑепеÑÑ Ð´Ð¾ÑÑÑпен нам из пеÑеменной adBox.
ÐÑли replaceBox ÑодеÑÐ¶Ð¸Ñ ÐºÐ°ÐºÐ¾Ðµ-Ñо знаÑение, Ð¼Ñ ÑаÑÑмаÑÑиваем его как ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ñекламного блока. ÐÑ Ð·Ð°Ð²ÐµÑÑаем наблÑдение за ÑлеменÑом Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ IntersectionObserver.unobserve(). ÐаÑем ÑобиÑаем в локалÑнÑе пеÑеменнÑе даннÑе из каждого ÑвойÑÑва ÑлеменÑа: заголовок, Ñело и ÑаймеÑ.
ÐÑли никакое знаÑение не Ñказано Ð´Ð»Ñ replaceBox, Ð¼Ñ ÑоздаÑм новÑй ÑлеменÑ. СоздаÑÑÑÑ Ð½Ð¾Ð²Ñй конÑÐµÐ¹Ð½ÐµÑ <div>. Ðго CSS-паÑамеÑÑÑ Ð·Ð°Ð´Ð°ÑÑÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÐºÐ»Ð°ÑÑа "ad". ÐаÑем ÑоздаÑÑÑÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²Ð¾Ðº Ñекламного блока, его ÑекÑÑ Ð¸ ÑаймеÑ. СооÑвеÑÑÑвенно, ÑÑо <h2>, <p> и <div>. ÐÑи ÑлеменÑÑ Ð¿ÑименÑÑÑÑÑ Ðº конÑейнеÑÑ adBox.
ÐоÑле ÑÑого ÑазвеÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð½Ð°Ñ ÐºÐ¾Ð´ Ð²Ð½Ð¾Ð²Ñ Ð²Ð¾Ð·Ð²ÑаÑаеÑÑÑ Ðº единомÑ. ФоновÑй ÑÐ²ÐµÑ ÑекламнÑÑ Ð±Ð»Ð¾ÐºÐ¾Ð² пÑиÑваиваеÑÑÑ ÑооÑвеÑÑÑвенно запиÑÑм. ÐлеменÑам пÑиÑваиваÑÑÑÑ ÐºÐ»Ð°ÑÑÑ Ð¸ ÑодеÑжимое.
ÐаÑÑÑпаем вÑÐµÐ¼Ñ Ð¿ÑиÑвоиÑÑ data-паÑамеÑÑÑ, ÑÑÐ¾Ð±Ñ Ð¾ÑÑлеживаÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑÑ ÑекламнÑÑ
блоков Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÑÑÑановки adBox.dataset.totalViewTime и adBox.dataset.lastViewStarted ÑавнÑми нÑлÑ.
ÐаконеÑ, Ð¼Ñ ÑÑÑанавливаем CSS-клаÑÑ ÐºÐ¾Ð½ÑейнеÑÑ ÑаймеÑа. С помоÑÑÑ ÑÑого клаÑÑа пÑиложение ÑÐ¼Ð¾Ð¶ÐµÑ Ñ Ð»ÑгкоÑÑÑÑ ÑобиÑаÑÑ Ð´Ð°Ð½Ð½Ñе и обновлÑÑÑ Ð¸Ñ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ÑаймеÑа. Ðо ÑмолÑаниÑ, ÑекÑÑ ÑÑого конÑейнеÑа - "0:00".
ÐÑли Ð¼Ñ ÑоздаÑм новÑÑ ÑекламÑ, Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿ÑимениÑÑ ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ðº ÑÑÑаниÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Document.appendChild(). ÐÑли Ð¼Ñ Ð»Ð¸ÑÑ Ð·Ð°Ð¼ÐµÐ½Ñем ÑекламнÑй блок - он Ñже пÑедÑÑавлен в DOM и вÑÑ, ÑÑо нам нÑжно ÑделаÑÑ - ÑÑо обновиÑÑ ÐµÐ³Ð¾. ÐаÑем Ð¼Ñ Ð²ÑзÑваем ÑÑнкÑÐ¸Ñ observe(). adObserver наÑÐ¸Ð½Ð°ÐµÑ Ð¾ÑÑлеживаÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿ÐµÑекÑÑÑÐ¸Ñ ÑлеменÑов в видимой облаÑÑи пÑиложениÑ. С ÑÑого моменÑа лÑбой ÑекламнÑй блок, коÑоÑÑй ÑÑановиÑÑÑ Ð½Ð° 100% ÑкÑÑÑ Ð¸Ð»Ð¸ Ñ
оÑÑ Ð±Ñ Ð½Ð° один пикÑÐµÐ»Ñ Ð²Ð¸Ð´Ð¸Ð¼ или пÑÐµÐ¾Ð´Ð¾Ð»ÐµÐ²Ð°ÐµÑ Ð¿Ð¾Ñог в 75% видимоÑÑи в лÑбом напÑавлении, запÑÑÐºÐ°ÐµÑ Ð²ÑÑиÑление Ñаймингов и обновление ÑодеÑжимого ÑаймеÑов.
Ðамена ÑÑÑеÑÑвÑÑÑей ÑекламÑ
ÐаÑа ÑÑнкÑÐ¸Ñ Ð¾Ð±ÑабоÑки пеÑекÑÑÑÐ¸Ñ Ð¾ÑÑÐ»ÐµÐ¶Ð¸Ð²Ð°ÐµÑ ÑекламнÑе блоки. Ðогда они ÑÑановÑÑÑÑ Ð½Ð° 100% и обÑее вÑÐµÐ¼Ñ Ð¸Ñ
видимоÑÑи доÑÑаÑоÑное Ð´Ð»Ñ Ñого, ÑекламнÑй блок заменÑеÑÑÑ Ð½Ð° новÑй. Ðогда ÑÑо пÑоиÑÑ
одиÑ, вÑзÑваеÑÑÑ ÑÑнкÑÐ¸Ñ replaceAd().
function replaceAd(adBox) {
let visibleTime;
updateAdTimer(adBox);
visibleTime = adBox.dataset.totalViewTime;
console.log(
" Replacing ad: " +
adBox.querySelector("h2").innerText +
" - visible for " +
visibleTime,
);
loadRandomAd(adBox);
}
replaceAd() наÑинаеÑÑÑ Ñ Ð²Ñзова updateAdTimer() Ð´Ð»Ñ ÑÑÑеÑÑвÑÑÑего Ñекламного блока, ÑÑÐ¾Ð±Ñ ÑбедиÑÑÑÑ, ÑÑо ÑÐ°Ð¹Ð¼ÐµÑ Ð¾Ð±Ð½Ð¾Ð²Ð»Ñн. С помоÑÑÑ ÑÑого вÑзова Ð¼Ñ ÑбеждаемÑÑ, ÑÑо totalViewTime, коÑоÑÑй Ð¼Ñ Ð¸ÑполÑзÑем Ð´Ð»Ñ Ð¾Ð±ÑабоÑки, дейÑÑвиÑелÑно ÑÐ¾Ð²Ð¿Ð°Ð´Ð°ÐµÑ Ñ Ñем, ÑÑо видел полÑзоваÑелÑ. ÐÑ Ð»Ð¾Ð³Ð¸ÑÑем ÑÑо знаÑение и загÑÑжаем в ÑекламнÑй блок новÑе даннÑе. ÐомниÑе, ÑÑо в ÑеалÑном миÑе Ð²Ñ Ð½Ðµ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð»Ð¾Ð³Ð¸ÑоваÑÑ Ð¿Ð¾Ð´Ð¾Ð±Ð½Ñе веÑи, а ÑкоÑее иÑполÑзоваÑÑ API Ð´Ð»Ñ ÑÐ±Ð¾Ñ Ð»Ð¾Ð³Ð¾Ð².
РезÑлÑÑаÑ
ÐÑ Ð¼Ð¾Ð¶ÐµÑе ÑвидеÑÑ ÑезÑлÑÑÐ°Ñ Ð² окне ниже. ÐопÑобÑйÑе ÑкÑпеÑименÑиÑоваÑÑ Ñ Ð¿ÑокÑÑÑкой и понаблÑдайÑе за Ñем, как изменение видимоÑÑи заÑÑÐ°Ð³Ð¸Ð²Ð°ÐµÑ ÐºÐ°Ð¶Ð´Ñй ÑаймеÑ. ÐÑоме Ñого, обÑаÑиÑе внимание, ÑÑо каждÑй ÑекламнÑй блок обновлÑеÑÑÑ ÑолÑко в Ñом ÑлÑÑае, еÑли он Ñже бÑл видим в ÑеÑение минÑÑÑ.