Electron自定义导航栏

electron默认使用系统自带的导航栏,对于有UI定制需求的产品,需要自定义开发;实现的功能包括title展示、最大化、最小化、调整大小、拖拽位置等等;
 

主进程部分隐藏默认导航栏和菜单栏,监听子进程事件,操作客户端界面

1.通过frame:false和Menu.setApplicationMenu(null)隐藏默认导航栏和菜单;

  const win = new BrowserWindow({
    width: 1000,
    height: 700,
    minWidth: 1000,
    minHeight: 700,
    maxWidth:2560,
    maxHeight:1440,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
      webSecurity: false,
      webviewTag:true
    },
    transparent: true,
    backgroundColor:'rgba(0,0,0,0)',
    frame:false
  });
  Menu.setApplicationMenu(null);

2.封装titleBar.js实现最小化、最大化、还原、拖拽位置;
windows上设置=>显示设置=>缩放 不是100%时,窗口会拖拽放大,所以在拖拽时还需要设置大小;
拖拽调整位置时如果失去焦点则终止调整

const { ipcMain, screen } = require('electron')

exports.initTitleBar = function (win) {
  let canMoving = false;
  let movingInterval = null;

  function windowMove(orderCanMoving) {
    canMoving = orderCanMoving;
    if (canMoving) {
      // 读取原位置
      const winPosition = win.getPosition();
      // 获取当前缩放[width, height]
      const winSize = win.getSize();
      let winStartSize = { w: winSize[0], h: winSize[1] };
      let winStartPosition = { x: winPosition[0], y: winPosition[1] };
      let mouseStartPosition = screen.getCursorScreenPoint();
      console.log('winPosition:', winPosition,',mouseStartPosition:',mouseStartPosition)
      // 清除定时器
      if (movingInterval) {
        clearInterval(movingInterval);
      }
      // 新开
      movingInterval = setInterval(() => {
        // 实时更新位置
        const cursorPosition = screen.getCursorScreenPoint();
        const x = winStartPosition.x + cursorPosition.x - mouseStartPosition.x;
        const y = winStartPosition.y + cursorPosition.y - mouseStartPosition.y;
        // 更新位置的同时设置窗口原大小, windows上设置=>显示设置=>缩放 不是100%时,窗口会拖拽放大
        win.setBounds({
          x: x,
          y: y,
          width: winStartSize.w,
          height: winStartSize.h,
        })

      }, 10);
    } else {
      if (movingInterval) {
        clearInterval(movingInterval);
        movingInterval = null;

      }
    }
  }

  ipcMain.on('min-app', () => {
    if(win){
      win.minimize()
    }
  })

  ipcMain.on('max-app', () => {
    if(win){
      win.maximize()
    }
  })

  ipcMain.on('restore-app', () => {
    if(win){
      if(win.isMaximized()){
        // win.restore()
        win.unmaximize();
      }else{
        win.maximize()
      }
    }
  })

  ipcMain.on('getIsMaximized',async(e,data)=>{
    e.returnValue = { 
      isMaximized: win.isMaximized()
    };
  });

  ipcMain.on('close-app', () => {
    if(win) {
      win.close()
    }
  })

  ipcMain.on("window-move-open", (events, orderCanMoving) => {
    windowMove(orderCanMoving);
  });

  ipcMain.on('setSize', (events,data) => {
    if(win) {
      win.setSize(data.width,data.height);
      win.setMinimumSize(data.width,data.height);
      win.center();
    }
  })

  ipcMain.on('setResizable', (events,data) => {
    if(win) {
      win.setResizable(data);
    }
  })

  // 监听窗口失去焦点事件
  win.on('blur', () => {
    windowMove(false);
  });

}

子进程实现界面显示和功能交互

客户端顶部进行拖拽和调整大小有个边界值,需要添加判断逻辑

function Head({handleCheckAppUpdata,version}){
  const { isInLive } = useIsInLive((state) => state);
  const menuOptions = [
    {
      label:'刷新',value:'1'
    },
    // {
    //   label:'清除缓存',value:'2'
    // },
    {
      label:'检查升级',value:'3'
    },
    // {
    //   label:'关于',value:'4'
    // },
    {
      label:'退出',value:'5'
    },

  ]

  function menuAction(menu){
    switch (menu.value) {
      case '1':
        EE.emit(EEName.APP_REFRESH);
        break;
      case '2':
        message.success('清除成功');
        break;
      case '3':
        handleCheckAppUpdata(true);
        break;
      case '5':
        if(isInLive){
          message.warning('正在直播中,请先结束直播');
        }else{
          logout();
        }
        break;
    
      default:
        break;
    }
  }

  function handleMouseup(){
    ipcRenderer.send('window-move-open',false)
  }

  useEffect(() => {
    document.removeEventListener('mouseup', handleMouseup);
    document.addEventListener('mouseup', handleMouseup);
  }, []);

  return (
    <div className='headWrap'>
      <div className='appTitle'
        onMouseDown={(e)=>{
          try {
            //边界值5,小于5触发调整客户端大小事件
            if(e.clientY<5){
              ipcRenderer.send('window-move-open',false)
              return
            };
          } catch (error) {

          }
          ipcRenderer.send('window-move-open',true)
        }} 
        onMouseUp={()=>{ipcRenderer.send('window-move-open',false)}}
        // onMouseLeave={()=>{ipcRenderer.send('window-move-open',false)}}
        onDoubleClick={()=>{ipcRenderer.send('restore-app')}}
      >直播助手<span className='version'>{version}</span></div>
      <div className='appOptions'>
        <PopoverPicker
          className='appPopoverPicker'
          options={menuOptions}
          onChange={menuAction} 
          trigger='click'
          showCheckIcon={false}
          placement='bottom'
        >
          <div className='appMenu'></div>
        </PopoverPicker>
        {/* <div className='appRefesh'></div> */}
        <div className='appLine'></div>
        <div className='appMin' onClick={()=>{ipcRenderer.send('min-app')}}></div>
        <div className='appRestore' onClick={()=>{ipcRenderer.send('restore-app')}}></div>
        {/* <div className='appMax' onClick={()=>{ipcRenderer.send('max-app')}}></div> */}
        <div className='appClose' onClick={()=>{
          confirm({
            title: '确认退出',
            //@ts-ignore
            icon: <ExclamationCircleFilled />,
            content: `${!!isInLive?'正在直播中,请先结束直播':'确认退出直播助手吗?'}`,
            onOk() {
              !isInLive && ipcRenderer.send('close-app')
            },
            onCancel() {
            },
            okText:'确认',
            cancelText:'取消'
          });
        }}></div>
      </div>
    </div>
  )
}



 

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Electron 中,可以使用自定义 HTML/CSS/JavaScript 来创建应用程序的操作栏,并使用 Electron 的 API 来使其可拖拽。以下是一个简单的示例: 1. 创建一个 HTML 文件,用于定义操作栏的外观和布局。 ``` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Custom Toolbar</title> <style> /* 操作栏样式 */ .toolbar { background-color: #333; color: white; height: 30px; padding: 5px; -webkit-app-region: drag; } /* 操作栏中按钮的样式 */ .toolbar button { background-color: transparent; border: none; color: white; cursor: pointer; font-size: 16px; margin-right: 10px; outline: none; } </style> </head> <body> <div class="toolbar"> <button id="close">X</button> <button id="minimize">-</button> <button id="maximize">+</button> </div> </body> </html> ``` 2. 在 Electron 的主进程中创建窗口,并将该 HTML 文件加载到该窗口中。 ``` const { app, BrowserWindow } = require('electron') function createWindow() { const win = new BrowserWindow({ width: 800, height: 600, frame: false, // 隐藏默认操作栏 webPreferences: { nodeIntegration: true } }) win.loadFile('toolbar.html') // 加载操作栏 HTML 文件 // 允许拖拽窗口 win.on('maximize', () => { win.webContents.send('maximized') }) win.on('unmaximize', () => { win.webContents.send('unmaximized') }) } app.whenReady().then(createWindow) ``` 3. 在 HTML 文件中添加 JavaScript 代码,以便在用户点击操作栏按钮时执行相应的窗口操作。 ``` const { ipcRenderer, remote } = require('electron') // 通过 IPC 通信接收窗口最大化/还原事件 ipcRenderer.on('maximized', () => { document.getElementById('maximize').innerHTML = '-' }) ipcRenderer.on('unmaximized', () => { document.getElementById('maximize').innerHTML = '+' }) // 获取当前窗口 const win = remote.getCurrentWindow() // 关闭窗口 document.getElementById('close').addEventListener('click', () => { win.close() }) // 最小化窗口 document.getElementById('minimize').addEventListener('click', () => { win.minimize() }) // 最大化/还原窗口 document.getElementById('maximize').addEventListener('click', () => { if (win.isMaximized()) { win.unmaximize() } else { win.maximize() } }) ``` 4. 使用 CSS 的 `drag` 属性,使操作栏可拖拽。 ``` .toolbar { -webkit-app-region: drag; } ``` 以上是一个简单的示例,您可以根据自己的需求进行扩展。注意,在使用自定义操作栏时,需要禁用 Electron 默认的操作栏(通过设置 `frame: false`)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值