使用 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 面向对象的JavaScript类
May 04 Javascript
js监听输入框值的即时变化onpropertychange、oninput
Jul 13 Javascript
文本框根据输入内容自适应高度的代码
Oct 24 Javascript
Javascript计算两个marker之间的距离(Google Map V3)
Apr 26 Javascript
Javascript setInterval的两种调用方法(实例讲解)
Nov 29 Javascript
JavaScript使用循环和分割来替换和删除元素实例
Oct 13 Javascript
jQuery中animate用法实例分析
Mar 09 Javascript
AngularJs页面筛选标签小功能
Aug 01 Javascript
jQuery Easyui DataGrid点击某个单元格即进入编辑状态焦点移开后保存数据
Aug 15 Javascript
js实现做通讯录的索引滑动显示效果和滑动显示锚点效果
Feb 18 Javascript
详解webpack的配置文件entry与output
Aug 21 Javascript
vue.js中父组件调用子组件的内部方法示例
Oct 22 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
Trying to clone an uncloneable object of class Imagic的解决方法
2012/01/11 PHP
php通过array_shift()函数移除数组第一个元素的方法
2015/03/18 PHP
php递归遍历删除文件的方法
2015/04/17 PHP
用javascript实现的支持lrc歌词的播放器
2007/05/17 Javascript
Extjs4 GridPanel 的几种样式使用介绍
2013/04/18 Javascript
iframe子父页面调用js函数示例
2013/11/07 Javascript
jQuery 无限级菜单的简单实例
2014/02/21 Javascript
单击和双击事件的冲突处理示例代码
2014/04/03 Javascript
js计算德州扑克牌面值的方法
2015/03/04 Javascript
jQuery编程中的一些核心方法简介
2015/08/14 Javascript
AngularJs动态加载模块和依赖注入详解
2016/01/11 Javascript
使用原生的javascript来实现轮播图
2017/02/24 Javascript
Vue.js 单页面多路由区域操作的实例详解
2017/07/17 Javascript
Node.js搭建小程序后台服务
2018/01/03 Javascript
JS声明对象时属性名加引号与不加引号的问题及解决方法
2018/02/16 Javascript
[46:02]DOTA2上海特级锦标赛D组资格赛#2 Liquid VS VP第二局
2016/02/28 DOTA
python删除列表中重复记录的方法
2015/04/28 Python
Python中取整的几种方法小结
2017/01/06 Python
Python实现按学生年龄排序的实际问题详解
2017/08/29 Python
对Python 2.7 pandas 中的read_excel详解
2018/05/04 Python
python方法生成txt标签文件的实例代码
2018/05/10 Python
Django上使用数据可视化利器Bokeh解析
2019/07/31 Python
Python面向对象之私有属性和私有方法应用案例分析
2019/12/31 Python
vue学习笔记之动态组件和v-once指令简单示例
2020/02/29 Python
python selenium自动化测试框架搭建的方法步骤
2020/06/14 Python
Python爬虫HTPP请求方法有哪些
2020/06/03 Python
浅谈移动端网页图片预加载方案
2018/11/05 HTML / CSS
斯凯奇美国官网:SKECHERS美国
2016/08/20 全球购物
Expedia印度:您的一站式在线旅游网站
2017/08/24 全球购物
Unineed中文官网:高端护肤美妆与时尚配饰,英国直邮
2020/07/23 全球购物
如何安装ruby on rails
2014/02/09 面试题
大学生优秀自荐信范文
2014/02/25 职场文书
竞选班长演讲稿400字
2014/08/22 职场文书
四查四看整改措施
2014/09/19 职场文书
2014乡党委副书记党建工作汇报材料
2014/11/02 职场文书
研究生毕业登记表的自我鉴定范文
2019/07/15 职场文书