WDPlayerRenderView.ets 7.83 KB
import componentUtils from '@ohos.arkui.componentUtils';
import { WDPlayerController } from '../controller/WDPlayerController'
import { Logger, WindowModel } from 'wdKit';
import { enableAliPlayer } from '../utils/GlobalSetting';
import json from '@ohos.util.json';
import { JSON } from '@kit.ArkTS';

class Size {
  width: Length = "100%";
  height: Length = "100%";

  constructor(width: Length, height: Length) {
    this.width = width;
    this.height = height;
  }
}

let insIndex: number = 0;
const TAG = 'WDPlayerRenderView'

class MGPlayRenderViewIns {
  static intCount: number = 0;

  static add() {
    MGPlayRenderViewIns.intCount++;
    WindowModel.shared.setWindowKeepScreenOn(true);
    Logger.debug(TAG, "add-- +1")
  }

  static del() {
    Logger.debug(TAG, "del-- -1")
    MGPlayRenderViewIns.intCount--;
    if (MGPlayRenderViewIns.intCount <= 0) {
      WindowModel.shared.setWindowKeepScreenOn(false);
    }
  }
}

/**
 * 播放窗口组件
 */
@Component
export struct WDPlayerRenderView {
  private playerController?: WDPlayerController;
  private xComponentController: XComponentController = new XComponentController();
  private insId: string = "WDPlayRenderView" + insIndex;
  onLoad?: ((event?: object) => void);
  @State videoWidth: number = 16
  @State videoHeight: number = 9
  @State videoRatio: number = 16 / 9
  @State selfSize: Size = new Size('100%', '100%');
  @State topSafeHeight: number = AppStorage.get<number>('topSafeHeight') || 0
  @StorageProp('currentBreakpoint') @Watch("currentChanged") currentBreakpoint: string = 'sm';
  @State isPad: boolean = this.currentBreakpoint == "md" || this.currentBreakpoint == "lg" ? true : false
  // 是否上推视频中
  @Link liftVideo: boolean
  private enableAliPlayer = false

  aboutToAppear() {
    Logger.info(TAG, `aboutToAppear topSafeHeight = ${this.topSafeHeight} isPad = ${this.isPad}`)
    MGPlayRenderViewIns.add();

    insIndex++;
    if (!this.playerController) {
      return
    }

    this.playerController.onVideoSizeChange = (width: number, height: number) => {
      Logger.info(TAG, ` onVideoSizeChange width:${width} height:${height}`)
      this.videoWidth = width;
      this.videoHeight = height;
      this.videoRatio = width / height
      this.updateLayout()
    }
  }

  aboutToDisappear() {
    Logger.info(TAG, `aboutToDisappear`)
    MGPlayRenderViewIns.del();
  }

  build() {
    Row() {
      // 设置为“surface“类型时XComponent组件可以和其他组件一起进行布局和渲染。
      XComponent({
        id: this.insId,
        type: XComponentType.SURFACE,
        libraryname: enableAliPlayer && this.enableAliPlayer ? "premierlibrary" : undefined,
        controller: this.xComponentController
      })// .animation({ duration: 500, curve: Curve.Friction })
        // .animation({
        //   duration: 1200,
        //   curve: Curve.Friction,
        //   delay: 500,
        //   iterations: -1, // 设置-1表示动画无限循环
        //   playMode: PlayMode.Alternate,
        //   expectedFrameRateRange: {
        //     min: 20,
        //     max: 120,
        //     expected: 90,
        //   }
        // })
        .id(this.insId)
        .onLoad(async (event) => {
          Logger.info(TAG, 'onLoad')

          if (this.videoHeight > 0 && this.videoWidth > 0) {
            this.xComponentController.setXComponentSurfaceRect({
              surfaceWidth: this.videoWidth,
              surfaceHeight: this.videoHeight
            });
          }

          if (enableAliPlayer && this.enableAliPlayer) {
            this.playerController?.setSurfaceId(this.insId)
          } else {
            this.playerController?.setXComponentController(this.xComponentController)
          }
          if (this.onLoad) {
            this.onLoad(event)
          }
        })
        .zIndex(1000)
      // .width(this.selfSize.width)
      // .height(this.selfSize.height)
    }
    .onAreaChange(() => {
      this.updateLayout()
    })
    // .animation({
    //   duration: 1200,
    //   curve: Curve.Friction,
    //   delay: 500,
    //   iterations: -1, // 设置-1表示动画无限循环
    //   playMode: PlayMode.Alternate,
    //   expectedFrameRateRange: {
    //     min: 20,
    //     max: 120,
    //     expected: 90,
    //   }
    // })
    // .animation({ duration: 500, curve: Curve.Friction })
    .backgroundColor("#000000")
    .justifyContent(FlexAlign.Center)
    .height('100%')
    .width('100%')
    // .align(this.videoWidth > this.videoHeight ? Alignment.Top : Alignment.Center)
    .align(Alignment.Center)
  }

  updateLayout() {

    let info = componentUtils.getRectangleById(this.insId);
    Logger.debug(TAG, "播放器区域变化:isPad " + this.isPad)
    Logger.debug(TAG, "播放器区域变化: " + JSON.stringify(info))

    Logger.debug(TAG, "xComponent rect: " + JSON.stringify(this.xComponentController.getXComponentSurfaceRect()))

    if (info.size.width > 0 && info.size.height > 0) {

      if (!this.liftVideo) {
        let ratio = this.videoWidth / this.videoHeight
        const height = info.size.width / ratio
        Logger.debug(TAG, "ratio = " + ratio + " ==> new height = " + height)
        if (this.videoHeight > 0 && this.videoWidth > 0) {
          this.xComponentController.setXComponentSurfaceRect({
            surfaceWidth: info.size.width,
            surfaceHeight: info.size.width / this.videoRatio,
            // offsetY: this.isPad ? this.topSafeHeight : (info.size.height - height) / 2
          });
          return
        }
        this.xComponentController.setXComponentSurfaceRect({
          surfaceWidth: info.size.width,
          surfaceHeight: info.size.height,
        });
        return
      }

      // 竖屏
      if (this.videoHeight > 0 && this.videoWidth > 0 && this.videoWidth < this.videoHeight) {
        let ratio = this.videoWidth / this.videoHeight
        const height = info.size.width / ratio

        // 竖屏,缩放高度大于 视频区域高度
        if (height > info.size.height) {

          Logger.debug(TAG, "ratio = " + ratio + " ==> new height = " + height)

          Logger.debug(TAG, "高度固定,求宽度: " + info.size.height * ratio)

          this.xComponentController.setXComponentSurfaceRect({
            surfaceWidth: info.size.height * ratio,
            surfaceHeight: info.size.height,
            offsetY: 0
          });
          return
        }
      } else {
        // 横屏
        let ratio = this.videoWidth / this.videoHeight
        const height = info.size.width / ratio

        // 横屏,缩放高度小 视频区域高度
        if (height < info.size.height) {

          Logger.debug(TAG, "ratio = " + ratio + " ==> new height = " + height)

          Logger.debug(TAG, "宽度固定,求高度: " + height)

          this.xComponentController.setXComponentSurfaceRect({
            surfaceWidth: info.size.width,
            surfaceHeight: height,
            offsetY: (info.size.height - height) / 2
          });
          return
        }
      }

      this.xComponentController.setXComponentSurfaceRect({
        surfaceWidth: info.size.width,
        surfaceHeight: info.size.height,
        offsetY: 0
      });
    }


    // if (info.size.width > 0 && info.size.height > 0 && this.videoHeight > 0 && this.videoWidth > 0) {
    //   if (info.size.width / info.size.height > this.videoWidth / this.videoHeight) {
    //     let scale = info.size.height / this.videoHeight;
    //     this.selfSize = new Size((this.videoWidth * scale / info.size.width) * 100 + "%", '100%');
    //   } else {
    //     let scale = info.size.width / this.videoWidth;
    //     this.selfSize = new Size('100%', (this.videoHeight * scale / info.size.height) * 100 + "%");
    //   }
    // }
  }

  currentChanged() {
    if (this.currentBreakpoint == "md" || this.currentBreakpoint == "lg") {
      //大屏幕  折叠屏 或者ipad
      this.isPad = true
    } else {
      this.isPad = false
    }
  }
}