Recenze Oppo Reno12 FS 5G: krása na pohled a dobrý foťák, na dotek je ale patrný kompromis

Sdílet

 Autor: Cnews (Dominik Dobrozenský)
Letošní Oppo Reno12 FS 5G se chlubí inspirativním designem. Některé parametry telefonu však patří do levnějšího segmentu, než kam jej řadí odvážná cena. Potěší však velké 512GB úložiště či slušný hlavní fotoaparát.
Co se dozvíte v článku
  1. Obsah balení:
  2. Parametry:
  3. Vzhled a celkové zpracování:
  4. Displej:
  5. Uživatelské rozhraní:
  6. Výkon:
  7. Výdrž:
  8. Fotoaparát:
  9. Závěr:

Obsah balení:

Uvnitř krabičky najdete na dnešní poměry poměrně standardní kombo v podobě telefonu, USB-C kabelu sloužícího pro napájení a přenos dat, špendlíček pro vytažení slotu na dvojici nanoSIM karet a příslušnou dokumentaci. Nic víc, nic míň.

Obsah balení je po vzoru moderní doby strohý

Obsah balení je po vzoru moderní doby strohý

Autor: Cnews

Parametry:

Rozměry a hmotnost:

163,1 × 75,8 × 7,8 mm; 187 g

Zpracování:

displej s odolným sklem, záda a rám z plastu, odolnost IP64

Displej:

6,67" AMOLED panel, 2400 × 1080 px, 120 Hz, jemnost 395 PPI, jas až 2100 nitů

Procesor:

Mediatek Dimensity 6300 (6 nm), 8jádrový, frekvence až 2,4 GHz, grafický akcelerátor Mali-G57 MC2

RAM a paměť:

12 GB RAM + 512 GB vnitřního úložiště

Selfie kamera:

32 Mpx, f/2.4, širokoúhlý, 1080p@30fps

Zadní fotoaparáty:
  • hlavní: 50 Mpx, f/1.8, 26 mm, PDAF, OIS

  • ultraširokoúhlý: 8 Mpx, f/2.2, 16 mm, 112°

  • makro: 2 Mpx, f/2.4

Nahrávání videa:

1080p@60/30fps

Baterie a nabíjení:

5000 mAh, rychlonabíjení 45 W, reverzní drátové napájení

Operační systém:

Android 14 s nadstavbou ColorOS 14 s Google službami

Konektivita a funkce:
  • 5G, 4G, GSM, Wi-Fi 6, Bluetooth 5.3 (aptX)
  • GPS, GLONASS, GALILEO, BDS, QZSS
  • USB-C 2.0, NFC, dual nanoSIM, optická čtečka otisku prstů, odemykání obličejem

Vzhled a celkové zpracování:

OPPO Reno12 FS přichází do střední třídy ve stylovém a relativně kompaktním těle. Na první pohled se jedná o pěkně zpracovaný kousek, který se zejména ve svém oranžovém provedení snaží skrýt přítomnost levného plastového rámečku. V ruce se smartphone díky své nízké hmotnosti 187 gramů a mírně ostřejším rohům drží pohodlně, v teplejších dnech však dokáže telefon díky svým plastovým rámečkům pěkně klouzat. Na druhou stranu matná úprava zad efektivně zabraňuje ulpívání otisku prstů.

Svým stylovým matným provedením se OPPO snaží zakrýt přítomnost plastu

Svým stylovým matným provedením se OPPO snaží zakrýt přítomnost plastu

Autor: Cnews

Mnou testovaná zelená varianta nabízí matně zpracovaná zelená záda s dominantním kruhovým fotomodulem. Díky jeho zapuštění jsou záda vesměs zarovnaná a při používání na stole se telefon nijak neviklá. Zbytek telefonu nabízí poměrně standardní rozložení, konkrétně tlačítko pro zapnutí a regulaci hlasitosti na pravém boku a napájecí USB-C doprovázené slotem na dvojici nanoSIM karet a hlasitý reproduktor vespod.


Pravý bok telefonu

Pravý bok telefonu

Autor: Cnews
Smartphone pojme až dvě nanoSIM karty, případně SIM a microSD kartu

Smartphone pojme až dvě nanoSIM karty, případně SIM a microSD kartu

Autor: Cnews

Telefon se pyšní zvýšenou odolností IP64, tedy odolností proti prachu a stříkající vodě. Na plné ponoření do vody si bohužel nechte zajít chuť.

Detail na kruhový fotomodul doplněný o kruhovou LED diodu

Detail na kruhový fotomodul doplněný o kruhovou LED diodu

Autor: Cnews

Displej:

O displej se stará osvědčený AMOLED panel s velikostí 6,67" a rozlišením 2400 × 1080 px. Vzhledem k rozlišení a velikosti displeje nám OPPO dalo jemnost 395 PPI, což je dostatečná jemnost pro bezproblémové každodenní používání i sledování videoobsahu.

Displej nabízí osvědčené barevné podání a příjemný maximální jas až 2100 nitů, díky čemu je možné jej bez větších obtíží používat venku nebo s trochou trpělivosti i na přímém slunci. Rovněž oceňuji velmi nízký maximální jas, díky kterému vás displej v úplně tmě zbytečně neoslňuje. OPPO do nastavení displeje přidává i možnosti nastavení ochrany zraku.


Dominantou je přední AMOLED displej

Dominantou je přední AMOLED displej

Autor: Cnews
Detail na přední selfie fotoaparát

Detail na přední selfie fotoaparát

Autor: Cnews

Uživatelské rozhraní:

OPPO sází na vlastní nadstavbu ColorOS 14.0 postavenou nad Android 14. Ta přináší vlastní ovládací nabídku a domovskou obrazovku, v systému se však dá relativně rychle zorientovat. K tomu vám telefon umožní používání flexibilních plovoucích oken nebo chytrý boční panel s rychlým spouštěním aplikací.

Systém jako takový je svižný a při běžném používání se nikterak neseká. Díky ne úplně nejnovějšímu procesoru systém ztratí dech při náročnějším multitaskingu. Osobně mi moc nesedí vzhled samotných ikon, což díky možnostem nastavení za jinou sadu lze také odpustit.

Recenze smartphonu Google Pixel 8a: vlajkový Pixel schovaný v levnějším kabátku Přečtěte si také:

Recenze smartphonu Google Pixel 8a: vlajkový Pixel schovaný v levnějším kabátku

Model Reno12 FS vrací z dávných let s jistou nadsázkou notifikační LED diodu v podobě kruhového prstence okolo fotoaparátu, který dokáže blikáním či svícením informovat o příchozích notifikacích, hovorech, doprovázet vás při hraní her nebo poslechu hudby.

Nabíjení, notifikace nebo poslech hudby mohou být doprovázeny podsvíceným prstencem

Nabíjení, notifikace nebo poslech hudby mohou být doprovázeny podsvíceným prstencem

Autor: Cnews
Nastavení kruhového prstence okolo fotoaparátů

Nastavení kruhového prstence okolo fotoaparátů

Autor: Cnews

OPPO pro tento model zaručilo 2 hlavní aktualizace Androidu a 3 roky bezpečnostních záplat, výkonnější bratříček OPPO Reno12 Pro obdrží 3 hlavní aktualizace a 4 roky bezpečnostních aktualizací. Rovněž musím upozornit na přehršel předinstalovaného bloatwaru, s jehož odinstalací strávíte zbytečně pár minut svého života.

Výkon:

Informace o procesoru z CPU-Z

Informace o procesoru z CPU-Z

Autor: Cnews

Jak už bylo řečeno v předchozí kapitole, použitý procesor Mediatek Dimensity 6300 vyrobený na 6nm technologii nepatří mezi nejvýkonnější, avšak stále se řadí mezi relativně schopné kousky. Na běžné používání vám procesor bez problému vystačí, na náročnější multitasking, sledování videa s vysokým bitratem nebo nedejbože hraní náročnějších her si raději nechte zajít chuť.

Procesor doprovází 12 GB operační paměti společně s 512 GB vnitřního úložiště, které můžete dále rozšířit skrze paměťové microSD karty. Součástí systému je i funkce virtuálního rozšíření RAM až o dalších virtuálních 12 GB.

3DMark (Wild Life)
PCMark (Work 3.0)
PCMark (battery)
Geekbench 6
AnTuTu Benchmark

1295 bodů

9310 bodů

10 hodin a 33 minut

781 bodů SC

1942 bodů MC

470 076 bodů

Výdrž:

Vzhledem k tloušťce a nízké hmotnosti je přítomnost 5000mAh baterie příjemným překvapením. Díky ní dokáže telefon bez problému fungovat při troše skromnosti i dva dny na nabití. Při náročnějším každodenním používání, kdy budete telefon brát do ruky co pár minut, se z něj pochopitelně stane typické jednodenní zařízení, které budete přes noc nechávat v nabíječce.

Oppo Reno12 FS s výkonnějším bratříčkem OPPO Reno12 Pro

Oppo Reno12 FS (s výkonnějším bratříčkem OPPO Reno12 Pro)

Autor: Cnews

Smartphone podporuje 45W drátové nabíjení a reverzní drátové nabíjení s blíže nespecifikovaným výkonem. Pro potřeby testování jsem smartphone nabíjel mojí 100W Baseus GaN nabíječkou, které trvalo 28 minut pro nabití telefonu na 50 %, do plných 100 % pak lehce přes hodinu a 15 minut.

50 % baterie
70 % baterie
100 % baterie

± 28 minut

± 40 minut

± 1 hodina a 15 minut

Fotoaparát:

Z fotovýbavy je použitelný jen hlavní 50Mpx fotoaparát, zbylé snímače nabízí přinejlepším průměrné snímky a některé (jako třeba makro) jsou zde pouze do počtu. To pro makro ostatně platí i u většiny konkurenčních telefonů.

Začněme tedy hlavním fotoaparátem. Za dne z něj dostanete relativně pěkné snímky s dobrou expozicí, detaily i barevným podáním. Fotky sází na nádech přirozenosti bez saturovanějšího postprocessingu, kterým je známý kupříkladu Samsung.


Ultraširokoúhlý 8Mpx fotoaparát

Ultraširokoúhlý 8Mpx fotoaparát

Autor: Cnews
Hlavní 50Mpx fotoaparát

Hlavní 50Mpx fotoaparát

Autor: Cnews
2násobný digitální zoom

2násobný digitální zoom

Autor: Cnews
Ultraširokoúhlý 8Mpx fotoaparát

Ultraširokoúhlý 8Mpx fotoaparát

Autor: Cnews
Hlavní 50Mpx fotoaparát

Hlavní 50Mpx fotoaparát

Autor: Cnews
2násobný digitální zoom

2násobný digitální zoom

Autor: Cnews

8Mpx ultraširokoúhlý fotoaparát s šíří záběru 112° fotí za dne průměrně kvalitní fotky, které nikterak neoslní, zároveň ale vzhledem k cenové kategorii neurazí. Za zhoršeného světla kvalita razantně ustupuje digitálnímu šumu a rozmazání. To stejné se bohužel nedá říci o 2Mpx makru, které je zde opravdu jen do počtu a jeho kvalita je jedním slovem chabá.


Ultraširokoúhlý 8Mpx fotoaparát

Ultraširokoúhlý 8Mpx fotoaparát

Autor: Cnews
Hlavní 50Mpx fotoaparát

Hlavní 50Mpx fotoaparát

Autor: Cnews
2násobný digitální zoom

2násobný digitální zoom

Autor: Cnews
Ultraširokoúhlý 8Mpx fotoaparát

Ultraširokoúhlý 8Mpx fotoaparát

Autor: Cnews
Hlavní 50Mpx fotoaparát

Hlavní 50Mpx fotoaparát

Autor: Cnews
2násobný digitální zoom

2násobný digitální zoom

Autor: Cnews

Přední 32Mpx selfie kamera vystačí na průměrně kvalitní fotografie a momentky, a pokud si potrpíte na kvalitní a detailně zpracované selfie snímky, bude to chtít jiný a vlajkovější telefon.

Ostatně ani s nahráváním videí to není žádná sláva. Telefon podporuje na všech fotoaparátech pouze 1080p video s 60 FPS na zadním a pouhými 30 FPS na předním fotoaparátu. Absencí jakékoliv stabilizace se do videa propisuje sebemenší otřes rukou nebo chůze, což výsledné kvalitě rovněž extra body nepřidá.

Cyber25

Zdroj: YouTube.com

Závěr:

Oppo Reno12 FS je zajímavý telefon, který však (zatím) zbytečně kazí jeho cena. Výrobce si mohl odpustit plastový rámeček, použít novější procesor a zkrátka předvést vzornější podporu hodnou roku 2024. Na druhou stranu je třeba pochválit za velké 512GB úložiště dále rozšířitelné o paměťové karty, poměrně odladěný systém a slušný hlavní fotoaparát (ostatní čočky už tak dobré nejsou).

V řadě parametrů tohle Reno víceméně spadá do průměru. V něm za cenu okolo 10 tisíc najdete kupříkladu Samsung Galaxy A55, Realme 11 Pro+ nebo Motorolu Edge 30 Ultra z roku 2022, která má i dnes díky svým vlajkovým parametrům co nabídnout. Osobně mi nad konkurencí (a někdy nudnou „šedí“) ve střední třídě vyčnívá spíše designem (LED kolečko je pro Oppo typické) a velkým úložištěm s možností dalšího rozšíření. 

Líbilo se mi:
Nelíbilo se mi:
+ povedený design v obou barevných variantách – průměrně rychlá čtečka otisku prstů
+ příjemná výdrž – předinstalovaný bloatware
+ nízká tloušťka a hmotnost – pouze 1080p video bez jakékoliv stabilizace
+ dostatek RAM a velké rozšířitelné úložiště
+ AMOLED panel s výborným maximálním jasem
+ ColorOS nabízí příjemné vychytávky
+ ozvláštnění v podobě kruhového notifikačního prstence

Autor článku

Šéfredaktor portálu Cnews.cz. Zaměřuje se na technologické novinky, recenze spotřební elektroniky, smartphony, 3D tisk, AI a herní novinky. Profil autora →

'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }
'; document.getElementById('outstream-iframe').onload = function () { setupIframe(); } replayScreen = document.getElementById('iinfoOutstreamReplay'); iinfoOutstreamPosition = document.getElementById('iinfoOutstreamPosition'); outstreamContainer = document.getElementsByClassName('outstream-container')[0]; setupReplayScreen(); } function setupIframe() { outstreamDocument = document.getElementById('outstream-iframe').contentWindow.document; let el = outstreamDocument.createElement('style'); outstreamDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:-5px;right:25px}"; videoContent = outstreamDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; if ( location.href.indexOf('rejstriky.finance.cz') !== -1 || location.href.indexOf('finance-rejstrik') !== -1 || location.href.indexOf('firmy.euro.cz') !== -1 || location.href.indexOf('euro-rejstrik') !== -1 || location.href.indexOf('/rejstrik/') !== -1 || location.href.indexOf('/rejstrik-firem/') !== -1) { outstreamDirectPlayed = true; soundAllowed = true; iinfoVastUrlIndex = 0; } if (!outstreamDirectPlayed) { console.log('OUTSTREAM direct'); setUpIMA(true); } else { if (soundAllowed) { const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('OUTSTREAM sound allowed'); setUpIMA(false); }).catch(function () { console.log('OUTSTREAM sound forbidden'); renderBanner(); }); } } else { renderBanner(); } } } function getWrapper() { let articleWrapper = document.querySelector('.rs-outstream-placeholder'); // Outstream Placeholder from RedSys manipulation if (articleWrapper && articleWrapper.style.display !== 'block') { articleWrapper.innerHTML = ""; articleWrapper.style.display = 'block'; } // Don't render OutStream on homepages if (articleWrapper === null) { if (document.querySelector('body.p-index')) { return null; } } if (articleWrapper === null) { articleWrapper = document.getElementById('iinfo-outstream'); } if (articleWrapper === null) { articleWrapper = document.querySelector('.layout-main__content .detail__article p:nth-of-type(6)'); } if (articleWrapper === null) { // Euro, Autobible, Zdravi articleWrapper = document.querySelector('.o-article .o-article__text p:nth-of-type(6)'); } if (articleWrapper === null) { articleWrapper = document.getElementById('sidebar'); } if (!articleWrapper) { console.error("Outstream wrapper of article was not found."); } return articleWrapper; } function setupDimensions() { outstreamWidth = Math.min(iinfoOutstreamPosition.offsetWidth, 480); outstreamHeight = Math.min(iinfoOutstreamPosition.offsetHeight, 320); } /** * Sets up IMA ad display container, ads loader, and makes an ad request. */ function setUpIMA(direct) { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); if (direct) { adsRequest.adTagUrl = directVast; console.log('Outstream DIRECT CAMPAING advert: ' + directVast); videoContent.muted = true; videoContent.volume = 0; outstreamDirectPlayed = true; } else { adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Outstream advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; } // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = outstreamWidth; // adsRequest.linearAdSlotHeight = outstreamHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function setupReplayScreen() { replayScreen.addEventListener('click', function () { iinfoOutstreamPosition.remove(); iinfoVastUrlIndex = 0; outstreamInit(); }); } /** * Sets the 'adContainer' div as the IMA ad display container. */ function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. outstreamDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( outstreamDocument.getElementById('adContainer'), videoContent); } function unmuteAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } } /** * Loads the video content and initializes IMA ad playback. */ function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(outstreamWidth, outstreamHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } /** * Handles the ad manager loading and sets ad event listeners. * @param { !google.ima.AdsManagerLoadedEvent } adsManagerLoadedEvent */ function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } /** * Handles actions taken in response to ad events. * @param { !google.ima.AdEvent } adEvent */ function onAdEvent(adEvent) { // Retrieve the ad from the event. Some events (for example, // ALL_ADS_COMPLETED) don't have ad object associated. const ad = adEvent.getAd(); console.log('Outstream event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: // This is the first event sent for an ad - it is possible to // determine whether the ad is a video ad or an overlay. if (!ad.isLinear()) { // Position AdDisplayContainer correctly for overlay. // Use ad.width and ad.height. videoContent.play(); } outstreamDocument.getElementById('adContainer').style.width = '100%'; outstreamDocument.getElementById('adContainer').style.maxWidth = '640px'; outstreamDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); // This event indicates the ad has started - the video player // can adjust the UI, for example display a pause button and // remaining time. if (ad.isLinear()) { // For a linear ad, a timer can be started to poll for // the remaining time. intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } outstreamDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (outstreamLastError === 303) { if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } } break; case google.ima.AdEvent.Type.COMPLETE: // This event indicates the ad has finished - the video player // can perform appropriate UI actions, such as removing the timer for // remaining time detection. if (ad.isLinear()) { clearInterval(intervalTimer); } if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } break; } } /** * Handles ad errors. * @param { !google.ima.AdErrorEvent } adErrorEvent */ function onAdError(adErrorEvent) { // Handle the error logging. console.log(adErrorEvent.getError()); outstreamLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { renderBanner(); } } function renderBanner() { if (isBanner) { console.log('Outstream: Render Banner'); iinfoOutstreamPosition.innerHTML = ""; iinfoOutstreamPosition.style.height = "330px"; iinfoOutstreamPosition.appendChild(bannerDiv); } else { console.log('Outstream: Banner is not set'); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoOutstreamPosition.remove(); outstreamInit(); } else { return false; } adVolume = 1; return true; } /** * Pauses video content and sets up ad UI. */ function onContentPauseRequested() { videoContent.pause(); // This function is where you should setup UI for showing ads (for example, // display ad timer countdown, disable seeking and more.) // setupUIForAds(); } /** * Resumes video content and removes ad UI. */ function onContentResumeRequested() { videoContent.play(); // This function is where you should ensure that your UI is ready // to play content. It is the responsibility of the Publisher to // implement this function when necessary. // setupUIForContent(); } function onActiveView() { if (outstreamContainer) { const containerOffset = outstreamContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (outstreamPaused) { adsManager.resume(); outstreamPaused = false; } return true; } else { if (!outstreamPaused) { adsManager.pause(); outstreamPaused = true; } } } return false; } let outstreamInitInterval; if (typeof cpexPackage !== "undefined") { outstreamInitInterval = setInterval(tryToInitializeOutstream, 100); } else { const wrapper = getWrapper(); if (wrapper) { let outstreamInitialized = false; window.addEventListener('scroll', () => { if (!outstreamInitialized) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { outstreamInit(); outstreamInitialized = true; } } }); } } function tryToInitializeOutstream() { const wrapper = getWrapper(); if (wrapper) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { if (cpexPackage.adserver.displayed) { clearInterval(outstreamInitInterval); outstreamInit(); } } } else { clearInterval(outstreamInitInterval); } } }
OSZAR »