@toc

0. 说明

OH系统版本:OpenHarmony3.1Release
IDE: 3.0.0.900
实现语言:ets

  • APP开屏视频挺常见,dayu200支持视频播放,3.5耳机口也正常输出音频。
  • 表盘在现代车机中很常见,样式多,风格迥异,OHOS API8也支持丰富的2D绘图能力,想要绘制表盘还是相对容易的。捣鼓以上两个是为做智能座舱做准备。将二者结合展示如下:
    m5.gif

    1. 首页视频播放

    1.1 Video组件总结

    参考地址:基于TS的Video组件说明
    Video开发流程如下:

  • 创建视频控制对象:
    //一个VideoController对象可以控制一个或多个video。
    controller: VideoController = new VideoController();
    controller.start()、 pause()、 stop() 、
    setCurrentTime(number,SeekMode)指定进度位置,并指定挑转模式(前后、最近关键帧以及精准跳转)、
    requesFullscreen(boolean)、exitFullscreen()
  • 获取视频路径:@State srcs: Resource = $rawfile('video1'); 网络视频也可以,需要配置INTERNET权限。值得注意的是,还可访问通过Data Ability提供的视频路径,也就是说分布式视频也可以实现的。
  • 设置Video属性:muted(是否静音)、autoPlay(自动播放)、controls(控制栏)、objectFit(显示模式)、loop(是否循环播放)。其中,objectFit参数设置值为ImageFit.Cover则铺满整个容器。
  • Video事件:
    image.png
    这里需要注意到,利用onFinish()事件,可以实现当播放完视频后我们可以直接跳跳转到APP内部。

1.2 开屏视频实现

新建一个基于ETS语言的项目,在index.ets中,先创建视频控制对象,以及视频路径。

 @State srcs: Resource = $r('app.media.aito');
  @State previewUris: Resource = $r('app.media.car_cover'); //预览封面
  controller: VideoController = new VideoController();

在Component中的build下创建Video组件,使用Column容器容纳,

        Column() {
        Video({
          src: this.srcs,
          previewUri: this.previewUris,
          controller: this.controller
        }).width('100%').height('100%')
          .objectFit(ImageFit.Cover)
          .autoPlay(true)
          .controls(false)
          .onStart(() => {
            console.error('onStart');
          })
          .onPause(() => {
            console.error('onPause');
          })
          .onFinish(() => {
            console.error('onFinish');
            router.push({url:'pages/gauge'})
          })
      }.backgroundColor('white').height("100%")

然后再页面创建时运行视频控制的start方法

  onPageShow() {
    this.controller.requestFullscreen(true)
    this.controller.start()
  }

2. Canvas绘制仪表盘

2.1 接口分析

参考地址:画布组件绘制图像的方法很多,这里主要总结常用的以及仪表绘制用到的。

  • 创建CanvasRenderingContext2D对象
    private settings: RenderingContextSettings = new RenderingContextSettings(true);
    private fuel_gauge: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
  • 事件:
    onReady(callback: () => void) 画布组件的事件回调,可以在此时进行绘制。
  • 属性:
    //阴影
    shadowBlur  number  0.0 设置绘制阴影时的模糊级别,值越大越模糊,精度为float。
    shadowColor <color> -   设置绘制阴影时的阴影颜色。
    shadowOffsetX   number  -   设置绘制阴影时和原有对象的水平偏移值。
    shadowOffsetY   number  -   设置绘制阴影时和原有对象的垂直偏移值。
    //颜色
    fillStyle、strokeStyle 
    //线宽、文字样式、线条端点样式
    lineWidth
    front
    lineCap string  ‘butt’  指定线端点的样式,可选值为:
    - ‘butt’:线端点以方形结束。
    - ‘round’:线端点以圆形结束。
    - ‘square’:线端点以方形结束,该样式下会增加一个长度和线段厚度相同,宽度是线段厚度一半的矩形。
  • 提供绘制方法

    //方形
    this.fuel_gauge.fillStyle = '#0000ff'
    this.fuel_gauge.fillRect(20, 160, 150, 100)//起点,宽高
    //边框 不填充
    1. this.context.strokeRect(30, 30, 200, 150)//矩形轮廓
    2. stroke(path?: Path2D): void //绘制轮廓
          this.context.moveTo(25, 25)
          this.context.lineTo(25, 105)
          this.context.strokeStyle = 'rgb(0,0,255)'
          this.context.stroke()
    //删除不要区域- 刷新图形时常用
    clearRect(x: number, y: number, w: number, h: number): void
    //圆形
    arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void
          this.context.beginPath()
          this.context.arc(100, 75, 50, 0, 6.28)
          this.context.stroke()
    //文字
    fillText(text: string, x: number, y: number): void
    //图片
    drawImage(image: ImageBitmap, dx: number, dy: number): void
    drawImage(image: ImageBitmap, dx: number, dy: number, dWidth: number, dHeight: number): void
  • 如何让图动起来
    可以获取系统时间,或者使用setTime来实现动态刷新图像。看起来图形在动其实只是某些结构在转动、移动或者缩放
    //转动
    rotate(rotate: number): void //针对当前坐标轴进行顺时针旋转。
    //缩放
    scale(x: number, y: number): void //设置canvas画布的缩放变换属性,后续的绘制操作将按照缩放比例进行缩放。
  • gauge组件
    说起绘制仪器表盘,gauge组件其实也常用到。和Text组件一样,gauge已经高度定义,我们只能做简单的定义参数。gauge的使用方法如下:
    //图像可以随参数变化
          //电量表
          Gauge({ value: this.fuel_value, min: 0, max: 120 })
            .startAngle(210)
            .endAngle((this.fuel_value))
            .colors([[0xF01020, 1],[0xCFB53B, 1], [0x5BA854, 1]])
            .strokeWidth(20)
            .width(120)
            .height(120)
            .margin({top:30})

    效果如下:
    image.png

2.2 绘制表盘

首先创建2D绘制对象,以及用到的变量

private settings: RenderingContextSettings = new RenderingContextSettings(true);
private car_gauge: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);

然后绘制圆盘与数字:

 //车速表
          Canvas(this.car_gauge)
            .width('45%')
            .height('20%')
            .backgroundColor('#000000')
            .onReady(() => {
              //表环-车速
              this.car_gauge.clearRect(-100, -100, 600, 600);
              this.car_gauge.beginPath()
              this.car_gauge.translate(0, 0)
              this.car_gauge.shadowBlur=30
              this.car_gauge.shadowColor=this.car_gauge_col
              this.car_gauge.arc(this.gauge_speed_x, this.gauge_speed_y, 100, 0, 6.28)
              this.car_gauge.fillStyle = 'black'
              this.car_gauge.fill()
              this.car_gauge.closePath()
              //数字环
              this.car_gauge.beginPath()
              this.car_gauge.translate(this.gauge_speed_x, this.gauge_speed_y)
              this.car_gauge.font = '20px bold'
              this.car_gauge.textAlign = 'center'
              this.car_gauge.textBaseline = "middle"
              this.car_gauge.fillStyle = "#cfb35b"
              for (var i = 0;i < this.car_speed.length; i++) {
                this.car_gauge.fillText(
                  this.car_speed[i],
                  80 * Math.cos(((i * 30 - 60) * Math.PI) / 180),
                  80 * Math.sin(((i * 30 - 60) * Math.PI) / 180)
                );
              }
              this.car_gauge.closePath()
              //速度
              this.car_gauge.beginPath()
              this.car_gauge.translate(-this.gauge_speed_x, -this.gauge_speed_y)
              this.car_gauge.fillStyle = '#0000000'
              //this.car_gauge.fillText("Km/H", 0, 25, 20)
              this.car_gauge.closePath()

绘制指针,指针需要旋转一定角度,所以坐标一定要固定好在圆盘中心

              //速度指针
              this.car_gauge.beginPath()
              this.car_gauge.arc(this.gauge_speed_x, this.gauge_speed_y, 10, 0, 6.28)
              this.car_gauge.fillStyle = 'red'
              this.car_gauge.fill()
              this.car_gauge.closePath()
              var radius = Math.PI / 120 * this.car_velocity
              this.car_gauge.save()
              this.car_gauge.beginPath()
              this.car_gauge.translate(this.gauge_speed_x, this.gauge_speed_y)
              this.car_gauge.lineWidth = 8
              this.car_gauge.strokeStyle = 'red'
              this.car_gauge.lineCap = 'round'
              this.car_gauge.rotate(radius)
              this.car_gauge.moveTo(0, 0)
              this.car_gauge.lineTo(0, 60)
              this.car_gauge.stroke()
              this.car_gauge.closePath()
              this.car_gauge.restore()
            })

表盘效果如下:
image.pngimage.png
使用定时器改变指针旋转角度以及阴影颜色效果,再结合首页视频,得到帖子前面展示的样例。

  update_canvas()
  {
    var that = this;
    that.car_velocity =0
    that.intervalID  = setInterval(function(){
      //      prompt.showToast({
      //        message:"car_velocity"+that.car_velocity,
      //      })
      that.car_velocity +=10;
      that.fuel_value +=20
      if(that.car_velocity>120)
      {
        that.car_gauge_col = 'red'
      }
      if(that.car_velocity>240)
      {
        that.car_velocity=0;
        that.fuel_value=60
        clearInterval(that.intervalID)
      }
    },80)
  }

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com/#bkwz