使用 electron 实现类似新版 QQ 的登录界面效果(阴影、背景动画、窗体3D翻转)


Posted in Javascript onOctober 23, 2018

现在什么都讲究追赶潮流,觉得 QQ 登录窗口做的效果不错,既然刚学习 electron ,那么就用 electron 模仿一下。其实主要用到的就是 CSS3 的效果:边框圆角、阴影,3D变换。对,就这么简单。先上效果:

使用 electron 实现类似新版 QQ 的登录界面效果(阴影、背景动画、窗体3D翻转)

下面是关键代码:

app.js

'use strict';
const { app, BrowserWindow } = require('electron')
const path = require('path')
const url = require('url')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win
function createWindow() {
  // Create the browser window.
  win = new BrowserWindow({
    width: 495, height: 470, /*skipTaskbar: true,*/ frame: false,
    resizable: false, transparent: true, show: false, alwaysOnTop: true
  })
  win.once('ready-to-show', () => {
    win.show()
  })
  // and load the index.html of the app.
  win.loadURL(url.format({
    pathname: path.join(__dirname, '/app/index.html'),
    protocol: 'file:',
    slashes: true
  }))
  // Open the DevTools.
  //win.webContents.openDevTools()
  // Emitted when the window is closed.
  win.on('closed', () => {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    win = null
  })
}
//app.disableHardwareAcceleration();
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})
app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (win === null) {
    createWindow()
  }
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

index.html

<!DOCTYPE html>
<html style="margin:0; padding:0;height:100%;">
<head>
  <meta charset="UTF-8">
  <title>QQ Login</title>
  <style>
    html, body {
      margin: 0;
      padding: 0;
      width: 100%;
      height: 100%;
    }

    body {
      perspective: 800px;
      -webkit-app-region: drag;
      -webkit-user-select: none;
    }

    input[type="submit"],
    input[type="reset"],
    input[type="button"],
    input[type="text"],
    button,
    textarea {
      -webkit-app-region: no-drag;
    }

    .shadow {
      box-shadow: 0 0 10px rgba(0, 0, 0, 1);
      position: absolute;
      width: 100%;
      height: 100%;
      border-radius: 4px;
    }

    #login-back {
      position: relative;
      border-radius: 3px 3px 0 0;
      left: 0;
      right: 0;
      height: 180px;
    }

    #card {
      left: 33px;
      top: 70px;
      right: 33px;
      bottom: 70px;
      background-color: #ebf2f9;
      position: absolute;
      -webkit-transition: -webkit-transform .6s ease-in-out;
      transition: transform .6s ease-in-out;
      -webkit-transform-style: preserve-3d;
      transform-style: preserve-3d;
      border-radius: 4px;
    }

      #card.flipped {
        -webkit-transform: rotateY( 180deg );
        transform: rotateY( 180deg );
      }

      #card .front {
        background: url(imgs/login-back.gif) no-repeat;
        background-size: 100% 180px;
        position: absolute;
        transform: rotateY(0deg);
      }

      #card .back {
        position: absolute;
        background: url(imgs/login-back.gif) no-repeat;
        background-size: 100% 180px;
        -webkit-transform: rotateY( -180deg );
        transform: rotateY( -180deg );
        -webkit-backface-visibility: hidden;
        backface-visibility: hidden;
        z-index:2;
      }

    .sys-control-box {
      float:right;
      width:84px;
      border-radius: 0 3px 0 0;
    }

    .sys-btn {
      width: 28px;
      height: 28px;
      border: none;
      outline: none;
      margin: 0;
    }

    .sys-btn-mini {
      background: url(imgs/btn_mini_normal.png) no-repeat;
    }

      .sys-btn-mini:hover {
        background: url(imgs/btn_mini_highlight.png) no-repeat;
      }

      .sys-btn-mini:active {
        background: url(imgs/btn_mini_down.png) no-repeat;
      }

    .sys-btn-close {
      border-radius: 0 3px 0 0;
      background: url(imgs/btn_close_normal.png) no-repeat;
    }

      .sys-btn-close:hover {
        background: url(imgs/btn_close_highlight.png) no-repeat;
      }

      .sys-btn-close:active {
        background: url(imgs/btn_close_down.png) no-repeat;
      }

    .sys-btn-set {
      background: url(imgs/btn_set_normal.png) 1px 0 no-repeat;
    }

      .sys-btn-set:hover {
        background: url(imgs/btn_set_hover.png) 1px 0 no-repeat;
      }

      .sys-btn-set:active {
        background: url(imgs/btn_set_press.png) 1px 0 no-repeat;
      }

    .btn {
      width: 78px;
      height: 28px;
      background: url(imgs/setting_btn_normal.png) no-repeat;
      background-size: 100% 100%;
      border: none;
      outline: none;
      margin: 0;
    }

      .btn:hover, .btn:active {
        background: url(imgs/setting_btn_hover.png) no-repeat;
        background-size: 100% 100%;
      }

      .btn:focus {
        background: url(imgs/setting_btn_hover.png) no-repeat;
        background-size: 100% 100%;
      }
  </style>
</head>
<body>
  <div id="card">
    <div id="front" class="front shadow">
      <div class="sys-control-box">
        <button id="btn-set" class="sys-btn sys-btn-set" title="设置"></button><button class="sys-btn sys-btn-mini" title="最小化"></button><button class="sys-btn sys-btn-close" title="关闭"></button>
      </div>
    </div>
    <div id="back" class="back shadow">
      <div style="width:100%;height:100%; border-radius: 4px;background:-webkit-linear-gradient(top, rgba(0, 0, 0, 0.00) 0%, rgba(0, 0, 0, 0.00) 6%, #ebf2f9 12%, #ebf2f9 90%, #cde2f2 90%, #cde2f2 100%);">
        <div class="sys-control-box" style="width:56px;">
          <button class="sys-btn sys-btn-mini" title="最小化"></button><button class="sys-btn sys-btn-close" title="关闭"></button>
        </div>
        <button id="btn-ok" style="position:absolute; right:91px; bottom:2px;" class="btn">确定</button>
        <button id="btn-cancel" style="position:absolute; right:10px; bottom:2px;" class="btn">取消</button>
      </div>
    </div>
  </div>
  <script>
    Element.prototype.hasClassName = function (a) {
      return new RegExp("(?:^|\\s+)" + a + "(?:\\s+|$)").test(this.className);
    };

    Element.prototype.addClassName = function (a) {
      if (!this.hasClassName(a)) {
        this.className = [this.className, a].join(" ");
      }
    };

    Element.prototype.removeClassName = function (b) {
      if (this.hasClassName(b)) {
        var a = this.className;
        this.className = a.replace(new RegExp("(?:^|\\s+)" + b + "(?:\\s+|$)", "g"), " ");
      }
    };

    Element.prototype.toggleClassName = function (a) {
      this[this.hasClassName(a) ? "removeClassName" : "addClassName"](a);
    };

    //var init = function () {
    //  var card = document.getElementById('card');

    //  document.getElementById('front').addEventListener('click', function () {
    //    card.toggleClassName('flipped');
    //  }, false);

    //  document.getElementById('back').addEventListener('click', function () {
    //    card.toggleClassName('flipped');
    //  }, false);
    //};

    //window.addEventListener('DOMContentLoaded', init, false);
    (function () {

      const remote = require('electron').remote;

      function init() {

        function flip() {
          if (frontShow == 2) {
            document.getElementById('front').style.display = 'block';
          }
          else {
            document.getElementById('back').style.display = 'block';
          }
          card.toggleClassName('flipped');
        };

        var btn_minis = document.getElementsByClassName("sys-btn-mini");
        for (var i = 0; i < btn_minis.length; i++) {
          btn_minis[i].addEventListener("click", function (e) {
            const window = remote.getCurrentWindow();
            window.minimize();
          });
        }

        //document.getElementById("sys-btn-maxi").addEventListener("click", function (e) {
        //  const window = remote.getCurrentWindow();
        //  if (!window.isMaximized()) {
        //    window.maximize();
        //  } else {
        //    window.unmaximize();
        //  }
        //});

        var btn_closes = document.getElementsByClassName("sys-btn-close");
        for (var i = 0; i < btn_closes.length; i++) {
          btn_closes[i].addEventListener("click", function (e) {
            const window = remote.getCurrentWindow();
            window.close();
          });
        }   

        var card = document.getElementById('card');
        var frontShow = 1;

        var btn_sets = document.getElementsByClassName("sys-btn-set");
        for (var i = 0; i < btn_sets.length; i++) {
          btn_sets[i].addEventListener('click', function () { flip(); }, false);
        } 

        card.addEventListener('transitionend', function () {
          if (frontShow == 1) {
            frontShow = 2;
            document.getElementById('front').style.display = 'none';
          }
          else {
            document.getElementById('back').style.display = 'none';
            frontShow = 1;
          }
        }, false);

        document.getElementById('btn-ok').addEventListener('click', function () { flip(); }, false);
        document.getElementById('btn-cancel').addEventListener('click', function () { flip(); }, false);
      };

      document.onreadystatechange = function () {
        if (document.readyState == "complete") {
          init();
        }
      };
    })();
  </script>
</body>
</html>

最后整个项目的源代码:https://github.com/starts2000/ElectronQQLogin

总结

以上所述是小编给大家介绍的使用 electron 实现类似新版 QQ 的登录界面效果(阴影、背景动画、窗体3D翻转),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
理解Javascript_06_理解对象的创建过程
Oct 15 Javascript
js+数组实现网页上显示时间/星期几的实用方法
Jan 18 Javascript
Textbox控件注册回车事件及触发按钮提交事件具体实现
Mar 04 Javascript
JS实现进入页面时渐变背景色的方法
Feb 25 Javascript
jQuery延迟加载图片插件Lazy Load使用指南
Mar 25 Javascript
BootStrap Fileinput初始化时的一些参数
Dec 30 Javascript
Vuex之理解Getters的用法实例
Apr 19 Javascript
javaScript中的空值和假值
Dec 18 Javascript
vue项目中用cdn优化的方法
Jan 03 Javascript
React Native 真机断点调试+跨域资源加载出错问题的解决方法
Jan 18 Javascript
layui实现table加载的示例代码
Aug 14 Javascript
微信小程序学习总结(三)条件、模板、文件引用实例分析
Jun 04 Javascript
解决JavaScript中0.1+0.2不等于0.3问题
Oct 23 #Javascript
React 路由懒加载的几种实现方案
Oct 23 #Javascript
react 兄弟组件如何调用对方的方法示例
Oct 23 #Javascript
详解React 的几种条件渲染以及选择
Oct 23 #Javascript
详解create-react-app 2.0版本如何启用装饰器语法
Oct 23 #Javascript
彻底弄懂 JavaScript 执行机制
Oct 23 #Javascript
深入理解JavaScript 中的执行上下文和执行栈
Oct 23 #Javascript
You might like
PHP回调函数与匿名函数实例详解
2017/08/16 PHP
javascript中的107个基础知识收集整理 推荐
2010/03/29 Javascript
Javascript 设计模式(二) 闭包
2010/05/26 Javascript
为Extjs加加速(javascript加速)
2010/08/19 Javascript
JS中批量给元素绑定事件过程中的相关问题使用闭包解决
2013/04/15 Javascript
JS组件系列之Bootstrap table表格组件神器【二、父子表和行列调序】
2016/05/10 Javascript
JavaScript中removeChild 方法开发示例代码
2016/08/15 Javascript
微信浏览器禁止页面下拉查看网址实例详解
2017/06/28 Javascript
Angular实现的简单查询天气预报功能示例
2017/12/27 Javascript
Angular5给组件本身的标签添加样式class的方法
2018/04/07 Javascript
Vue+mui实现图片的本地缓存示例代码
2018/05/24 Javascript
解决vue无法设置滚动位置的问题
2018/10/07 Javascript
浅谈发布订阅模式与观察者模式
2019/04/09 Javascript
Node.js实现用户评论社区功能(体验前后端开发的乐趣)
2019/05/09 Javascript
vue cli安装使用less的教程详解
2019/07/12 Javascript
js实现左右轮播图
2020/01/09 Javascript
node crawler如何添加promise支持
2020/02/01 Javascript
JavaScript进阶(二)词法作用域与作用域链实例分析
2020/05/09 Javascript
详解vue 组件的实现原理
2020/11/12 Javascript
Python2中的raw_input() 与 input()
2015/06/12 Python
python使用邻接矩阵构造图代码示例
2017/11/10 Python
Python通过cv2读取多个USB摄像头
2019/08/28 Python
Python新手如何进行闭包时绑定变量操作
2020/05/29 Python
全球最大的中文旅行网站:去哪儿网
2017/11/16 全球购物
美国智能家居专家:tink
2019/06/04 全球购物
英国家居装饰品、户外家具和玻璃器皿购物网站:Rinkit.com
2019/11/04 全球购物
说出一些常用的类,包,接口
2014/09/22 面试题
新浪微博实习心得体会
2014/01/27 职场文书
宾馆仓管员岗位职责
2014/07/27 职场文书
党的群众路线整改落实情况汇报
2014/10/28 职场文书
党员教师群众路线思想汇报范文
2014/10/28 职场文书
2014年银行个人工作总结
2014/12/05 职场文书
教师辞职书范文
2015/02/26 职场文书
小学主题班会教案
2015/08/17 职场文书
中学教代会开幕词
2016/03/04 职场文书
MySQL视图概念以及相关应用
2022/04/19 MySQL