使用 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 相关文章推荐
jQuery-serialize()输出序列化form表单值的方法
Dec 26 Javascript
博客侧边栏模块跟随滚动条滑动固定效果的实现方法(js+jquery等)
Mar 24 Javascript
JavaScript判断用户是否对表单进行了修改的方法
Mar 18 Javascript
jQuery计算文本框字数及限制文本框字数的方法
Mar 01 Javascript
jquery选择器中的空格与大于号&gt;、加号+与波浪号~的区别介绍
Jun 24 Javascript
angularjs封装$http为factory的方法
May 18 Javascript
html中通过JS获取JSON数据并加载的方法
Nov 30 Javascript
js实现上传并压缩图片效果
Jan 10 Javascript
vue如何将v-for中的表格导出来
May 07 Javascript
React router动态加载组件之适配器模式的应用详解
Sep 12 Javascript
vue 优化CDN加速的方法示例
Sep 19 Javascript
echarts实现折线图的拖拽效果
Dec 19 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
配置支持SSI
2006/11/25 PHP
php+xml结合Ajax实现点赞功能完整实例
2015/01/30 PHP
php源码分析之DZX1.5字符串截断函数cutstr用法
2015/06/17 PHP
thinkPHP内置字符串截取函数用法详解
2016/11/15 PHP
PHP Web表单生成器案例分析
2020/06/02 PHP
php中get_object_vars()在数组的实例用法
2021/02/22 PHP
让angularjs支持浏览器自动填表
2014/11/10 Javascript
jquery实现炫酷的叠加层自动切换特效
2015/02/01 Javascript
jQuery跨域问题解决方案
2015/08/03 Javascript
JavaScript事件 &quot;事件对象&quot;的注意要点
2016/01/14 Javascript
jQuery 局部div刷新和全局刷新方法总结
2016/10/05 Javascript
Bootstrap复选框和单选按钮美化插件(推荐)
2016/11/23 Javascript
详解nodejs 文本操作模块-fs模块(四)
2016/12/22 NodeJs
AngularJS 文件上传控件 ng-file-upload详解
2017/01/13 Javascript
AngularJS之页面跳转Route实例代码
2017/03/10 Javascript
详解angular中通过$location获取路径(参数)的写法
2017/03/21 Javascript
JS插件clipboard.js实现一键复制粘贴功能
2020/12/04 Javascript
JS实现的贪吃蛇游戏完整实例
2019/01/18 Javascript
vue+element 模态框表格形式的可编辑表单实现
2019/06/07 Javascript
微信小程序 自定义复选框实现代码实例
2019/09/04 Javascript
javascript局部自定义鼠标右键菜单
2020/12/08 Javascript
[10:14]2018DOTA2国际邀请赛寻真——paiN Gaming不仅为自己而战
2018/08/14 DOTA
linux系统使用python获取cpu信息脚本分享
2014/01/15 Python
python使用Berkeley DB数据库实例
2014/09/26 Python
django 通过ajax完成邮箱用户注册、激活账号的方法
2018/04/17 Python
python opencv 简单阈值算法的实现
2019/08/04 Python
通过实例了解Python异常处理机制底层实现
2020/07/23 Python
BeautifulSoup中find和find_all的使用详解
2020/12/07 Python
MoviePy简介及Python视频剪辑自动化
2020/12/18 Python
欧舒丹加拿大官网:L’Occitane加拿大
2017/10/29 全球购物
巴西手表购物网站:eclock
2019/03/19 全球购物
美国在线肉类和海鲜配送:Crowd Cow
2020/10/02 全球购物
怎样自定义一个异常类
2016/09/27 面试题
Ruby如何定义一个类
2012/10/08 面试题
卫生院艾滋病宣传活动总结
2015/05/09 职场文书
详解MySQL主从复制及读写分离
2021/05/07 MySQL