From d65381ddc8dccba30ad84945faf12999fe4a9163 Mon Sep 17 00:00:00 2001
From: Your Name <123456>
Date: 星期三, 29 六月 2022 19:37:19 +0800
Subject: [PATCH] 'lct'
---
src/assets/menu/card5.png | 0
src/assets/menu/icon4.png | 0
src/assets/menu/icon5.png | 0
src/assets/loginPage/login_icon_user.png | 0
src/assets/menu/icon11.png | 0
src/assets/menu/icon9.png | 0
static/loginPage.js/login.js | 1545 +++++++++++++++++++++++++++++++++++++++
src/assets/menu/bg_home.jpg | 0
src/assets/menu/icon1.png | 0
src/views/loginPage/loginPage.vue | 160 ++++
src/assets/menu/icon6.png | 0
src/router/route.ts | 10
src/assets/menu/card1.png | 0
src/assets/menu/card4.png | 0
static/loginPage.js/loginApp.js | 137 +++
src/assets/menu/card9.png | 0
src/views/loginPage/component/accountLogin.vue | 207 +++++
src/assets/menu/admin.png | 0
src/assets/menu/icon2.png | 0
src/assets/menu/icon7.png | 0
src/layout/navBars/breadcrumb/user.vue | 2
src/assets/menu/card7.png | 0
src/assets/menu/card2.png | 0
src/assets/menu/card8.png | 0
src/assets/menu/card6.png | 0
src/assets/menu/icon8.png | 0
src/assets/menu/card11.png | 0
src/assets/menu/icon3.png | 0
src/assets/menu/card3.png | 0
src/assets/menu/card10.png | 0
src/views/homeMenu/homeMenu.vue | 277 +++++++
src/assets/menu/icon10.png | 0
src/assets/loginPage/login_icon_password.png | 0
33 files changed, 2,336 insertions(+), 2 deletions(-)
diff --git a/src/assets/loginPage/login_icon_password.png b/src/assets/loginPage/login_icon_password.png
new file mode 100644
index 0000000..1f6653d
--- /dev/null
+++ b/src/assets/loginPage/login_icon_password.png
Binary files differ
diff --git a/src/assets/loginPage/login_icon_user.png b/src/assets/loginPage/login_icon_user.png
new file mode 100644
index 0000000..a113a9b
--- /dev/null
+++ b/src/assets/loginPage/login_icon_user.png
Binary files differ
diff --git a/src/assets/menu/admin.png b/src/assets/menu/admin.png
new file mode 100644
index 0000000..55eeace
--- /dev/null
+++ b/src/assets/menu/admin.png
Binary files differ
diff --git a/src/assets/menu/bg_home.jpg b/src/assets/menu/bg_home.jpg
new file mode 100644
index 0000000..ab60219
--- /dev/null
+++ b/src/assets/menu/bg_home.jpg
Binary files differ
diff --git a/src/assets/menu/card1.png b/src/assets/menu/card1.png
new file mode 100644
index 0000000..d70d653
--- /dev/null
+++ b/src/assets/menu/card1.png
Binary files differ
diff --git a/src/assets/menu/card10.png b/src/assets/menu/card10.png
new file mode 100644
index 0000000..cb8129f
--- /dev/null
+++ b/src/assets/menu/card10.png
Binary files differ
diff --git a/src/assets/menu/card11.png b/src/assets/menu/card11.png
new file mode 100644
index 0000000..2155f53
--- /dev/null
+++ b/src/assets/menu/card11.png
Binary files differ
diff --git a/src/assets/menu/card2.png b/src/assets/menu/card2.png
new file mode 100644
index 0000000..9415cb6
--- /dev/null
+++ b/src/assets/menu/card2.png
Binary files differ
diff --git a/src/assets/menu/card3.png b/src/assets/menu/card3.png
new file mode 100644
index 0000000..b22eae4
--- /dev/null
+++ b/src/assets/menu/card3.png
Binary files differ
diff --git a/src/assets/menu/card4.png b/src/assets/menu/card4.png
new file mode 100644
index 0000000..d29a9f4
--- /dev/null
+++ b/src/assets/menu/card4.png
Binary files differ
diff --git a/src/assets/menu/card5.png b/src/assets/menu/card5.png
new file mode 100644
index 0000000..ee12eb6
--- /dev/null
+++ b/src/assets/menu/card5.png
Binary files differ
diff --git a/src/assets/menu/card6.png b/src/assets/menu/card6.png
new file mode 100644
index 0000000..cc7d602
--- /dev/null
+++ b/src/assets/menu/card6.png
Binary files differ
diff --git a/src/assets/menu/card7.png b/src/assets/menu/card7.png
new file mode 100644
index 0000000..d5bf656
--- /dev/null
+++ b/src/assets/menu/card7.png
Binary files differ
diff --git a/src/assets/menu/card8.png b/src/assets/menu/card8.png
new file mode 100644
index 0000000..a839c27
--- /dev/null
+++ b/src/assets/menu/card8.png
Binary files differ
diff --git a/src/assets/menu/card9.png b/src/assets/menu/card9.png
new file mode 100644
index 0000000..7481ef0
--- /dev/null
+++ b/src/assets/menu/card9.png
Binary files differ
diff --git a/src/assets/menu/icon1.png b/src/assets/menu/icon1.png
new file mode 100644
index 0000000..bef5341
--- /dev/null
+++ b/src/assets/menu/icon1.png
Binary files differ
diff --git a/src/assets/menu/icon10.png b/src/assets/menu/icon10.png
new file mode 100644
index 0000000..0f1d961
--- /dev/null
+++ b/src/assets/menu/icon10.png
Binary files differ
diff --git a/src/assets/menu/icon11.png b/src/assets/menu/icon11.png
new file mode 100644
index 0000000..392b926
--- /dev/null
+++ b/src/assets/menu/icon11.png
Binary files differ
diff --git a/src/assets/menu/icon2.png b/src/assets/menu/icon2.png
new file mode 100644
index 0000000..5ca9d63
--- /dev/null
+++ b/src/assets/menu/icon2.png
Binary files differ
diff --git a/src/assets/menu/icon3.png b/src/assets/menu/icon3.png
new file mode 100644
index 0000000..c512b58
--- /dev/null
+++ b/src/assets/menu/icon3.png
Binary files differ
diff --git a/src/assets/menu/icon4.png b/src/assets/menu/icon4.png
new file mode 100644
index 0000000..1088209
--- /dev/null
+++ b/src/assets/menu/icon4.png
Binary files differ
diff --git a/src/assets/menu/icon5.png b/src/assets/menu/icon5.png
new file mode 100644
index 0000000..28200e7
--- /dev/null
+++ b/src/assets/menu/icon5.png
Binary files differ
diff --git a/src/assets/menu/icon6.png b/src/assets/menu/icon6.png
new file mode 100644
index 0000000..c58c489
--- /dev/null
+++ b/src/assets/menu/icon6.png
Binary files differ
diff --git a/src/assets/menu/icon7.png b/src/assets/menu/icon7.png
new file mode 100644
index 0000000..838cb9a
--- /dev/null
+++ b/src/assets/menu/icon7.png
Binary files differ
diff --git a/src/assets/menu/icon8.png b/src/assets/menu/icon8.png
new file mode 100644
index 0000000..0e7d42f
--- /dev/null
+++ b/src/assets/menu/icon8.png
Binary files differ
diff --git a/src/assets/menu/icon9.png b/src/assets/menu/icon9.png
new file mode 100644
index 0000000..ce58f60
--- /dev/null
+++ b/src/assets/menu/icon9.png
Binary files differ
diff --git a/src/layout/navBars/breadcrumb/user.vue b/src/layout/navBars/breadcrumb/user.vue
index 6782651..ca35a27 100644
--- a/src/layout/navBars/breadcrumb/user.vue
+++ b/src/layout/navBars/breadcrumb/user.vue
@@ -56,7 +56,7 @@
<el-dropdown :show-timeout="70" :hide-timeout="50" @command="onHandleCommandClick">
<span class="layout-navbars-breadcrumb-user-link">
<img :src="userInfos.photo" class="layout-navbars-breadcrumb-user-link-photo mr5" />
- {{ userInfos.userName === '' ? 'common' : userInfos.userName }}
+ {{ userInfos.userName }}
<el-icon class="el-icon--right">
<ele-ArrowDown />
</el-icon>
diff --git a/src/router/route.ts b/src/router/route.ts
index d88d69f..7275ffa 100644
--- a/src/router/route.ts
+++ b/src/router/route.ts
@@ -85,7 +85,15 @@
{
path: '/login',
name: 'login',
- component: () => import('/@/views/login/index.vue'),
+ component: () => import('/@/views/loginPage/loginPage.vue'),
+ meta: {
+ title: '登录',
+ },
+ },
+ {
+ path: '/homeMenu',
+ name: 'homeMenu',
+ component: () => import('/@/views/homeMenu/homeMenu.vue'),
meta: {
title: '登录',
},
diff --git a/src/views/homeMenu/homeMenu.vue b/src/views/homeMenu/homeMenu.vue
new file mode 100644
index 0000000..79c6862
--- /dev/null
+++ b/src/views/homeMenu/homeMenu.vue
@@ -0,0 +1,277 @@
+<template>
+ <div class="login-container">
+ <div class="topPanel">
+ <div class="topPanelCont">
+ <div class="topTit">
+ <div>新疆国泰新华安</div>
+ <span></span>
+ <div>全风险预警监测系统</div>
+ </div>
+ <div class="userInfo">
+ <div class="avator">
+ <img src="../../assets/menu/admin.png">
+ <div>admin</div>
+ </div>
+ <span></span>
+ <div class="loginOut" @click="onLoginOut">退出登录</div>
+ </div>
+ </div>
+ </div>
+
+ <div class="menuGrid">
+ <div class="gridCont">
+ <el-row :gutter="16">
+ <el-col :span="6"><div class="grid-content" @click="renderMenu('2')"><div class="itemTit">双重预防系统</div><img class="iconImg" src="../../assets/menu/icon4.png"><img class="bgImg" src="../../assets/menu/card4.png"></div></el-col>
+ <el-col :span="6"><div class="grid-content" @click="renderMenu('3')"><div class="itemTit">特殊作业系统</div><img class="iconImg" src="../../assets/menu/icon7.png"><img class="bgImg" src="../../assets/menu/card7.png"></div></el-col>
+ <el-col :span="6"><div class="grid-content" @click="renderMenu('4')"><div class="itemTit">智能巡检系统</div><img class="iconImg" src="../../assets/menu/icon8.png"><img class="bgImg" src="../../assets/menu/card8.png"></div></el-col>
+ <el-col :span="6">
+ <div class="grid-content" @click="renderMenu('5')">
+ <div class="itemTit">安全风险综合
+ <br>预警预报平台
+ </div>
+ <img class="iconImg" src="../../assets/menu/icon1.png">
+ <img class="bgImg" src="../../assets/menu/card1.png">
+ </div>
+ </el-col>
+ </el-row>
+ <el-row :gutter="16">
+ <el-col :span="6"><div class="grid-content grid-content-2" @click="renderMenu('6')"><div class="itemTit">应急管理系统</div><img class="iconImg" src="../../assets/menu/icon5.png"><img class="bgImg" src="../../assets/menu/card5.png"></div></el-col>
+ <el-col :span="6"><div class="grid-content grid-content-2" @click="renderMenu('7')"><div class="itemTit">目标责任管理系统</div><img class="iconImg" src="../../assets/menu/icon2.png"><img class="bgImg" src="../../assets/menu/card2.png"></div></el-col>
+ <el-col :span="6"><div class="grid-content grid-content-2" @click="renderMenu('8')"><div class="itemTit">事故管理系统</div><img class="iconImg" src="../../assets/menu/icon6.png"><img class="bgImg" src="../../assets/menu/card6.png"></div></el-col>
+ <el-col :span="6"><div class="grid-content grid-content-2" @click="renderMenu('9')"><div class="itemTit">设备综合管控系统</div><img class="iconImg" src="../../assets/menu/icon9.png"><img class="bgImg" src="../../assets/menu/card9.png"></div></el-col>
+ </el-row>
+ <el-row :gutter="16">
+ <el-col :span="6"><div class="grid-content grid-content-3" @click="renderMenu('10')"><div class="itemTit">安全知识图谱系统</div><img class="iconImg" src="../../assets/menu/icon3.png"><img class="bgImg" src="../../assets/menu/card3.png"></div></el-col>
+ <el-col :span="9"><div class="grid-content grid-content-3" @click="renderMenu('11')"><div class="itemTit">危险化学品全生命周期安全<br>管理系统</div><img class="iconImg" src="../../assets/menu/icon10.png"><img class="bgImg" src="../../assets/menu/card10.png"></div></el-col>
+ <el-col :span="9"><div class="grid-content grid-content-3" @click="renderMenu('1')"><div class="itemTit">基础数据权限管理系统</div><img class="iconImg" src="../../assets/menu/icon11.png"><img class="bgImg" src="../../assets/menu/card11.png"></div></el-col>
+ </el-row>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script lang="ts">
+import { toRefs, reactive, computed, defineComponent, onMounted } from 'vue';
+import { storeToRefs } from 'pinia';
+import { useThemeConfig } from '/@/stores/themeConfig';
+import logoMini from '/@/assets/logo-mini.svg';
+import loginIconTwo from '/@/assets/login-icon-two.svg';
+import { NextLoading } from '/@/utils/loading';
+import {Session} from "/@/utils/storage";
+import {useRoute, useRouter} from "vue-router";
+import {initBackEndControlRoutes} from "/@/router/backEnd";
+import {useUserInfo} from "/@/stores/userInfo";
+
+// 定义接口来定义对象的类型
+interface LoginState {
+ tabsActiveName: string;
+ isScan: boolean;
+}
+
+export default defineComponent({
+ name: 'loginIndex',
+ components: {},
+ setup() {
+ const route = useRoute();
+ const router = useRouter();
+ const userInfo = useUserInfo()
+ const { userInfos } = storeToRefs(userInfo);
+ const storesThemeConfig = useThemeConfig();
+ const { themeConfig } = storeToRefs(storesThemeConfig);
+ const state = reactive<LoginState>({
+ tabsActiveName: 'account',
+ isScan: false,
+ });
+ // 获取布局配置信息
+ const getThemeConfig = computed(() => {
+ return themeConfig.value;
+ });
+ // 下拉菜单点击时
+ const onLoginOut = () => {
+ console.log('退出登录')
+ };
+ const renderMenu = async (value: string) => {
+ Session.set('projectId',value)
+ userInfos.value.projectId = value
+ await initBackEndControlRoutes();
+ router.push('./')
+ };
+ //点击进入特殊作业
+ const toSpecialWorkSys = () => {
+ router.push('/workReservation');
+ };
+ // 页面加载时
+ onMounted(() => {
+ NextLoading.done();
+ // loginBg();
+ // loginApp()
+ });
+ return {
+ logoMini,
+ loginIconTwo,
+ getThemeConfig,
+ renderMenu,
+ toSpecialWorkSys,
+ ...toRefs(state),
+ };
+ },
+});
+</script>
+
+<style scoped lang="scss">
+.login-container {
+ width: 100%;
+ height: 100%;
+ position: relative;
+ background: url("../../assets/menu/bg_home.jpg") no-repeat center;
+ .topPanel{
+ position: absolute;
+ width: 100%;
+ top: -100px;
+ left: 0;
+ height:100px;
+ background: #fff;
+ display: flex;
+ justify-content: center;
+ box-shadow: 0 8px 32px rgba(0,0,0,.1);
+ animation: showDown .6s 1 ease forwards;
+
+ @keyframes showDown {
+ 100%{
+ position: absolute;
+ top: 0;
+ }
+ }
+ .topPanelCont{
+ width: 1200px;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ .topTit{
+ font-size: 24px;
+ font-weight: bold;
+ display: flex;
+ align-items: center;
+ color: #333;
+ line-height: 28px;
+
+ &>div:last-of-type{
+ color: #006DF5;
+ }
+
+ span{
+ width: 1px;
+ height: 28px;
+ background: #999;
+ margin: 0 15px;
+ }
+ }
+
+ .userInfo{
+ display: flex;
+ align-items: center;
+
+ .avator{
+ display: flex;
+ justify-content: right;
+
+ img{
+ width: 20px;
+ height: 20px;
+ border-radius: 10px;
+ }
+ div{
+ font-size: 15px;
+ color: #333333;
+ line-height: 20px;
+ margin-left: 6px;
+ }
+ }
+ span{
+ width: 1px;
+ height: 20px;
+ background: #999;
+ margin: 0 15px;
+ }
+ .loginOut{
+ font-size: 15px;
+ color: #333;
+ line-height: 20px;
+ cursor: pointer;
+
+ &:hover{
+ color: #006DF5;
+ }
+ }
+ }
+ }
+ }
+
+ .menuGrid{
+ width: 100%;
+ position: absolute;
+ top: 150px;
+ display: flex;
+ justify-content: center;
+ .gridCont{
+ width: 1200px;
+ .el-row {
+ margin-bottom: 16px;
+ }
+ .el-row:last-child {
+ margin-bottom: 0;
+ }
+ .el-col {
+ border-radius: 8px;
+ }
+
+ .grid-content {
+ border-radius: 8px;
+ height: 234px;
+ padding: 32px;
+ position: relative;
+ background-image: linear-gradient(135deg,#00C0F5,#147AEA);
+ overflow: hidden;
+ cursor: pointer;
+ transition: .3s;
+ border: none;
+
+ &:hover{
+ box-shadow: 0 8px 32px rgba(20,97,234,.4);
+ }
+
+ .itemTit{
+ font-size: 24px;
+ line-height: 36px;
+ height: 40%;
+ font-family: "PingFang SC";
+ font-weight: lighter;
+ color: #fff;
+ margin-bottom: 25px;
+ }
+ .iconImg{
+ width: 80px;
+ height: 80px;
+ }
+
+ .bgImg{
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ }
+ }
+
+ .grid-content-2{
+ background-image: linear-gradient(135deg,#0098F5,#1461EA);
+ }
+
+ .grid-content-3{
+ background-image: linear-gradient(135deg,#006DF5,#1450EA);
+ }
+ }
+
+ }
+}
+</style>
diff --git a/src/views/loginPage/component/accountLogin.vue b/src/views/loginPage/component/accountLogin.vue
new file mode 100644
index 0000000..d477fa1
--- /dev/null
+++ b/src/views/loginPage/component/accountLogin.vue
@@ -0,0 +1,207 @@
+<template>
+ <el-form size="large" class="login-content-form">
+ <el-form-item class="login-animation1">
+ <el-input type="text" :placeholder="$t('message.account.accountPlaceholder1')" v-model="ruleForm.username" clearable autocomplete="off" size="large">
+ <template #prefix>
+ <el-icon class="el-input__icon" style="margin-right: 20px"><img src="../../../assets/loginPage/login_icon_user.png" style="width: 24px;height: 24px"></el-icon>
+ </template>
+ </el-input>
+ </el-form-item>
+ <el-form-item class="login-animation2">
+ <el-input
+ :type="isShowPassword ? 'text' : 'password'"
+ :placeholder="$t('message.account.accountPlaceholder2')"
+ v-model="ruleForm.password"
+ autocomplete="off"
+ size="large"
+ >
+ <template #prefix>
+ <el-icon class="el-input__icon" style="margin-right: 20px"><img src="../../../assets/loginPage/login_icon_password.png" style="width: 24px;height: 24px"></el-icon>
+ </template>
+ <template #suffix>
+ <i
+ class="iconfont el-input__icon login-content-password"
+ :class="isShowPassword ? 'icon-yincangmima' : 'icon-xianshimima'"
+ @click="isShowPassword = !isShowPassword"
+ >
+ </i>
+ </template>
+ </el-input>
+ </el-form-item>
+ <el-form-item class="login-animation4 codeDeal">
+ <el-checkbox v-model="saveCode" label="记住密码" size="large" />
+ <span class="forgetCode">忘记密码?</span>
+ </el-form-item>
+ <el-form-item class="login-animation4">
+ <el-button type="primary" class="login-content-submit" round @click="onSignIn" :loading="loading.signIn">
+ <span>登录系统</span>
+ </el-button>
+ </el-form-item>
+ </el-form>
+</template>
+
+<script lang="ts">
+import { toRefs, reactive, defineComponent, computed } from 'vue';
+import { useRoute, useRouter } from 'vue-router';
+import { ElMessage } from 'element-plus';
+import { useI18n } from 'vue-i18n';
+import Cookies from 'js-cookie';
+import { storeToRefs } from 'pinia';
+import { useThemeConfig } from '/@/stores/themeConfig';
+import { initFrontEndControlRoutes } from '/@/router/frontEnd';
+import { initBackEndControlRoutes } from '/@/router/backEnd';
+import { Session } from '/@/utils/storage';
+import { formatAxis } from '/@/utils/formatTime';
+import { NextLoading } from '/@/utils/loading';
+import { useLoginApi } from '/@/api/login';
+import {useUserInfo} from "/@/stores/userInfo";
+
+export default defineComponent({
+ name: 'accountLogin',
+ setup() {
+ const { t } = useI18n();
+ const userInfo = useUserInfo()
+ const route = useRoute();
+ const router = useRouter();
+ const state = reactive({
+ isShowPassword: false,
+ ruleForm: {
+ username: 'admin',
+ password: '123456',
+ },
+ loading: {
+ signIn: false,
+ },
+ });
+ // 时间获取
+ const currentTime = computed(() => {
+ return formatAxis(new Date());
+ });
+ // 登录
+ const onSignIn = async () => {
+ state.loading.signIn = true;
+ // 存储 token 到浏览器缓存
+ let res = await useLoginApi().signIn(state.ruleForm)
+ if(res.data.code === '200'){
+ userInfo.setUserInfos(res.data.data)
+ Session.set('token', res.data.data.accessToken);
+ Session.set('projectId','');
+ Session.set('uid',res.data.data.uid);
+ signInSuccess();
+ }else{
+ state.loading.signIn = false
+ ElMessage({
+ type:'warning',
+ message:res.data.msg
+ })
+ }
+ // Session.set('token', Math.random().toString(36).substr(0));
+ // // 模拟数据,对接接口时,记得删除多余代码及对应依赖的引入。用于 `/src/stores/userInfo.ts` 中不同用户登录判断(模拟数据)
+ // Cookies.set('userName', state.ruleForm.username);
+ // if (!themeConfig.value.isRequestRoutes) {
+ // // 前端控制路由,2、请注意执行顺序
+ // await initFrontEndControlRoutes();
+ // signInSuccess();
+ // } else {
+ // // 模拟后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
+ // // 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/"
+ // await initBackEndControlRoutes();
+ // // 执行完 initBackEndControlRoutes,再执行 signInSuccess
+ // signInSuccess();
+ // }
+ };
+ // 登录成功后的跳转
+ const signInSuccess = async () => {
+ // 初始化登录成功时间问候语
+ let currentTimeInfo = currentTime.value;
+ // 登录成功,跳到转首页
+ // 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
+ if (route.query?.redirect) {
+ router.push('/homeMenu');
+ // router.push({
+ // path: <string>route.query?.redirect,
+ // query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
+ // });
+ } else {
+ router.push('/loginPage');
+ }
+ state.loading.signIn = true;
+ const signInText = t('message.signInText');
+ ElMessage.success(`${currentTimeInfo},${signInText}`);
+ // 登录成功提示
+ // 关闭 loading
+ // 添加 loading,防止第一次进入界面时出现短暂空白
+ // NextLoading.start();
+ };
+ return {
+ onSignIn,
+ ...toRefs(state),
+ };
+ },
+});
+</script>
+
+<style scoped lang="scss">
+.login-content-form {
+ margin-top: 40px;
+ width: 420px;
+
+ .el-input::v-deep .el-input__wrapper{
+ height: 56px;
+ border-radius: 28px;
+ padding: 0 30px;
+ background: #F2F2F2;
+ &:focus-within{
+ border: 1px solid #2053D7;
+ }
+ }
+ @for $i from 1 through 4 {
+ .login-animation#{$i} {
+ opacity: 0;
+ animation-name: error-num;
+ animation-duration: 0.5s;
+ animation-fill-mode: forwards;
+ animation-delay: calc($i/10) + s;
+ }
+ }
+ .codeDeal::v-deep .el-form-item__content{
+ display: flex;
+ justify-content: space-between;
+
+ .forgetCode{
+ color: #2053D7;
+ cursor: pointer;
+ }
+ }
+ .login-content-password {
+ width: 100%;
+ display: inline-block;
+ width: 20px;
+ cursor: pointer;
+ &:hover {
+ color: #909399;
+ }
+ }
+ .login-content-code {
+ width: 100%;
+ padding: 0;
+ font-weight: bold;
+ letter-spacing: 5px;
+ }
+ .login-content-submit {
+ width: 100%;
+ height: 56px;
+ font-size: 16px;
+ border-radius: 28px;
+ letter-spacing: 4px;
+ font-weight: 300;
+ margin-top: 15px;
+ background: #2053D7;
+ transition: .3s;
+ &:hover{
+ letter-spacing: 6px;
+ background: #4E7AEC;
+ }
+ }
+}
+</style>
diff --git a/src/views/loginPage/loginPage.vue b/src/views/loginPage/loginPage.vue
new file mode 100644
index 0000000..66c68bc
--- /dev/null
+++ b/src/views/loginPage/loginPage.vue
@@ -0,0 +1,160 @@
+<template>
+ <div class="login-container">
+ <div id="particles-js" style="display: flex;align-items: center;justify-content: center">
+ <canvas class="particles-js-canvas-el" style="width: 100%; height: 100%;" width="472" height="625"></canvas>
+ </div>
+ <div class="loginContent">
+ <div class="loginContL">
+ <div class="apTitleT">新疆国泰新华</div>
+ <div class="apTitleB">安全风险预警监测系统</div>
+ <span></span>
+ </div>
+ <div class="loginPanel">
+ <div class="welc">WELCOME!</div>
+ <div class="welcc">欢迎登录</div>
+<!-- <div class="loginInfo">-->
+<!-- <el-input v-model="input" placeholder="Please input" />-->
+<!-- </div>-->
+ <div>
+ <el-tabs v-model="tabsActiveName">
+ <AccountLogin />
+ </el-tabs>
+ </div>
+ </div>
+ </div>
+
+ </div>
+</template>
+
+<script lang="ts">
+import { toRefs, reactive, computed, defineComponent, onMounted } from 'vue';
+import { storeToRefs } from 'pinia';
+import { useThemeConfig } from '/@/stores/themeConfig';
+import logoMini from '/@/assets/logo-mini.svg';
+import loginIconTwo from '/@/assets/login-icon-two.svg';
+import { NextLoading } from '/@/utils/loading';
+import AccountLogin from '/@/views/loginPage/component/accountLogin.vue';
+import { loginBg } from '../../../static/loginPage.js/login.js'
+import { loginApp } from '../../../static/loginPage.js/loginApp.js'
+
+// 定义接口来定义对象的类型
+interface LoginState {
+ tabsActiveName: string;
+ isScan: boolean;
+}
+
+export default defineComponent({
+ name: 'loginIndex',
+ components: { AccountLogin },
+ setup() {
+ const storesThemeConfig = useThemeConfig();
+ const { themeConfig } = storeToRefs(storesThemeConfig);
+ const state = reactive<LoginState>({
+ tabsActiveName: 'account',
+ isScan: false,
+ });
+ // 获取布局配置信息
+ const getThemeConfig = computed(() => {
+ return themeConfig.value;
+ });
+ // 页面加载时
+ onMounted(() => {
+ NextLoading.done();
+ loginBg();
+ loginApp()
+ });
+ return {
+ logoMini,
+ loginIconTwo,
+ getThemeConfig,
+ ...toRefs(state),
+ };
+ },
+});
+</script>
+
+<style scoped lang="scss">
+.login-container {
+ width: 100%;
+ height: 100%;
+ position: relative;
+ z-index: 999;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-image: radial-gradient(at center, #0075c3, #000b61);
+
+ canvas {
+ display: block;
+ vertical-align: bottom;
+ }
+
+ #particles-js {
+ width: 100%;
+ height: 100%;
+
+ background-size: cover;
+ background-position: 50% 50%;
+ background-repeat: no-repeat;
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ }
+
+ .loginContent{
+ width: 100%;
+ padding: 0 300px;
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+
+ .loginContL{
+ font-size: 48px;
+ font-weight: bold;
+ padding-top: 20px;
+ margin-right: 30px;
+
+ .apTitleT{
+ color: #fff;
+ margin-bottom: 20px;
+ letter-spacing: 4px;
+ }
+ .apTitleB{
+ color: #01d0ff;
+ margin-bottom: 40px;
+ letter-spacing: 4px;
+ }
+ &>span{
+ display: block;
+ width: 120px;
+ height: 8px;
+ background: #01d0ff;
+ }
+ }
+ .loginPanel{
+ padding: 85px 70px;
+ background: #fff;
+ border-radius: 15px;
+ box-shadow: 0 8px 40px rgba(0,0,0,.15);
+
+ .welc{
+ font-size: 36px;
+ font-family: "PingFang SC";
+ font-weight: normal;
+ color: #999999;
+ letter-spacing: 2px;
+ margin-bottom: 15px;
+ }
+ .welcc{
+ font-size: 32px;
+ font-family: "PingFang SC";
+ font-weight: lighter;
+ color: #333;
+ letter-spacing: 2px;
+ }
+ }
+ }
+}
+</style>
diff --git a/static/loginPage.js/login.js b/static/loginPage.js/login.js
new file mode 100644
index 0000000..431ef23
--- /dev/null
+++ b/static/loginPage.js/login.js
@@ -0,0 +1,1545 @@
+/* -----------------------------------------------
+/* Author : Vincent Garreau - vincentgarreau.com
+/* MIT license: http://opensource.org/licenses/MIT
+/* Demo / Generator : vincentgarreau.com/particles.js
+/* GitHub : github.com/VincentGarreau/particles.js
+/* How to use? : Check the GitHub README
+/* v2.0.0
+/* ----------------------------------------------- */
+function loginBg() {
+var pJS = function(tag_id, params){
+
+ var canvas_el = document.querySelector('#'+tag_id+' > .particles-js-canvas-el');
+
+ /* particles.js variables with default values */
+ this.pJS = {
+ canvas: {
+ el: canvas_el,
+ w: canvas_el.offsetWidth,
+ h: canvas_el.offsetHeight
+ },
+ particles: {
+ number: {
+ value: 400,
+ density: {
+ enable: true,
+ value_area: 800
+ }
+ },
+ color: {
+ value: '#fff'
+ },
+ shape: {
+ type: 'circle',
+ stroke: {
+ width: 0,
+ color: '#ff0000'
+ },
+ polygon: {
+ nb_sides: 5
+ },
+ image: {
+ src: '',
+ width: 100,
+ height: 100
+ }
+ },
+ opacity: {
+ value: 1,
+ random: false,
+ anim: {
+ enable: false,
+ speed: 2,
+ opacity_min: 0,
+ sync: false
+ }
+ },
+ size: {
+ value: 20,
+ random: false,
+ anim: {
+ enable: false,
+ speed: 20,
+ size_min: 0,
+ sync: false
+ }
+ },
+ line_linked: {
+ enable: true,
+ distance: 100,
+ color: '#fff',
+ opacity: 1,
+ width: 1
+ },
+ move: {
+ enable: true,
+ speed: 2,
+ direction: 'none',
+ random: false,
+ straight: false,
+ out_mode: 'out',
+ bounce: false,
+ attract: {
+ enable: false,
+ rotateX: 3000,
+ rotateY: 3000
+ }
+ },
+ array: []
+ },
+ interactivity: {
+ detect_on: 'canvas',
+ events: {
+ onhover: {
+ enable: true,
+ mode: 'grab'
+ },
+ onclick: {
+ enable: true,
+ mode: 'push'
+ },
+ resize: true
+ },
+ modes: {
+ grab:{
+ distance: 100,
+ line_linked:{
+ opacity: 1
+ }
+ },
+ bubble:{
+ distance: 200,
+ size: 80,
+ duration: 0.7
+ },
+ repulse:{
+ distance: 200,
+ duration: 0.4
+ },
+ push:{
+ particles_nb: 4
+ },
+ remove:{
+ particles_nb: 2
+ }
+ },
+ mouse:{}
+ },
+ retina_detect: false,
+ fn: {
+ interact: {},
+ modes: {},
+ vendors:{}
+ },
+ tmp: {}
+ };
+
+ var pJS = this.pJS;
+
+ /* params settings */
+ if(params){
+ Object.deepExtend(pJS, params);
+ }
+
+ pJS.tmp.obj = {
+ size_value: pJS.particles.size.value,
+ size_anim_speed: pJS.particles.size.anim.speed,
+ move_speed: pJS.particles.move.speed,
+ line_linked_distance: pJS.particles.line_linked.distance,
+ line_linked_width: pJS.particles.line_linked.width,
+ mode_grab_distance: pJS.interactivity.modes.grab.distance,
+ mode_bubble_distance: pJS.interactivity.modes.bubble.distance,
+ mode_bubble_size: pJS.interactivity.modes.bubble.size,
+ mode_repulse_distance: pJS.interactivity.modes.repulse.distance
+ };
+
+
+ pJS.fn.retinaInit = function(){
+
+ if(pJS.retina_detect && window.devicePixelRatio > 1){
+ pJS.canvas.pxratio = window.devicePixelRatio;
+ pJS.tmp.retina = true;
+ }
+ else{
+ pJS.canvas.pxratio = 1;
+ pJS.tmp.retina = false;
+ }
+
+ pJS.canvas.w = pJS.canvas.el.offsetWidth * pJS.canvas.pxratio;
+ pJS.canvas.h = pJS.canvas.el.offsetHeight * pJS.canvas.pxratio;
+
+ pJS.particles.size.value = pJS.tmp.obj.size_value * pJS.canvas.pxratio;
+ pJS.particles.size.anim.speed = pJS.tmp.obj.size_anim_speed * pJS.canvas.pxratio;
+ pJS.particles.move.speed = pJS.tmp.obj.move_speed * pJS.canvas.pxratio;
+ pJS.particles.line_linked.distance = pJS.tmp.obj.line_linked_distance * pJS.canvas.pxratio;
+ pJS.interactivity.modes.grab.distance = pJS.tmp.obj.mode_grab_distance * pJS.canvas.pxratio;
+ pJS.interactivity.modes.bubble.distance = pJS.tmp.obj.mode_bubble_distance * pJS.canvas.pxratio;
+ pJS.particles.line_linked.width = pJS.tmp.obj.line_linked_width * pJS.canvas.pxratio;
+ pJS.interactivity.modes.bubble.size = pJS.tmp.obj.mode_bubble_size * pJS.canvas.pxratio;
+ pJS.interactivity.modes.repulse.distance = pJS.tmp.obj.mode_repulse_distance * pJS.canvas.pxratio;
+
+ };
+
+
+
+ /* ---------- pJS functions - canvas ------------ */
+
+ pJS.fn.canvasInit = function(){
+ pJS.canvas.ctx = pJS.canvas.el.getContext('2d');
+ };
+
+ pJS.fn.canvasSize = function(){
+
+ pJS.canvas.el.width = pJS.canvas.w;
+ pJS.canvas.el.height = pJS.canvas.h;
+
+ if(pJS && pJS.interactivity.events.resize){
+
+ window.addEventListener('resize', function(){
+
+ pJS.canvas.w = pJS.canvas.el.offsetWidth;
+ pJS.canvas.h = pJS.canvas.el.offsetHeight;
+
+ /* resize canvas */
+ if(pJS.tmp.retina){
+ pJS.canvas.w *= pJS.canvas.pxratio;
+ pJS.canvas.h *= pJS.canvas.pxratio;
+ }
+
+ pJS.canvas.el.width = pJS.canvas.w;
+ pJS.canvas.el.height = pJS.canvas.h;
+
+ /* repaint canvas on anim disabled */
+ if(!pJS.particles.move.enable){
+ pJS.fn.particlesEmpty();
+ pJS.fn.particlesCreate();
+ pJS.fn.particlesDraw();
+ pJS.fn.vendors.densityAutoParticles();
+ }
+
+ /* density particles enabled */
+ pJS.fn.vendors.densityAutoParticles();
+
+ });
+
+ }
+
+ };
+
+
+ pJS.fn.canvasPaint = function(){
+ pJS.canvas.ctx.fillRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+ };
+
+ pJS.fn.canvasClear = function(){
+ pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+ };
+
+
+ /* --------- pJS functions - particles ----------- */
+
+ pJS.fn.particle = function(color, opacity, position){
+
+ /* size */
+ this.radius = (pJS.particles.size.random ? Math.random() : 1) * pJS.particles.size.value;
+ if(pJS.particles.size.anim.enable){
+ this.size_status = false;
+ this.vs = pJS.particles.size.anim.speed / 100;
+ if(!pJS.particles.size.anim.sync){
+ this.vs = this.vs * Math.random();
+ }
+ }
+
+ /* position */
+ this.x = position ? position.x : Math.random() * pJS.canvas.w;
+ this.y = position ? position.y : Math.random() * pJS.canvas.h;
+
+ /* check position - into the canvas */
+ if(this.x > pJS.canvas.w - this.radius*2) this.x = this.x - this.radius;
+ else if(this.x < this.radius*2) this.x = this.x + this.radius;
+ if(this.y > pJS.canvas.h - this.radius*2) this.y = this.y - this.radius;
+ else if(this.y < this.radius*2) this.y = this.y + this.radius;
+
+ /* check position - avoid overlap */
+ if(pJS.particles.move.bounce){
+ pJS.fn.vendors.checkOverlap(this, position);
+ }
+
+ /* color */
+ this.color = {};
+ if(typeof(color.value) == 'object'){
+
+ if(color.value instanceof Array){
+ var color_selected = color.value[Math.floor(Math.random() * pJS.particles.color.value.length)];
+ this.color.rgb = hexToRgb(color_selected);
+ }else{
+ if(color.value.r != undefined && color.value.g != undefined && color.value.b != undefined){
+ this.color.rgb = {
+ r: color.value.r,
+ g: color.value.g,
+ b: color.value.b
+ }
+ }
+ if(color.value.h != undefined && color.value.s != undefined && color.value.l != undefined){
+ this.color.hsl = {
+ h: color.value.h,
+ s: color.value.s,
+ l: color.value.l
+ }
+ }
+ }
+
+ }
+ else if(color.value == 'random'){
+ this.color.rgb = {
+ r: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),
+ g: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),
+ b: (Math.floor(Math.random() * (255 - 0 + 1)) + 0)
+ }
+ }
+ else if(typeof(color.value) == 'string'){
+ this.color = color;
+ this.color.rgb = hexToRgb(this.color.value);
+ }
+
+ /* opacity */
+ this.opacity = (pJS.particles.opacity.random ? Math.random() : 1) * pJS.particles.opacity.value;
+ if(pJS.particles.opacity.anim.enable){
+ this.opacity_status = false;
+ this.vo = pJS.particles.opacity.anim.speed / 100;
+ if(!pJS.particles.opacity.anim.sync){
+ this.vo = this.vo * Math.random();
+ }
+ }
+
+ /* animation - velocity for speed */
+ var velbase = {}
+ switch(pJS.particles.move.direction){
+ case 'top':
+ velbase = { x:0, y:-1 };
+ break;
+ case 'top-right':
+ velbase = { x:0.5, y:-0.5 };
+ break;
+ case 'right':
+ velbase = { x:1, y:-0 };
+ break;
+ case 'bottom-right':
+ velbase = { x:0.5, y:0.5 };
+ break;
+ case 'bottom':
+ velbase = { x:0, y:1 };
+ break;
+ case 'bottom-left':
+ velbase = { x:-0.5, y:1 };
+ break;
+ case 'left':
+ velbase = { x:-1, y:0 };
+ break;
+ case 'top-left':
+ velbase = { x:-0.5, y:-0.5 };
+ break;
+ default:
+ velbase = { x:0, y:0 };
+ break;
+ }
+
+ if(pJS.particles.move.straight){
+ this.vx = velbase.x;
+ this.vy = velbase.y;
+ if(pJS.particles.move.random){
+ this.vx = this.vx * (Math.random());
+ this.vy = this.vy * (Math.random());
+ }
+ }else{
+ this.vx = velbase.x + Math.random()-0.5;
+ this.vy = velbase.y + Math.random()-0.5;
+ }
+
+ // var theta = 2.0 * Math.PI * Math.random();
+ // this.vx = Math.cos(theta);
+ // this.vy = Math.sin(theta);
+
+ this.vx_i = this.vx;
+ this.vy_i = this.vy;
+
+
+
+ /* if shape is image */
+
+ var shape_type = pJS.particles.shape.type;
+ if(typeof(shape_type) == 'object'){
+ if(shape_type instanceof Array){
+ var shape_selected = shape_type[Math.floor(Math.random() * shape_type.length)];
+ this.shape = shape_selected;
+ }
+ }else{
+ this.shape = shape_type;
+ }
+
+ if(this.shape == 'image'){
+ var sh = pJS.particles.shape;
+ this.img = {
+ src: sh.image.src,
+ ratio: sh.image.width / sh.image.height
+ }
+ if(!this.img.ratio) this.img.ratio = 1;
+ if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg != undefined){
+ pJS.fn.vendors.createSvgImg(this);
+ if(pJS.tmp.pushing){
+ this.img.loaded = false;
+ }
+ }
+ }
+
+
+
+ };
+
+
+ pJS.fn.particle.prototype.draw = function() {
+
+ var p = this;
+
+ if(p.radius_bubble != undefined){
+ var radius = p.radius_bubble;
+ }else{
+ var radius = p.radius;
+ }
+
+ if(p.opacity_bubble != undefined){
+ var opacity = p.opacity_bubble;
+ }else{
+ var opacity = p.opacity;
+ }
+
+ if(p.color.rgb){
+ var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+opacity+')';
+ }else{
+ var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+opacity+')';
+ }
+
+ pJS.canvas.ctx.fillStyle = color_value;
+ pJS.canvas.ctx.beginPath();
+
+ switch(p.shape){
+
+ case 'circle':
+ pJS.canvas.ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false);
+ break;
+
+ case 'edge':
+ pJS.canvas.ctx.rect(p.x-radius, p.y-radius, radius*2, radius*2);
+ break;
+
+ case 'triangle':
+ pJS.fn.vendors.drawShape(pJS.canvas.ctx, p.x-radius, p.y+radius / 1.66, radius*2, 3, 2);
+ break;
+
+ case 'polygon':
+ pJS.fn.vendors.drawShape(
+ pJS.canvas.ctx,
+ p.x - radius / (pJS.particles.shape.polygon.nb_sides/3.5), // startX
+ p.y - radius / (2.66/3.5), // startY
+ radius*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength
+ pJS.particles.shape.polygon.nb_sides, // sideCountNumerator
+ 1 // sideCountDenominator
+ );
+ break;
+
+ case 'star':
+ pJS.fn.vendors.drawShape(
+ pJS.canvas.ctx,
+ p.x - radius*2 / (pJS.particles.shape.polygon.nb_sides/4), // startX
+ p.y - radius / (2*2.66/3.5), // startY
+ radius*2*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength
+ pJS.particles.shape.polygon.nb_sides, // sideCountNumerator
+ 2 // sideCountDenominator
+ );
+ break;
+
+ case 'image':
+
+ function draw(){
+ pJS.canvas.ctx.drawImage(
+ img_obj,
+ p.x-radius,
+ p.y-radius,
+ radius*2,
+ radius*2 / p.img.ratio
+ );
+ }
+
+ if(pJS.tmp.img_type == 'svg'){
+ var img_obj = p.img.obj;
+ }else{
+ var img_obj = pJS.tmp.img_obj;
+ }
+
+ if(img_obj){
+ draw();
+ }
+
+ break;
+
+ }
+
+ pJS.canvas.ctx.closePath();
+
+ if(pJS.particles.shape.stroke.width > 0){
+ pJS.canvas.ctx.strokeStyle = pJS.particles.shape.stroke.color;
+ pJS.canvas.ctx.lineWidth = pJS.particles.shape.stroke.width;
+ pJS.canvas.ctx.stroke();
+ }
+
+ pJS.canvas.ctx.fill();
+
+ };
+
+
+ pJS.fn.particlesCreate = function(){
+ for(var i = 0; i < pJS.particles.number.value; i++) {
+ pJS.particles.array.push(new pJS.fn.particle(pJS.particles.color, pJS.particles.opacity.value));
+ }
+ };
+
+ pJS.fn.particlesUpdate = function(){
+
+ for(var i = 0; i < pJS.particles.array.length; i++){
+
+ /* the particle */
+ var p = pJS.particles.array[i];
+
+ // var d = ( dx = pJS.interactivity.mouse.click_pos_x - p.x ) * dx + ( dy = pJS.interactivity.mouse.click_pos_y - p.y ) * dy;
+ // var f = -BANG_SIZE / d;
+ // if ( d < BANG_SIZE ) {
+ // var t = Math.atan2( dy, dx );
+ // p.vx = f * Math.cos(t);
+ // p.vy = f * Math.sin(t);
+ // }
+
+ /* move the particle */
+ if(pJS.particles.move.enable){
+ var ms = pJS.particles.move.speed/2;
+ p.x += p.vx * ms;
+ p.y += p.vy * ms;
+ }
+
+ /* change opacity status */
+ if(pJS.particles.opacity.anim.enable) {
+ if(p.opacity_status == true) {
+ if(p.opacity >= pJS.particles.opacity.value) p.opacity_status = false;
+ p.opacity += p.vo;
+ }else {
+ if(p.opacity <= pJS.particles.opacity.anim.opacity_min) p.opacity_status = true;
+ p.opacity -= p.vo;
+ }
+ if(p.opacity < 0) p.opacity = 0;
+ }
+
+ /* change size */
+ if(pJS.particles.size.anim.enable){
+ if(p.size_status == true){
+ if(p.radius >= pJS.particles.size.value) p.size_status = false;
+ p.radius += p.vs;
+ }else{
+ if(p.radius <= pJS.particles.size.anim.size_min) p.size_status = true;
+ p.radius -= p.vs;
+ }
+ if(p.radius < 0) p.radius = 0;
+ }
+
+ /* change particle position if it is out of canvas */
+ if(pJS.particles.move.out_mode == 'bounce'){
+ var new_pos = {
+ x_left: p.radius,
+ x_right: pJS.canvas.w,
+ y_top: p.radius,
+ y_bottom: pJS.canvas.h
+ }
+ }else{
+ var new_pos = {
+ x_left: -p.radius,
+ x_right: pJS.canvas.w + p.radius,
+ y_top: -p.radius,
+ y_bottom: pJS.canvas.h + p.radius
+ }
+ }
+
+ if(p.x - p.radius > pJS.canvas.w){
+ p.x = new_pos.x_left;
+ p.y = Math.random() * pJS.canvas.h;
+ }
+ else if(p.x + p.radius < 0){
+ p.x = new_pos.x_right;
+ p.y = Math.random() * pJS.canvas.h;
+ }
+ if(p.y - p.radius > pJS.canvas.h){
+ p.y = new_pos.y_top;
+ p.x = Math.random() * pJS.canvas.w;
+ }
+ else if(p.y + p.radius < 0){
+ p.y = new_pos.y_bottom;
+ p.x = Math.random() * pJS.canvas.w;
+ }
+
+ /* out of canvas modes */
+ switch(pJS.particles.move.out_mode){
+ case 'bounce':
+ if (p.x + p.radius > pJS.canvas.w) p.vx = -p.vx;
+ else if (p.x - p.radius < 0) p.vx = -p.vx;
+ if (p.y + p.radius > pJS.canvas.h) p.vy = -p.vy;
+ else if (p.y - p.radius < 0) p.vy = -p.vy;
+ break;
+ }
+
+ /* events */
+ if(isInArray('grab', pJS.interactivity.events.onhover.mode)){
+ pJS.fn.modes.grabParticle(p);
+ }
+
+ if(isInArray('bubble', pJS.interactivity.events.onhover.mode) || isInArray('bubble', pJS.interactivity.events.onclick.mode)){
+ pJS.fn.modes.bubbleParticle(p);
+ }
+
+ if(isInArray('repulse', pJS.interactivity.events.onhover.mode) || isInArray('repulse', pJS.interactivity.events.onclick.mode)){
+ pJS.fn.modes.repulseParticle(p);
+ }
+
+ /* interaction auto between particles */
+ if(pJS.particles.line_linked.enable || pJS.particles.move.attract.enable){
+ for(var j = i + 1; j < pJS.particles.array.length; j++){
+ var p2 = pJS.particles.array[j];
+
+ /* link particles */
+ if(pJS.particles.line_linked.enable){
+ pJS.fn.interact.linkParticles(p,p2);
+ }
+
+ /* attract particles */
+ if(pJS.particles.move.attract.enable){
+ pJS.fn.interact.attractParticles(p,p2);
+ }
+
+ /* bounce particles */
+ if(pJS.particles.move.bounce){
+ pJS.fn.interact.bounceParticles(p,p2);
+ }
+
+ }
+ }
+
+
+ }
+
+ };
+
+ pJS.fn.particlesDraw = function(){
+
+ /* clear canvas */
+ pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+
+ /* update each particles param */
+ pJS.fn.particlesUpdate();
+
+ /* draw each particle */
+ for(var i = 0; i < pJS.particles.array.length; i++){
+ var p = pJS.particles.array[i];
+ p.draw();
+ }
+
+ };
+
+ pJS.fn.particlesEmpty = function(){
+ pJS.particles.array = [];
+ };
+
+ pJS.fn.particlesRefresh = function(){
+
+ /* init all */
+ cancelRequestAnimFrame(pJS.fn.checkAnimFrame);
+ cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ pJS.tmp.source_svg = undefined;
+ pJS.tmp.img_obj = undefined;
+ pJS.tmp.count_svg = 0;
+ pJS.fn.particlesEmpty();
+ pJS.fn.canvasClear();
+
+ /* restart */
+ pJS.fn.vendors.start();
+
+ };
+
+
+ /* ---------- pJS functions - particles interaction ------------ */
+
+ pJS.fn.interact.linkParticles = function(p1, p2){
+
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx*dx + dy*dy);
+
+ /* draw a line between p1 and p2 if the distance between them is under the config distance */
+ if(dist <= pJS.particles.line_linked.distance){
+
+ var opacity_line = pJS.particles.line_linked.opacity - (dist / (1/pJS.particles.line_linked.opacity)) / pJS.particles.line_linked.distance;
+
+ if(opacity_line > 0){
+
+ /* style */
+ var color_line = pJS.particles.line_linked.color_rgb_line;
+ pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')';
+ pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;
+ //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */
+
+ /* path */
+ pJS.canvas.ctx.beginPath();
+ pJS.canvas.ctx.moveTo(p1.x, p1.y);
+ pJS.canvas.ctx.lineTo(p2.x, p2.y);
+ pJS.canvas.ctx.stroke();
+ pJS.canvas.ctx.closePath();
+
+ }
+
+ }
+
+ };
+
+
+ pJS.fn.interact.attractParticles = function(p1, p2){
+
+ /* condensed particles */
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx*dx + dy*dy);
+
+ if(dist <= pJS.particles.line_linked.distance){
+
+ var ax = dx/(pJS.particles.move.attract.rotateX*1000),
+ ay = dy/(pJS.particles.move.attract.rotateY*1000);
+
+ p1.vx -= ax;
+ p1.vy -= ay;
+
+ p2.vx += ax;
+ p2.vy += ay;
+
+ }
+
+
+ }
+
+
+ pJS.fn.interact.bounceParticles = function(p1, p2){
+
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx*dx + dy*dy),
+ dist_p = p1.radius+p2.radius;
+
+ if(dist <= dist_p){
+ p1.vx = -p1.vx;
+ p1.vy = -p1.vy;
+
+ p2.vx = -p2.vx;
+ p2.vy = -p2.vy;
+ }
+
+ }
+
+
+ /* ---------- pJS functions - modes events ------------ */
+
+ pJS.fn.modes.pushParticles = function(nb, pos){
+
+ pJS.tmp.pushing = true;
+
+ for(var i = 0; i < nb; i++){
+ pJS.particles.array.push(
+ new pJS.fn.particle(
+ pJS.particles.color,
+ pJS.particles.opacity.value,
+ {
+ 'x': pos ? pos.pos_x : Math.random() * pJS.canvas.w,
+ 'y': pos ? pos.pos_y : Math.random() * pJS.canvas.h
+ }
+ )
+ )
+ if(i == nb-1){
+ if(!pJS.particles.move.enable){
+ pJS.fn.particlesDraw();
+ }
+ pJS.tmp.pushing = false;
+ }
+ }
+
+ };
+
+
+ pJS.fn.modes.removeParticles = function(nb){
+
+ pJS.particles.array.splice(0, nb);
+ if(!pJS.particles.move.enable){
+ pJS.fn.particlesDraw();
+ }
+
+ };
+
+
+ pJS.fn.modes.bubbleParticle = function(p){
+
+ /* on hover event */
+ if(pJS.interactivity.events.onhover.enable && isInArray('bubble', pJS.interactivity.events.onhover.mode)){
+
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse),
+ ratio = 1 - dist_mouse / pJS.interactivity.modes.bubble.distance;
+
+ function init(){
+ p.opacity_bubble = p.opacity;
+ p.radius_bubble = p.radius;
+ }
+
+ /* mousemove - check ratio */
+ if(dist_mouse <= pJS.interactivity.modes.bubble.distance){
+
+ if(ratio >= 0 && pJS.interactivity.status == 'mousemove'){
+
+ /* size */
+ if(pJS.interactivity.modes.bubble.size != pJS.particles.size.value){
+
+ if(pJS.interactivity.modes.bubble.size > pJS.particles.size.value){
+ var size = p.radius + (pJS.interactivity.modes.bubble.size*ratio);
+ if(size >= 0){
+ p.radius_bubble = size;
+ }
+ }else{
+ var dif = p.radius - pJS.interactivity.modes.bubble.size,
+ size = p.radius - (dif*ratio);
+ if(size > 0){
+ p.radius_bubble = size;
+ }else{
+ p.radius_bubble = 0;
+ }
+ }
+
+ }
+
+ /* opacity */
+ if(pJS.interactivity.modes.bubble.opacity != pJS.particles.opacity.value){
+
+ if(pJS.interactivity.modes.bubble.opacity > pJS.particles.opacity.value){
+ var opacity = pJS.interactivity.modes.bubble.opacity*ratio;
+ if(opacity > p.opacity && opacity <= pJS.interactivity.modes.bubble.opacity){
+ p.opacity_bubble = opacity;
+ }
+ }else{
+ var opacity = p.opacity - (pJS.particles.opacity.value-pJS.interactivity.modes.bubble.opacity)*ratio;
+ if(opacity < p.opacity && opacity >= pJS.interactivity.modes.bubble.opacity){
+ p.opacity_bubble = opacity;
+ }
+ }
+
+ }
+
+ }
+
+ }else{
+ init();
+ }
+
+
+ /* mouseleave */
+ if(pJS.interactivity.status == 'mouseleave'){
+ init();
+ }
+
+ }
+
+ /* on click event */
+ else if(pJS.interactivity.events.onclick.enable && isInArray('bubble', pJS.interactivity.events.onclick.mode)){
+
+
+ if(pJS.tmp.bubble_clicking){
+ var dx_mouse = p.x - pJS.interactivity.mouse.click_pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.click_pos_y,
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse),
+ time_spent = (new Date().getTime() - pJS.interactivity.mouse.click_time)/1000;
+
+ if(time_spent > pJS.interactivity.modes.bubble.duration){
+ pJS.tmp.bubble_duration_end = true;
+ }
+
+ if(time_spent > pJS.interactivity.modes.bubble.duration*2){
+ pJS.tmp.bubble_clicking = false;
+ pJS.tmp.bubble_duration_end = false;
+ }
+ }
+
+
+ function process(bubble_param, particles_param, p_obj_bubble, p_obj, id){
+
+ if(bubble_param != particles_param){
+
+ if(!pJS.tmp.bubble_duration_end){
+ if(dist_mouse <= pJS.interactivity.modes.bubble.distance){
+ if(p_obj_bubble != undefined) var obj = p_obj_bubble;
+ else var obj = p_obj;
+ if(obj != bubble_param){
+ var value = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration);
+ if(id == 'size') p.radius_bubble = value;
+ if(id == 'opacity') p.opacity_bubble = value;
+ }
+ }else{
+ if(id == 'size') p.radius_bubble = undefined;
+ if(id == 'opacity') p.opacity_bubble = undefined;
+ }
+ }else{
+ if(p_obj_bubble != undefined){
+ var value_tmp = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration),
+ dif = bubble_param - value_tmp;
+ value = bubble_param + dif;
+ if(id == 'size') p.radius_bubble = value;
+ if(id == 'opacity') p.opacity_bubble = value;
+ }
+ }
+
+ }
+
+ }
+
+ if(pJS.tmp.bubble_clicking){
+ /* size */
+ process(pJS.interactivity.modes.bubble.size, pJS.particles.size.value, p.radius_bubble, p.radius, 'size');
+ /* opacity */
+ process(pJS.interactivity.modes.bubble.opacity, pJS.particles.opacity.value, p.opacity_bubble, p.opacity, 'opacity');
+ }
+
+ }
+
+ };
+
+
+ pJS.fn.modes.repulseParticle = function(p){
+
+ if(pJS.interactivity.events.onhover.enable && isInArray('repulse', pJS.interactivity.events.onhover.mode) && pJS.interactivity.status == 'mousemove') {
+
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse);
+
+ var normVec = {x: dx_mouse/dist_mouse, y: dy_mouse/dist_mouse},
+ repulseRadius = pJS.interactivity.modes.repulse.distance,
+ velocity = 100,
+ repulseFactor = clamp((1/repulseRadius)*(-1*Math.pow(dist_mouse/repulseRadius,2)+1)*repulseRadius*velocity, 0, 50);
+
+ var pos = {
+ x: p.x + normVec.x * repulseFactor,
+ y: p.y + normVec.y * repulseFactor
+ }
+
+ if(pJS.particles.move.out_mode == 'bounce'){
+ if(pos.x - p.radius > 0 && pos.x + p.radius < pJS.canvas.w) p.x = pos.x;
+ if(pos.y - p.radius > 0 && pos.y + p.radius < pJS.canvas.h) p.y = pos.y;
+ }else{
+ p.x = pos.x;
+ p.y = pos.y;
+ }
+
+ }
+
+
+ else if(pJS.interactivity.events.onclick.enable && isInArray('repulse', pJS.interactivity.events.onclick.mode)) {
+
+ if(!pJS.tmp.repulse_finish){
+ pJS.tmp.repulse_count++;
+ if(pJS.tmp.repulse_count == pJS.particles.array.length){
+ pJS.tmp.repulse_finish = true;
+ }
+ }
+
+ if(pJS.tmp.repulse_clicking){
+
+ var repulseRadius = Math.pow(pJS.interactivity.modes.repulse.distance/6, 3);
+
+ var dx = pJS.interactivity.mouse.click_pos_x - p.x,
+ dy = pJS.interactivity.mouse.click_pos_y - p.y,
+ d = dx*dx + dy*dy;
+
+ var force = -repulseRadius / d * 1;
+
+ function process(){
+
+ var f = Math.atan2(dy,dx);
+ p.vx = force * Math.cos(f);
+ p.vy = force * Math.sin(f);
+
+ if(pJS.particles.move.out_mode == 'bounce'){
+ var pos = {
+ x: p.x + p.vx,
+ y: p.y + p.vy
+ }
+ if (pos.x + p.radius > pJS.canvas.w) p.vx = -p.vx;
+ else if (pos.x - p.radius < 0) p.vx = -p.vx;
+ if (pos.y + p.radius > pJS.canvas.h) p.vy = -p.vy;
+ else if (pos.y - p.radius < 0) p.vy = -p.vy;
+ }
+
+ }
+
+ // default
+ if(d <= repulseRadius){
+ process();
+ }
+
+ // bang - slow motion mode
+ // if(!pJS.tmp.repulse_finish){
+ // if(d <= repulseRadius){
+ // process();
+ // }
+ // }else{
+ // process();
+ // }
+
+
+ }else{
+
+ if(pJS.tmp.repulse_clicking == false){
+
+ p.vx = p.vx_i;
+ p.vy = p.vy_i;
+
+ }
+
+ }
+
+ }
+
+ }
+
+
+ pJS.fn.modes.grabParticle = function(p){
+
+ if(pJS.interactivity.events.onhover.enable && pJS.interactivity.status == 'mousemove'){
+
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse);
+
+ /* draw a line between the cursor and the particle if the distance between them is under the config distance */
+ if(dist_mouse <= pJS.interactivity.modes.grab.distance){
+
+ var opacity_line = pJS.interactivity.modes.grab.line_linked.opacity - (dist_mouse / (1/pJS.interactivity.modes.grab.line_linked.opacity)) / pJS.interactivity.modes.grab.distance;
+
+ if(opacity_line > 0){
+
+ /* style */
+ var color_line = pJS.particles.line_linked.color_rgb_line;
+ pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')';
+ pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;
+ //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */
+
+ /* path */
+ pJS.canvas.ctx.beginPath();
+ pJS.canvas.ctx.moveTo(p.x, p.y);
+ pJS.canvas.ctx.lineTo(pJS.interactivity.mouse.pos_x, pJS.interactivity.mouse.pos_y);
+ pJS.canvas.ctx.stroke();
+ pJS.canvas.ctx.closePath();
+
+ }
+
+ }
+
+ }
+
+ };
+
+
+
+ /* ---------- pJS functions - vendors ------------ */
+
+ pJS.fn.vendors.eventsListeners = function(){
+
+ /* events target element */
+ if(pJS.interactivity.detect_on == 'window'){
+ pJS.interactivity.el = window;
+ }else{
+ pJS.interactivity.el = pJS.canvas.el;
+ }
+
+
+ /* detect mouse pos - on hover / click event */
+ if(pJS.interactivity.events.onhover.enable || pJS.interactivity.events.onclick.enable){
+
+ /* el on mousemove */
+ pJS.interactivity.el.addEventListener('mousemove', function(e){
+
+ if(pJS.interactivity.el == window){
+ var pos_x = e.clientX,
+ pos_y = e.clientY;
+ }
+ else{
+ var pos_x = e.offsetX || e.clientX,
+ pos_y = e.offsetY || e.clientY;
+ }
+
+ pJS.interactivity.mouse.pos_x = pos_x;
+ pJS.interactivity.mouse.pos_y = pos_y;
+
+ if(pJS.tmp.retina){
+ pJS.interactivity.mouse.pos_x *= pJS.canvas.pxratio;
+ pJS.interactivity.mouse.pos_y *= pJS.canvas.pxratio;
+ }
+
+ pJS.interactivity.status = 'mousemove';
+
+ });
+
+ /* el on onmouseleave */
+ pJS.interactivity.el.addEventListener('mouseleave', function(e){
+
+ pJS.interactivity.mouse.pos_x = null;
+ pJS.interactivity.mouse.pos_y = null;
+ pJS.interactivity.status = 'mouseleave';
+
+ });
+
+ }
+
+ /* on click event */
+ if(pJS.interactivity.events.onclick.enable){
+
+ pJS.interactivity.el.addEventListener('click', function(){
+
+ pJS.interactivity.mouse.click_pos_x = pJS.interactivity.mouse.pos_x;
+ pJS.interactivity.mouse.click_pos_y = pJS.interactivity.mouse.pos_y;
+ pJS.interactivity.mouse.click_time = new Date().getTime();
+
+ if(pJS.interactivity.events.onclick.enable){
+
+ switch(pJS.interactivity.events.onclick.mode){
+
+ case 'push':
+ if(pJS.particles.move.enable){
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);
+ }else{
+ if(pJS.interactivity.modes.push.particles_nb == 1){
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);
+ }
+ else if(pJS.interactivity.modes.push.particles_nb > 1){
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb);
+ }
+ }
+ break;
+
+ case 'remove':
+ pJS.fn.modes.removeParticles(pJS.interactivity.modes.remove.particles_nb);
+ break;
+
+ case 'bubble':
+ pJS.tmp.bubble_clicking = true;
+ break;
+
+ case 'repulse':
+ pJS.tmp.repulse_clicking = true;
+ pJS.tmp.repulse_count = 0;
+ pJS.tmp.repulse_finish = false;
+ setTimeout(function(){
+ pJS.tmp.repulse_clicking = false;
+ }, pJS.interactivity.modes.repulse.duration*1000)
+ break;
+
+ }
+
+ }
+
+ });
+
+ }
+
+
+ };
+
+ pJS.fn.vendors.densityAutoParticles = function(){
+
+ if(pJS.particles.number.density.enable){
+
+ /* calc area */
+ var area = pJS.canvas.el.width * pJS.canvas.el.height / 1000;
+ if(pJS.tmp.retina){
+ area = area/(pJS.canvas.pxratio*2);
+ }
+
+ /* calc number of particles based on density area */
+ var nb_particles = area * pJS.particles.number.value / pJS.particles.number.density.value_area;
+
+ /* add or remove X particles */
+ var missing_particles = pJS.particles.array.length - nb_particles;
+ if(missing_particles < 0) pJS.fn.modes.pushParticles(Math.abs(missing_particles));
+ else pJS.fn.modes.removeParticles(missing_particles);
+
+ }
+
+ };
+
+
+ pJS.fn.vendors.checkOverlap = function(p1, position){
+ for(var i = 0; i < pJS.particles.array.length; i++){
+ var p2 = pJS.particles.array[i];
+
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx*dx + dy*dy);
+
+ if(dist <= p1.radius + p2.radius){
+ p1.x = position ? position.x : Math.random() * pJS.canvas.w;
+ p1.y = position ? position.y : Math.random() * pJS.canvas.h;
+ pJS.fn.vendors.checkOverlap(p1);
+ }
+ }
+ };
+
+
+ pJS.fn.vendors.createSvgImg = function(p){
+
+ /* set color to svg element */
+ var svgXml = pJS.tmp.source_svg,
+ rgbHex = /#([0-9A-F]{3,6})/gi,
+ coloredSvgXml = svgXml.replace(rgbHex, function (m, r, g, b) {
+ if(p.color.rgb){
+ var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+p.opacity+')';
+ }else{
+ var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+p.opacity+')';
+ }
+ return color_value;
+ });
+
+ /* prepare to create img with colored svg */
+ var svg = new Blob([coloredSvgXml], {type: 'image/svg+xml;charset=utf-8'}),
+ DOMURL = window.URL || window.webkitURL || window,
+ url = DOMURL.createObjectURL(svg);
+
+ /* create particle img obj */
+ var img = new Image();
+ img.addEventListener('load', function(){
+ p.img.obj = img;
+ p.img.loaded = true;
+ DOMURL.revokeObjectURL(url);
+ pJS.tmp.count_svg++;
+ });
+ img.src = url;
+
+ };
+
+
+ pJS.fn.vendors.destroypJS = function(){
+ cancelAnimationFrame(pJS.fn.drawAnimFrame);
+ canvas_el.remove();
+ pJSDom = null;
+ };
+
+
+ pJS.fn.vendors.drawShape = function(c, startX, startY, sideLength, sideCountNumerator, sideCountDenominator){
+
+ // By Programming Thomas - https://programmingthomas.wordpress.com/2013/04/03/n-sided-shapes/
+ var sideCount = sideCountNumerator * sideCountDenominator;
+ var decimalSides = sideCountNumerator / sideCountDenominator;
+ var interiorAngleDegrees = (180 * (decimalSides - 2)) / decimalSides;
+ var interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180; // convert to radians
+ c.save();
+ c.beginPath();
+ c.translate(startX, startY);
+ c.moveTo(0,0);
+ for (var i = 0; i < sideCount; i++) {
+ c.lineTo(sideLength,0);
+ c.translate(sideLength,0);
+ c.rotate(interiorAngle);
+ }
+ //c.stroke();
+ c.fill();
+ c.restore();
+
+ };
+
+ pJS.fn.vendors.exportImg = function(){
+ window.open(pJS.canvas.el.toDataURL('image/png'), '_blank');
+ };
+
+
+ pJS.fn.vendors.loadImg = function(type){
+
+ pJS.tmp.img_error = undefined;
+
+ if(pJS.particles.shape.image.src != ''){
+
+ if(type == 'svg'){
+
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', pJS.particles.shape.image.src);
+ xhr.onreadystatechange = function (data) {
+ if(xhr.readyState == 4){
+ if(xhr.status == 200){
+ pJS.tmp.source_svg = data.currentTarget.response;
+ pJS.fn.vendors.checkBeforeDraw();
+ }else{
+ console.log('Error pJS - Image not found');
+ pJS.tmp.img_error = true;
+ }
+ }
+ }
+ xhr.send();
+
+ }else{
+
+ var img = new Image();
+ img.addEventListener('load', function(){
+ pJS.tmp.img_obj = img;
+ pJS.fn.vendors.checkBeforeDraw();
+ });
+ img.src = pJS.particles.shape.image.src;
+
+ }
+
+ }else{
+ console.log('Error pJS - No image.src');
+ pJS.tmp.img_error = true;
+ }
+
+ };
+
+
+ pJS.fn.vendors.draw = function(){
+
+ if(pJS.particles.shape.type == 'image'){
+
+ if(pJS.tmp.img_type == 'svg'){
+
+ if(pJS.tmp.count_svg >= pJS.particles.number.value){
+ pJS.fn.particlesDraw();
+ if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }else{
+ //console.log('still loading...');
+ if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }
+
+ }else{
+
+ if(pJS.tmp.img_obj != undefined){
+ pJS.fn.particlesDraw();
+ if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }else{
+ if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }
+
+ }
+
+ }else{
+ pJS.fn.particlesDraw();
+ if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }
+
+ };
+
+
+ pJS.fn.vendors.checkBeforeDraw = function(){
+
+ // if shape is image
+ if(pJS.particles.shape.type == 'image'){
+
+ if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg == undefined){
+ pJS.tmp.checkAnimFrame = requestAnimFrame(check);
+ }else{
+ //console.log('images loaded! cancel check');
+ cancelRequestAnimFrame(pJS.tmp.checkAnimFrame);
+ if(!pJS.tmp.img_error){
+ pJS.fn.vendors.init();
+ pJS.fn.vendors.draw();
+ }
+
+ }
+
+ }else{
+ pJS.fn.vendors.init();
+ pJS.fn.vendors.draw();
+ }
+
+ };
+
+
+ pJS.fn.vendors.init = function(){
+
+ /* init canvas + particles */
+ pJS.fn.retinaInit();
+ pJS.fn.canvasInit();
+ pJS.fn.canvasSize();
+ pJS.fn.canvasPaint();
+ pJS.fn.particlesCreate();
+ pJS.fn.vendors.densityAutoParticles();
+
+ /* particles.line_linked - convert hex colors to rgb */
+ pJS.particles.line_linked.color_rgb_line = hexToRgb(pJS.particles.line_linked.color);
+
+ };
+
+
+ pJS.fn.vendors.start = function(){
+
+ if(isInArray('image', pJS.particles.shape.type)){
+ pJS.tmp.img_type = pJS.particles.shape.image.src.substr(pJS.particles.shape.image.src.length - 3);
+ pJS.fn.vendors.loadImg(pJS.tmp.img_type);
+ }else{
+ pJS.fn.vendors.checkBeforeDraw();
+ }
+
+ };
+
+
+
+
+ /* ---------- pJS - start ------------ */
+
+
+ pJS.fn.vendors.eventsListeners();
+
+ pJS.fn.vendors.start();
+
+
+
+};
+
+/* ---------- global functions - vendors ------------ */
+
+Object.deepExtend = function ED(destination, source) {
+ for (var property in source) {
+ if (source[property] && source[property].constructor &&
+ source[property].constructor === Object) {
+ destination[property] = destination[property] || {};
+ ED(destination[property], source[property]);
+ } else {
+ destination[property] = source[property];
+ }
+ }
+ return destination;
+};
+
+window.requestAnimFrame = (function(){
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function(callback){
+ window.setTimeout(callback, 1000 / 60);
+ };
+})();
+
+window.cancelRequestAnimFrame = ( function() {
+ return window.cancelAnimationFrame ||
+ window.webkitCancelRequestAnimationFrame ||
+ window.mozCancelRequestAnimationFrame ||
+ window.oCancelRequestAnimationFrame ||
+ window.msCancelRequestAnimationFrame ||
+ clearTimeout
+} )();
+
+function hexToRgb(hex){
+ // By Tim Down - http://stackoverflow.com/a/5624139/3493650
+ // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
+ var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
+ hex = hex.replace(shorthandRegex, function(m, r, g, b) {
+ return r + r + g + g + b + b;
+ });
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ return result ? {
+ r: parseInt(result[1], 16),
+ g: parseInt(result[2], 16),
+ b: parseInt(result[3], 16)
+ } : null;
+};
+
+function clamp(number, min, max) {
+ return Math.min(Math.max(number, min), max);
+};
+
+function isInArray(value, array) {
+ return array.indexOf(value) > -1;
+}
+
+
+/* ---------- particles.js functions - start ------------ */
+
+window.pJSDom = [];
+
+window.particlesJS = function(tag_id, params){
+
+ //console.log(params);
+
+ /* no string id? so it's object params, and set the id with default id */
+ if(typeof(tag_id) != 'string'){
+ params = tag_id;
+ tag_id = 'particles-js';
+ }
+
+ /* no id? set the id to default id */
+ if(!tag_id){
+ tag_id = 'particles-js';
+ }
+
+ /* pJS elements */
+ var pJS_tag = document.getElementById(tag_id),
+ pJS_canvas_class = 'particles-js-canvas-el',
+ exist_canvas = pJS_tag.getElementsByClassName(pJS_canvas_class);
+
+ /* remove canvas if exists into the pJS target tag */
+ if(exist_canvas.length){
+ while(exist_canvas.length > 0){
+ pJS_tag.removeChild(exist_canvas[0]);
+ }
+ }
+
+ /* create canvas element */
+ var canvas_el = document.createElement('canvas');
+ canvas_el.className = pJS_canvas_class;
+
+ /* set size canvas */
+ canvas_el.style.width = "100%";
+ canvas_el.style.height = "100%";
+
+ /* append canvas */
+ var canvas = document.getElementById(tag_id).appendChild(canvas_el);
+
+ /* launch particle.js */
+ if(canvas != null){
+ pJSDom.push(new pJS(tag_id, params));
+ }
+
+};
+
+window.particlesJS.load = function(tag_id, path_config_json, callback){
+
+ /* load json config */
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', path_config_json);
+ xhr.onreadystatechange = function (data) {
+ if(xhr.readyState == 4){
+ if(xhr.status == 200){
+ var params = JSON.parse(data.currentTarget.response);
+ window.particlesJS(tag_id, params);
+ if(callback) callback();
+ }else{
+ console.log('Error pJS - XMLHttpRequest status: '+xhr.status);
+ console.log('Error pJS - File config not found');
+ }
+ }
+ };
+ xhr.send();
+
+};
+}
+export {
+ loginBg
+}
\ No newline at end of file
diff --git a/static/loginPage.js/loginApp.js b/static/loginPage.js/loginApp.js
new file mode 100644
index 0000000..c5dd94b
--- /dev/null
+++ b/static/loginPage.js/loginApp.js
@@ -0,0 +1,137 @@
+/* -----------------------------------------------
+/* How to use? : Check the GitHub README
+/* ----------------------------------------------- */
+
+/* To load a config file (particles.json) you need to host this demo (MAMP/WAMP/local)... */
+/*
+particlesJS.load('particles-js', 'particles.json', function() {
+ console.log('particles.js loaded - callback');
+});
+*/
+
+/* Otherwise just put the config content (json): */
+function loginApp(){
+particlesJS('particles-js',
+
+ {
+ "particles": {
+ "number": {
+ "value": 80,
+ "density": {
+ "enable": true,
+ "value_area": 800
+ }
+ },
+ "color": {
+ "value": "#ffffff"
+ },
+ "shape": {
+ "type": "circle",
+ "stroke": {
+ "width": 0,
+ "color": "#000000"
+ },
+ "polygon": {
+ "nb_sides": 5
+ },
+ "image": {
+ "src": "img/github.svg",
+ "width": 100,
+ "height": 100
+ }
+ },
+ "opacity": {
+ "value": 0.5,
+ "random": false,
+ "anim": {
+ "enable": false,
+ "speed": 1,
+ "opacity_min": 0.1,
+ "sync": false
+ }
+ },
+ "size": {
+ "value": 5,
+ "random": true,
+ "anim": {
+ "enable": false,
+ "speed": 40,
+ "size_min": 0.1,
+ "sync": false
+ }
+ },
+ "line_linked": {
+ "enable": true,
+ "distance": 150,
+ "color": "#ffffff",
+ "opacity": 0.4,
+ "width": 1
+ },
+ "move": {
+ "enable": true,
+ "speed": 6,
+ "direction": "none",
+ "random": false,
+ "straight": false,
+ "out_mode": "out",
+ "attract": {
+ "enable": false,
+ "rotateX": 600,
+ "rotateY": 1200
+ }
+ }
+ },
+ "interactivity": {
+ "detect_on": "canvas",
+ "events": {
+ "onhover": {
+ "enable": true,
+ "mode": "repulse"
+ },
+ "onclick": {
+ "enable": true,
+ "mode": "push"
+ },
+ "resize": true
+ },
+ "modes": {
+ "grab": {
+ "distance": 400,
+ "line_linked": {
+ "opacity": 1
+ }
+ },
+ "bubble": {
+ "distance": 400,
+ "size": 40,
+ "duration": 2,
+ "opacity": 8,
+ "speed": 3
+ },
+ "repulse": {
+ "distance": 200
+ },
+ "push": {
+ "particles_nb": 4
+ },
+ "remove": {
+ "particles_nb": 2
+ }
+ }
+ },
+ "retina_detect": true,
+ "config_demo": {
+ "hide_card": false,
+ "background_color": "#b61924",
+ "background_image": "",
+ "background_position": "50% 50%",
+ "background_repeat": "no-repeat",
+ "background_size": "cover"
+ }
+ }
+
+);
+}
+export {
+ loginApp
+}
\ No newline at end of file
--
Gitblit v1.9.2