diff --git a/src/js/api/Api.js b/src/js/api/Api.js index 4f5950dc..da662b1c 100755 --- a/src/js/api/Api.js +++ b/src/js/api/Api.js @@ -400,7 +400,22 @@ const Api = function (container) { OvenPlayerConsole.log("API : getPlaybackRate() ", currentProvider.getPlaybackRate()); return currentProvider.getPlaybackRate(); }; + that.setZoomFactor = (zoomFactor) => { + if (!currentProvider) { + return null; + } + OvenPlayerConsole.log("API : setZoomFactor() ", zoomFactor); + return currentProvider.setZoomFactor(playerConfig.setZoomFactor(zoomFactor)); + }; + that.getZoomFactor = () => { + if (!currentProvider) { + return null; + } + + OvenPlayerConsole.log("API : getZoomFactor() ", currentProvider.getZoomFactor()); + return currentProvider.getZoomFactor(); + }; that.getPlaylist = () => { OvenPlayerConsole.log("API : getPlaylist() ", playlistManager.getPlaylist()); return playlistManager.getPlaylist(); diff --git a/src/js/api/Configurator.js b/src/js/api/Configurator.js index c3c0835f..2388c660 100755 --- a/src/js/api/Configurator.js +++ b/src/js/api/Configurator.js @@ -37,6 +37,7 @@ const Configurator = function(options, provider){ fullscreenOption: null, showBigPlayButton: true, doubleTapToSeek: false, + showZoomSettings: false, }; const serialize = function (val) { if (val === undefined) { @@ -165,7 +166,13 @@ const Configurator = function(options, provider){ spec.playbackRate = playbackRate; return playbackRate; }; - + that.getZoomFactor =()=>{ + return spec.zoomFactor; + }; + that.setZoomFactor =(zoomFactor)=>{ + spec.zoomFactor = zoomFactor; + return zoomFactor; + }; that.getQualityLabel = () => { return spec.qualityLabel; }; diff --git a/src/js/api/constants.js b/src/js/api/constants.js index 471a8c9d..3e44ec0e 100755 --- a/src/js/api/constants.js +++ b/src/js/api/constants.js @@ -58,6 +58,7 @@ export const PLAYER_LOADING = "loading"; export const PLAYER_FULLSCREEN_REQUEST = "fullscreenRequested"; export const PLAYER_FULLSCREEN_CHANGED = "fullscreenChanged"; export const PLAYER_WARNING = "warning"; +export const PLAYER_ZOOM_CAHNGED = "zoomChanged"; export const AD_CHANGED = "adChanged"; export const AD_TIME = "adTime"; @@ -140,7 +141,8 @@ export const SYSTEM_TEXT = [ "quality": "Quality", "audioTrack": "Audio", "caption": "Caption", - "display": "Display" + "display": "Display", + "zoom": "Zoom" } }, "api": { @@ -299,7 +301,8 @@ export const SYSTEM_TEXT = [ "quality": "품질", "audioTrack": "오디오", "caption": "자막", - "display": "표시" + "display": "표시", + "zoom": "Zoom" } }, "api": { @@ -458,7 +461,8 @@ export const SYSTEM_TEXT = [ "quality": "Jakość", "audioTrack": "Audio", "caption": "Podtytuł", - "display": "Wyświetlacz" + "display": "Wyświetlacz", + "zoom": "Zoom" } }, "api": { diff --git a/src/js/api/provider/html5/Provider.js b/src/js/api/provider/html5/Provider.js index 5025ff72..75440391 100644 --- a/src/js/api/provider/html5/Provider.js +++ b/src/js/api/provider/html5/Provider.js @@ -10,7 +10,7 @@ import { WARN_MSG_MUTEDPLAY, UI_ICONS, PLAYER_WARNING, STATE_IDLE, STATE_PLAYING, STATE_PAUSED, STATE_COMPLETE, STATE_ERROR, - PLAYER_STATE, PLAYER_COMPLETE, PLAYER_PAUSE, PLAYER_PLAY, STATE_AD_PLAYING, STATE_AD_PAUSED, + PLAYER_STATE, PLAYER_COMPLETE, PLAYER_PAUSE, PLAYER_PLAY, PLAYER_ZOOM_CAHNGED, STATE_AD_PLAYING, STATE_AD_PAUSED, CONTENT_META, CONTENT_TIME, CONTENT_CAPTION_CUE_CHANGED, CONTENT_SOURCE_CHANGED, AD_CLIENT_GOOGLEIMA, AD_CLIENT_VAST, PLAYBACK_RATE_CHANGED, CONTENT_MUTE, PROVIDER_HTML5, PROVIDER_WEBRTC, PROVIDER_DASH, PROVIDER_HLS @@ -50,6 +50,7 @@ const Provider = function (spec, playerConfig, onExtendedLoad) { listener = EventsListener(elVideo, that, ads ? ads.videoEndedCallback : null, playerConfig); elVideo.playbackRate = elVideo.defaultPlaybackRate = playerConfig.getPlaybackRate(); + spec.zoomFactor = 1.0; const _load = (lastPlayPosition) => { @@ -381,7 +382,13 @@ const Provider = function (spec, playerConfig, onExtendedLoad) { } return elVideo.playbackRate; }; - + that.getZoomFactor = () => { + return spec.zoomFactor; + }; + that.setZoomFactor = (zoomFactor) => { + that.trigger(PLAYER_ZOOM_CAHNGED, { zoomFactor: zoomFactor }); + return spec.zoomFactor = zoomFactor; + }; that.getSources = () => { if (!elVideo) { return []; diff --git a/src/js/view/components/controls/settingButton.js b/src/js/view/components/controls/settingButton.js index 68248140..4c683545 100644 --- a/src/js/view/components/controls/settingButton.js +++ b/src/js/view/components/controls/settingButton.js @@ -15,7 +15,8 @@ let PANEL_TITLE = { "quality": "Quality", "audioTrack": "Audio", "caption": "Caption", - "display": "Display" + "display": "Display", + "zoom": "Zoom" }; const SettingButton = function ($container, api) { let panelManager = PanelManager(); @@ -51,6 +52,8 @@ const SettingButton = function ($container, api) { let framerate = api.getFramerate(); + let allowZoom = playerConfig.showZoomSettings; + if (currentSource) { let body = { title: PANEL_TITLE.speed, @@ -61,6 +64,7 @@ const SettingButton = function ($container, api) { }; panel.body.push(body); } + if (sources && sources.length > 1) { let body = { @@ -123,6 +127,17 @@ const SettingButton = function ($container, api) { panel.body.push(body); } + if (allowZoom) { + let body = { + title: PANEL_TITLE.zoom, + value: Math.round(api.getZoomFactor() * 100) + "%", + description: Math.round(api.getZoomFactor() * 100) + "%", + panelType: "zoom", + hasNext: true + }; + panel.body.push(body); + } + return panel; }; diff --git a/src/js/view/components/controls/settingPanel/main.js b/src/js/view/components/controls/settingPanel/main.js index 6e32b74e..9c6345f5 100644 --- a/src/js/view/components/controls/settingPanel/main.js +++ b/src/js/view/components/controls/settingPanel/main.js @@ -7,18 +7,20 @@ import LA$ from 'utils/likeA$'; import _ from "utils/underscore"; import sizeHumanizer from "utils/sizeHumanizer"; import SpeedPanel from "view/components/controls/settingPanel/speedPanel"; +import ZoomPanel from "view/components/controls/settingPanel/zoomPanel"; import SourcePanel from "view/components/controls/settingPanel/sourcePanel"; import QualityPanel from "view/components/controls/settingPanel/qualityPanel"; import AudioTrackPanel from "view/components/controls/settingPanel/audioTrackPanel"; import CaptionPanel from "view/components/controls/settingPanel/captionPanel"; import TimeDisplayPanel from "view/components/controls/settingPanel/timeDisplayPanel"; import { - CONTENT_LEVEL_CHANGED, PROVIDER_RTMP + CONTENT_LEVEL_CHANGED, PLAYER_ZOOM_CAHNGED } from "api/constants"; -import {AUDIO_TRACK_CHANGED} from "../../../../api/constants"; +import { AUDIO_TRACK_CHANGED } from "../../../../api/constants"; let PANEL_TITLE = { "speed": "Speed", + "zoom": "Zoom", "speedUnit": "x", "source": "Source", "quality": "Quality", @@ -64,6 +66,32 @@ const Panels = function ($container, api, data) { panel.body.push(body); } + } else if (panelType === "zoom") { + let bodyIn = { + title: "+5%", + isCheck: false, + value: 0.05, + description: 0.05, + panelType: panelType + }; + let body = { + title: "100%", + isCheck: false, + value: 0, + description: 1.0, + panelType: panelType + }; + let bodyOut = { + title: "-5%", + isCheck: false, + value: -0.05, + description: -0.05, + panelType: panelType + }; + panel.body.push(bodyIn); + panel.body.push(body); + panel.body.push(bodyOut); + } else if (panelType === "source") { let sources = api.getSources(); for (let i = 0; i < sources.length; i++) { @@ -182,11 +210,23 @@ const Panels = function ($container, api, data) { let $panel = LA$(panel); - if($panel.attr("op-panel-type") === "audioTrack"){ + if ($panel.attr("op-panel-type") === "audioTrack") { $panel.find(".op-setting-item-value").text(api.getAudioTracks()[data.currentAudioTrack].label); } }); }, template); + + + api.on(PLAYER_ZOOM_CAHNGED, function (data) { + _.forEach($root.find("#" + template.data.id).find(".op-setting-item").get() || [], function (panel) { + + let $panel = LA$(panel); + + if ($panel.attr("op-panel-type") === "zoom") { + $panel.find(".op-setting-item-value").text(Math.round(data.zoomFactor * 100) + "%"); + } + }); + }, template); }; const onDestroyed = function (template) { api.off(CONTENT_LEVEL_CHANGED, null, template); @@ -203,6 +243,8 @@ const Panels = function ($container, api, data) { let panel = null; if (panelType === "speed") { panel = SpeedPanel($container, api, extractSubPanelData(api, panelType)); + } else if (panelType === "zoom") { + panel = ZoomPanel($container, api, extractSubPanelData(api, panelType)); } else if (panelType === "source") { panel = SourcePanel($container, api, extractSubPanelData(api, panelType)); } else if (panelType === "quality") { diff --git a/src/js/view/components/controls/settingPanel/zoomPanel.js b/src/js/view/components/controls/settingPanel/zoomPanel.js new file mode 100644 index 00000000..92d6a85e --- /dev/null +++ b/src/js/view/components/controls/settingPanel/zoomPanel.js @@ -0,0 +1,54 @@ +import OvenTemplate from 'view/engine/OvenTemplate'; +import PanelManager from "view/global/PanelManager"; +import LA$ from 'utils/likeA$'; + + +const ZoomPanel = function($container, api, data){ + const $root = LA$(api.getContainerElement()); + const media = $root.find(".op-media-element-container"); + + let panelManager = PanelManager(); + let zoomProperty = "--mediaZoom"; + + data.setFront = function(isFront){ + if(isFront){ + $root.find("#"+data.id).removeClass("background"); + }else{ + $root.find("#"+data.id).addClass("background"); + } + }; + const onRendered = function($current, template){ + //Do nothing + }; + const onDestroyed = function(template){ + //Do nothing + }; + const events = { + "click .op-setting-item": function (event, $current, template) { + event.preventDefault(); + let offset = LA$(event.currentTarget).attr("op-data-value"); + let zoomFactor = api.getZoomFactor(); + + if (offset == 0) { + zoomFactor = 1.0; + } else { + zoomFactor = parseFloat(zoomFactor) + parseFloat(offset); + } + + if (zoomFactor <= 0 ) { + zoomFactor = 0 + } + + media.get().style.setProperty(zoomProperty, api.setZoomFactor(parseFloat(zoomFactor).toFixed(2))); + }, + "click .op-setting-title" : function(event, $current, template){ + event.preventDefault(); + panelManager.removeLastItem(); + } + }; + + return OvenTemplate($container, "ZoomPanel", api.getConfig(), data, events, onRendered, onDestroyed ); + +}; + +export default ZoomPanel; \ No newline at end of file diff --git a/src/js/view/engine/Templates.js b/src/js/view/engine/Templates.js index 4bbf0848..cab01fbe 100644 --- a/src/js/view/engine/Templates.js +++ b/src/js/view/engine/Templates.js @@ -23,6 +23,7 @@ import TimeDisplayTemplate from 'view/components/controls/timeDisplayTemplate'; import FullScreenButtonTemplate from 'view/components/controls/fullScreenButtonTemplate'; import PanelsTemplate from 'view/components/controls/settingPanel/mainTemplate'; import SpeedPanelTemplate from 'view/components/controls/settingPanel/mainTemplate'; +import ZoomPanelTemplate from 'view/components/controls/settingPanel/mainTemplate'; import SourcePanelTemplate from 'view/components/controls/settingPanel/mainTemplate'; import QualityPanelTemplate from 'view/components/controls/settingPanel/mainTemplate'; import AudioTrackPanelTemplate from 'view/components/controls/settingPanel/mainTemplate'; @@ -52,6 +53,7 @@ const Templates = { FullScreenButtonTemplate, PanelsTemplate, SpeedPanelTemplate, + ZoomPanelTemplate, SourcePanelTemplate, QualityPanelTemplate, AudioTrackPanelTemplate, diff --git a/src/stylesheet/ovenplayer.less b/src/stylesheet/ovenplayer.less index 509d2d01..6acdac09 100644 --- a/src/stylesheet/ovenplayer.less +++ b/src/stylesheet/ovenplayer.less @@ -271,6 +271,7 @@ top: 0px; width: 100%; height: 100%; + transform: scale(var(--mediaZoom)); video { position: absolute;