Commit 8e97b441 by zhanghui1

甲方功能嵌套login和reg

parent c223ccb8
File added
......@@ -356,4 +356,7 @@ html,body {-webkit-tap-highlight-color: rgba(0, 0, 0,0); font-size: 0.28rem; bac
}
}
}
}
.login-reg{
}
\ No newline at end of file
<template>
<div>
<input v-model="captcha_input" name="captcha"/>
<img :src="captchaUrl">
</div>
</template>
<script>
import config from '@/config'
console.log(config)
export default {
// beforeMount () {
// const captcha_img =;
// this.captchaUrl = captcha_img ;
// },
data(){
return {
captcha_input:'',
captchaUrl: 'http://ucdev1212.blockin.com/captcha?' + new Date().getTime()
}
},
methods:{
newCaptcha:function () {
}
}
}
</script>
\ No newline at end of file
<template>
<div class="captcha">
<input autofocus="true" class="left" ref="captchaIpt" type="text" v-model="captchaComputed" placeholder="请输入正确的验证码">
<img @click="newCaptcha" :src="captchaUrl" alt="">
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
props: ['captcha'],
beforeMount() {
this.captchaUrl = this.UC_BASEURL + '/captcha?' + new Date().getTime();
},
data() {
return {
captchaUrl: ''
}
},
computed: {
...mapState(["txt", 'UC_BASEURL']),
language() {
return this.$store.state.language || localStorage.getItem('language');
},
captchaComputed: {
get() {
return this.$props.captcha
},
set(captcha) {
this.$emit('dispatchCaptcha', captcha);
}
}
},
mounted() {
},
methods: {
newCaptcha() {
this.captchaUrl = this.UC_BASEURL + '/captcha?' + new Date().getTime();
},
focusCaptchaInput() {
// 这个地方有bug,用异步hack
setTimeout(() => {
this.$refs.captchaIpt.focus();
}, 100)
}
}
}
</script>
import axios from 'axios';
// import conf from './../config';
// let helpers = {};
// const domainUrl = conf.domain_url;
// export const getBus = (apiName, params, apiParams = {}) => {
// let url = conf.api[apiName];
// if ( ! url ) { // 如果取不到
// throw new Error('get DataBus not match url');
// }
// for (let _key in apiParams) {
// let value = apiParams[_key];
// let regArr = ['\{', _key, '\}'];
// // let regExp = new RegExp(regArr.join(''), 'igm');
// let regExp = new RegExp('\{'+_key+'\}', 'igm');
// url = url.replace(regExp, value);
// }
// // 获取token
// let access_token = localStorage.getItem('access_token');
// return new Promise((resolve, reject) => {
// axios.get(domainUrl+url, {
// params: params,
// headers: {
// // Authorization: 'Bearer ' + access_token
// }
// // withCredentials: true
// }).then( (response) => {
// resolve(response.data);
// }).catch( (error) => { // 该error是个json。
// let errorMsg = 'Network Error';
// if (error.response) {
// let errorStatus = error.response.status;
// switch (errorStatus) {
// case 401: // 未登录
// errorMsg = 'Please Login';
// break;
// case 500:
// default:
// if (error.response.data.message) {
// errorMsg = error.response.data.message;
// }
// break;
// }
// // console.log(error.response);
// } else {
// // console.log(error.message);
// }
// lolpool && lolpool.$message && lolpool.$message.error(errorMsg, 5);
// });
// });
// };
// export const postBus = (apiName, params, apiParams) => {
// let url = conf.api[apiName];
// if ( ! url ) { // 如果取不到url
// throw new Error('post DataBus not match url');
// }
// for (let _key in apiParams) {
// let value = apiParams[_key];
// let regArr = ['\{', _key, '\}'];
// let regExp = new RegExp('\{'+_key+'\}', 'igm');
// url = url.replace(regExp, value);
// }
// // 获取token
// let access_token = localStorage.getItem('access_token');
// return new Promise((resolve, reject) => {
// axios.post(domainUrl+url, params, {
// headers: {
// // 'Content-Type': 'application/x-www-form-urlencoded',
// // Authorization: 'Bearer ' + access_token
// }
// // withCredentials: true
// }).then( (response) => {
// resolve(response.data);
// }).catch( (error) => {
// let errorMsg = 'Network Error';
// if (error.response) {
// let errorStatus = error.response.status;
// switch (errorStatus) {
// case 401: // 未登录
// errorMsg = 'Please Login';
// break;
// case 500:
// default:
// if (error.response.data.message) {
// errorMsg = error.response.data.message;
// }
// break;
// }
// }
// lolpool && lolpool.$message && lolpool.$message.error(errorMsg, 5);
// });
// });
// }
// export const renderFullUrl = (api, apiParams) => {
// for (let _key in apiParams) {
// let value = apiParams[_key];
// let regArr = ['\{', _key, '\}'];
// // let regExp = new RegExp(regArr.join(''), 'igm');
// let regExp = new RegExp('\{'+_key+'\}', 'igm');
// api = api.replace(regExp, value);
// }
// return api;
// }
export const apiErrMap = (errNo, errMsg) => {
if (errNo == 0) {
return {
errNo: 0,
errMsg: ''
};
}
if (errNo == -1) {
return {
errNo: -1,
errMsg
};
}
// todo: 翻译
const errMap = new Map()
.set(100, '步骤不正确')
.set(1000, '请输入验证码')
.set(1001, '验证码错误')
.set(1010, '用户已存在')
.set(1011, '用户不存在')
.set(1012, '用户被锁定')
.set(1013, '登录次数过多')
.set(1014, '密码错误')
.set(1015, 'invalid totp code')
.set(1020, '验证码过多')
.set(1021, '无效手机号')
.set(1022, '邮箱地址无效')
.set(1023, '电话号码不支持')
.set(1024, 'sms rate limited');
errMsg = errMap.get(errNo);
if (errMsg) {
return {
errNo,
errMsg
}
}
return {
errNo,
errMsg: '网络错误'
}
}
export const isEmailAddress = (str) => {
return new RegExp('^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$').test(str);
}
export const isVerifyCode = (str) => {
return new RegExp('^[a-z0-9A-Z]{4}$').test(str);
}
// export const getServices = (serviceName) => {
// }
\ No newline at end of file
<template>
<div class="page">
<div class="page-header">
<div class="l" @click="goBack"><span class="icon-back"><i class="iconfont icon-fanhui"></i></span></div>
<div class="c">登录</div>
<div class="r"><span class="txt abs-right">注册</span></div>
</div>
<div class="page-content uc-login">
<!-- 邮箱登录 -->
<div class="login-emial" v-if="useMail">
<input type="email" ref="emailActIpt" v-model="form.email" placeholder="mail@example.com" />
<div v-show="showEmailCaptcha">
<captcha ref="emailCaptcha" :captcha="form.captcha" @dispatchCaptcha="getCaptchaValue"></captcha>
</div>
<input type="password" ref="emailPwd" v-model="form.password" placeholder="请输入密码">
</div>
<!-- 手机登录 -->
<div class="login-mobile" v-else>
<select class="mobile-country" v-model="form.country" aria-label="国家/地区代码">
<option v-for="(item, index) in countryInfo" :key="index" :value="item.phone_country_code">
<!-- todo: 电话号码语言联动 -->
{{ item['text_zh-cn'] + ' +' + item['phone_country_code'] }}
</option>
</select>
<input type="text" ref="mobileActIpt" v-model="form.email" placeholder="请输入手机号码" />
<div v-show="showMobileCaptcha">
<captcha ref="mobileCaptcha" :captcha="form.captcha" @dispatchCaptcha="getCaptchaValue"></captcha>
</div>
<input type="password" ref="mobilePwd" v-model="form.password" placeholder="请输入密码">
</div>
<div class="error-tip" v-show="errTipMsg != ''">{{errTipMsg}}</div>
<button @click="goLogin" :disabled="showLoading" :isLoading="showLoading">{{ showLoading ? '' : '登录' }}</button>
<div class="clearfix">
<a class="left" @click="switchLogin">{{ useMail ? '使用手机号登录' : '使用邮箱登录' }}</a>
<router-link class="right" to="/sign-up-mobile">注册</router-link>
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import countryInfo from './country_info.json'
import captcha from './captcha.vue'
import { apiErrMap, isEmailAddress, isVerifyCode } from './helpers.js';
export default {
components: {
captcha
},
beforeMount() {
this.useMail = localStorage.getItem('login-type') == 'email';
this.form.country = '86';
// 渲染上次登录
let accountInfo = localStorage.getItem('account-info');
if (accountInfo) {
accountInfo = JSON.parse(accountInfo);
if (accountInfo.account) { // 有账号信息
if (accountInfo.type == 'mobile') {
let phoneNumber = accountInfo.account.split('|');
this.form.country = phoneNumber[0] ? phoneNumber[0] : '';
this.form.email = phoneNumber[1] ? phoneNumber[1] : '';
} else {
this.form.email = accountInfo.account ? accountInfo.account : '';
}
}
this.useMail = accountInfo.type == 'email';
}
},
mounted() {},
computed: {
...mapState(["txt", 'UC_BASEURL']),
},
data() {
return {
countryInfo: countryInfo.data,
errTipMsg: '',
form: { "country": "86", "captcha": "", "email": "", "password": "" },
showEmailCaptcha: false,
showLoading: false,
showMobileCaptcha: false,
step: 1,
useMail: false
}
},
methods: {
async goLogin() {
if (this.showLoading) {
return '';
}
this.errTipMsg = '';
let email = ''; // 用于浏览器端保存用户账号信息
this.showLoading = true;
if (this.useMail) { // 邮箱登录
// 检测参数是否存在
if (!isEmailAddress(this.form.email)) {
this.showErrorTip(-1, '请输入正确的邮箱地址');
return;
}
if (this.showEmailCaptcha && !isVerifyCode(this.form.captcha)) {
this.showErrorTip(-1, '请输入正确的验证码');
return;
}
if (this.form.password == '') {
this.showErrorTip(-1, '请输入密码');
return;
}
email = this.form.email;
const { data: accountResponse } = await this.$axios
.post(config.apiDomain + config.api['post-login-start'], {
captcha: this.showEmailCaptcha ? this.form.captcha : '', // todo: 登录验证码
email,
type: 'email'
});
if (accountResponse.err_no) {
if (accountResponse.err_no == 1000 && !this.showEmailCaptcha) { // 需要验证码
this.showErrorTip(-1, '');
this.showEmailCaptcha = true;
this.form.password = '';
this.$refs.emailCaptcha.focusCaptchaInput();
return;
}
this.showErrorTip(accountResponse.err_no, accountResponse.err_msg);
return;
}
const { data: passwordResponse } = await this.$axios
.post(config.apiDomain + config.api['post-login-password'], {
password: this.form.password
});
// 登录失败
if (passwordResponse.err_no) {
this.showErrorTip(passwordResponse.err_no, passwordResponse.err_msg);
return;
}
} else { // 手机登录
// 检测参数是否存在
if (this.form.email == '' || this.form.country == '') {
this.showErrorTip(-1, '请输入手机号码');
return;
}
if (this.showMobileCaptcha && !isVerifyCode(this.form.captcha)) {
this.showErrorTip(-1, '请输入正确的验证码');
return;
}
if (this.form.password == '') {
this.showErrorTip(-1, '请输入密码');
return;
}
email = this.form.country + '|' + this.form.email;
const { data: accountResponse } = await this.$axios
.post(config.apiDomain + config.api['post-login-start'], {
captcha: this.showMobileCaptcha ? this.form.captcha : '', // todo: 登录验证码
email,
type: 'mobile'
});
// 增加错误id提示
if (accountResponse.err_no) {
if (accountResponse.err_no == 1000 && !this.showMobileCaptcha) { // 需要验证码
this.showErrorTip(-1, '');
this.showMobileCaptcha = true;
this.form.password = '';
this.$refs.mobileCaptcha.focusCaptchaInput();
return;
}
this.showErrorTip(accountResponse.err_no, accountResponse.err_msg);
return;
}
const { data: passwordResponse } = await this.$axios
.post(config.apiDomain + config.api['post-login-password'], {
password: this.form.password
});
// 登录失败
if (passwordResponse.err_no) {
this.showErrorTip(passwordResponse.err_no, passwordResponse.err_msg);
return;
}
}
// 获取用户信息
const userinfo = await this.$store.dispatch("Auth/fetchUser");
this.showLoading = false;
// 跳转用户中心
this.$router.push({
name: 'home'
});
// 记录登录信息
localStorage.setItem('account-info', JSON.stringify({
'account': email,
'type': this.useMail ? 'email' : 'mobile'
}));
},
showErrorTip(errNo, errMsg) {
this.showLoading = false;
this.errTipMsg = apiErrMap(errNo, errMsg).errMsg;
},
goBack() {
this.$router.go(-1)
},
getCaptchaValue(captcha) {
this.form.captcha = captcha;
},
switchLogin() {
this.useMail = !this.useMail;
this.form.email = '';
if (this.useMail) {
localStorage.setItem('login-type', 'email');
this.showEmailCaptcha = false;
this.$refs.mobileActIpt.focus();
} else {
localStorage.setItem('login-type', 'mobile');
this.showMobileCaptcha = false;
this.$refs.emailActIpt.focus();
}
},
},
}
</script>
<template>
<div>邮箱注册页</div>
</template>
<script>
export default{
data(){
return {}
}
}
</script>
\ No newline at end of file
<template>
<div>手机注册页</div>
</template>
<script>
export default{
data(){
return {}
}
}
</script>
\ No newline at end of file
......@@ -112,21 +112,21 @@ const router = new Router({
title: 'settings.vue'
}
}]
},{
}, {
path: '/address',
name: 'modifyAddress',
component: resolve => require(['@/components/settings/address.vue'], resolve),
meta: {
title: 'address.vue'
}
},{
}, {
path: '/search',
name: 'search',
component: resolve => require(['@/components/miners/search.vue'], resolve),
meta: {
title: 'search.vue'
}
},{
}, {
path: '/defaultCoin',
name: 'defaultCoin',
component: resolve => require(['@/components/settings/defaultCoin'], resolve),
......@@ -175,6 +175,24 @@ const router = new Router({
meta: {
title: 'moban.vue'
}
}, {
path: '/ucenter',
component: resolve => require(['@/components/ucenter'], resolve),
meta: {
title: 'userCenter/index.vue'
}
}, {
path: '/sign-up-mobile',
component: resolve => require(['@/components/ucenter/signUpMobile'], resolve),
meta: {
title: '手机注册'
}
}, {
path: '/sign-up-email',
component: resolve => require(['@/components/ucenter/signUpEmail'], resolve),
meta: {
title: '邮箱注册'
}
}
]
})
......
......@@ -5,72 +5,74 @@ Vue.use(Vuex);
import dictionaries from '@/utils/dictionaries.js'; //字典
const state = {
refresh_time: 10000, //定时刷新
// is_login: $auth.isAuthenticated(), //是否登录
init_url: {}, //全站入口信息
cur_coins: [], //获取支持的币种
txt: dictionaries.txt, //字典
language: 'zh-cn', //en/zh-cn切换语言,从localStorage中取;
coin_type_show: false, //是否显示币种切换
enter_panel:false,//是否从子账户面板进来的
refresh_time: 10000, //定时刷新
// is_login: $auth.isAuthenticated(), //是否登录
init_url: {}, //全站入口信息
cur_coins: [], //获取支持的币种
txt: dictionaries.txt, //字典
language: 'zh-cn', //en/zh-cn切换语言,从localStorage中取;
coin_type_show: false, //是否显示币种切换
enter_panel: false, //是否从子账户面板进来的
base_url: "http://ltc-bj-dev.c6396418dd7954b228d8b967c8a929103.cn-beijing.alicontainer.com/api/public/v1/url", //初始接口
common_url: "http://ltc-bj-dev.c6396418dd7954b228d8b967c8a929103.cn-beijing.alicontainer.com/api/public/v1", //币种切换对应的baseUrl
base_url: "http://ltc-bj-dev.c6396418dd7954b228d8b967c8a929103.cn-beijing.alicontainer.com/api/public/v1/url", //初始接口
common_url: "http://ltc-bj-dev.c6396418dd7954b228d8b967c8a929103.cn-beijing.alicontainer.com/api/public/v1", //币种切换对应的baseUrl
// base_url: "BASE_URL", //初始接口
// common_url: "COMMON_URL", //币种切换对应的baseUrl
// base_url: "BASE_URL", //初始接口
// common_url: "COMMON_URL", //币种切换对应的baseUrl
puid: '', //初始用户id为空,与localStorage同步
coin_type: '', //默认币种类型
region_id: '', //默认节点
refresh:'',
tab_bar:0
puid: '', //初始用户id为空,与localStorage同步
coin_type: '', //默认币种类型
region_id: '', //默认节点
refresh: '',
tab_bar: 0,
UC_BASEURL: 'https://ucdev1212.blockin.com',
}
const mutations = {
setEnterPannel(state,v){
state.enter_panel=v;
localStorage.setItem("enter_panel", v);
},
setRefresh(state){
state.refresh=new Date().getTime();
},
setInitUrl(state, v) {
state.init_url = v;
},
setCurCoins(state, v) {
state.cur_coins = v
},
setCoinType(state, v) {
state.coin_type = v;
localStorage.setItem("coin_type", v);
},
setRegionId(state, v) {
state.region_id = v
localStorage.setItem("region_id", v);
},
setPuid(state, v) {
state.puid = v
localStorage.setItem("puid", v);
},
setLanguage(state,v){
state.language = v
localStorage.setItem("language", v);
}
setEnterPannel(state, v) {
state.enter_panel = v;
localStorage.setItem("enter_panel", v);
},
setRefresh(state) {
state.refresh = new Date().getTime();
},
setInitUrl(state, v) {
state.init_url = v;
},
setCurCoins(state, v) {
state.cur_coins = v
},
setCoinType(state, v) {
state.coin_type = v;
localStorage.setItem("coin_type", v);
},
setRegionId(state, v) {
state.region_id = v
localStorage.setItem("region_id", v);
},
setPuid(state, v) {
state.puid = v
localStorage.setItem("puid", v);
},
setLanguage(state, v) {
state.language = v
localStorage.setItem("language", v);
}
}
const getters = {
// count: function(state) {
// return state.count += 100;
// }
// count: function(state) {
// return state.count += 100;
// }
}
const actions = {
// addAction(context) {
// context.commit('add', 10)
// }
// addAction(context) {
// context.commit('add', 10)
// }
}
export default new Vuex.Store({
state,
mutations,
getters,
actions
state,
mutations,
getters,
actions
})
<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M9 11.75c-.69 0-1.25.56-1.25 1.25s.56 1.25 1.25 1.25 1.25-.56 1.25-1.25-.56-1.25-1.25-1.25zm6 0c-.69 0-1.25.56-1.25 1.25s.56 1.25 1.25 1.25 1.25-.56 1.25-1.25-.56-1.25-1.25-1.25zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8 0-.29.02-.58.05-.86 2.36-1.05 4.23-2.98 5.21-5.37C11.07 8.33 14.05 10 17.42 10c.78 0 1.53-.09 2.25-.26.21.71.33 1.47.33 2.26 0 4.41-3.59 8-8 8z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</svg>
\ No newline at end of file
<svg fill="#000000" height="18" viewBox="0 0 24 24" width="18" xmlns="http://www.w3.org/2000/svg">
<path d="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z"/>
<path d="M0-.75h24v24H0z" fill="none"/>
</svg>
\ No newline at end of file
<svg class="lds-spinner" width="200px" height="200px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" style="background: none;"><g transform="rotate(0 50 50)">
<rect x="47" y="22" rx="15.51" ry="7.26" width="6" height="10" fill="#18a8ea">
<animate attributeName="opacity" values="1;0" times="0;1" dur="1.1s" begin="-1.0083333333333335s" repeatCount="indefinite"></animate>
</rect>
</g><g transform="rotate(30 50 50)">
<rect x="47" y="22" rx="15.51" ry="7.26" width="6" height="10" fill="#18a8ea">
<animate attributeName="opacity" values="1;0" times="0;1" dur="1.1s" begin="-0.9166666666666666s" repeatCount="indefinite"></animate>
</rect>
</g><g transform="rotate(60 50 50)">
<rect x="47" y="22" rx="15.51" ry="7.26" width="6" height="10" fill="#18a8ea">
<animate attributeName="opacity" values="1;0" times="0;1" dur="1.1s" begin="-0.8250000000000001s" repeatCount="indefinite"></animate>
</rect>
</g><g transform="rotate(90 50 50)">
<rect x="47" y="22" rx="15.51" ry="7.26" width="6" height="10" fill="#18a8ea">
<animate attributeName="opacity" values="1;0" times="0;1" dur="1.1s" begin="-0.7333333333333334s" repeatCount="indefinite"></animate>
</rect>
</g><g transform="rotate(120 50 50)">
<rect x="47" y="22" rx="15.51" ry="7.26" width="6" height="10" fill="#18a8ea">
<animate attributeName="opacity" values="1;0" times="0;1" dur="1.1s" begin="-0.6416666666666667s" repeatCount="indefinite"></animate>
</rect>
</g><g transform="rotate(150 50 50)">
<rect x="47" y="22" rx="15.51" ry="7.26" width="6" height="10" fill="#18a8ea">
<animate attributeName="opacity" values="1;0" times="0;1" dur="1.1s" begin="-0.55s" repeatCount="indefinite"></animate>
</rect>
</g><g transform="rotate(180 50 50)">
<rect x="47" y="22" rx="15.51" ry="7.26" width="6" height="10" fill="#18a8ea">
<animate attributeName="opacity" values="1;0" times="0;1" dur="1.1s" begin="-0.4583333333333333s" repeatCount="indefinite"></animate>
</rect>
</g><g transform="rotate(210 50 50)">
<rect x="47" y="22" rx="15.51" ry="7.26" width="6" height="10" fill="#18a8ea">
<animate attributeName="opacity" values="1;0" times="0;1" dur="1.1s" begin="-0.3666666666666667s" repeatCount="indefinite"></animate>
</rect>
</g><g transform="rotate(240 50 50)">
<rect x="47" y="22" rx="15.51" ry="7.26" width="6" height="10" fill="#18a8ea">
<animate attributeName="opacity" values="1;0" times="0;1" dur="1.1s" begin="-0.275s" repeatCount="indefinite"></animate>
</rect>
</g><g transform="rotate(270 50 50)">
<rect x="47" y="22" rx="15.51" ry="7.26" width="6" height="10" fill="#18a8ea">
<animate attributeName="opacity" values="1;0" times="0;1" dur="1.1s" begin="-0.18333333333333335s" repeatCount="indefinite"></animate>
</rect>
</g><g transform="rotate(300 50 50)">
<rect x="47" y="22" rx="15.51" ry="7.26" width="6" height="10" fill="#18a8ea">
<animate attributeName="opacity" values="1;0" times="0;1" dur="1.1s" begin="-0.09166666666666667s" repeatCount="indefinite"></animate>
</rect>
</g><g transform="rotate(330 50 50)">
<rect x="47" y="22" rx="15.51" ry="7.26" width="6" height="10" fill="#18a8ea">
<animate attributeName="opacity" values="1;0" times="0;1" dur="1.1s" begin="0s" repeatCount="indefinite"></animate>
</rect>
</g></svg>
\ No newline at end of file
<svg class="lds-default" width="100px" height="100px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" style="background: none;"><circle cx="75" cy="50" fill="undefined" r="3.6">
<animate attributeName="r" values="3.5999999999999996;3.5999999999999996;6;3.5999999999999996;3.5999999999999996" times="0;0.1;0.2;0.3;1" dur="2.2s" repeatCount="indefinite" begin="-1.98s"></animate>
<animate attributeName="fill" values="#3d7d9a;#3d7d9a;#45a6d2;#3d7d9a;#3d7d9a" repeatCount="indefinite" times="0;0.1;0.2;0.3;1" dur="2.2s" begin="-1.98s"></animate>
</circle><circle cx="70.225" cy="64.695" fill="undefined" r="3.6">
<animate attributeName="r" values="3.5999999999999996;3.5999999999999996;6;3.5999999999999996;3.5999999999999996" times="0;0.1;0.2;0.3;1" dur="2.2s" repeatCount="indefinite" begin="-1.76s"></animate>
<animate attributeName="fill" values="#3d7d9a;#3d7d9a;#45a6d2;#3d7d9a;#3d7d9a" repeatCount="indefinite" times="0;0.1;0.2;0.3;1" dur="2.2s" begin="-1.76s"></animate>
</circle><circle cx="57.725" cy="73.776" fill="undefined" r="4.15273">
<animate attributeName="r" values="3.5999999999999996;3.5999999999999996;6;3.5999999999999996;3.5999999999999996" times="0;0.1;0.2;0.3;1" dur="2.2s" repeatCount="indefinite" begin="-1.54s"></animate>
<animate attributeName="fill" values="#3d7d9a;#3d7d9a;#45a6d2;#3d7d9a;#3d7d9a" repeatCount="indefinite" times="0;0.1;0.2;0.3;1" dur="2.2s" begin="-1.54s"></animate>
</circle><circle cx="42.275" cy="73.776" fill="undefined" r="5.11273">
<animate attributeName="r" values="3.5999999999999996;3.5999999999999996;6;3.5999999999999996;3.5999999999999996" times="0;0.1;0.2;0.3;1" dur="2.2s" repeatCount="indefinite" begin="-1.32s"></animate>
<animate attributeName="fill" values="#3d7d9a;#3d7d9a;#45a6d2;#3d7d9a;#3d7d9a" repeatCount="indefinite" times="0;0.1;0.2;0.3;1" dur="2.2s" begin="-1.32s"></animate>
</circle><circle cx="29.775" cy="64.695" fill="undefined" r="5.92727">
<animate attributeName="r" values="3.5999999999999996;3.5999999999999996;6;3.5999999999999996;3.5999999999999996" times="0;0.1;0.2;0.3;1" dur="2.2s" repeatCount="indefinite" begin="-1.1s"></animate>
<animate attributeName="fill" values="#3d7d9a;#3d7d9a;#45a6d2;#3d7d9a;#3d7d9a" repeatCount="indefinite" times="0;0.1;0.2;0.3;1" dur="2.2s" begin="-1.1s"></animate>
</circle><circle cx="25" cy="50" fill="undefined" r="4.96727">
<animate attributeName="r" values="3.5999999999999996;3.5999999999999996;6;3.5999999999999996;3.5999999999999996" times="0;0.1;0.2;0.3;1" dur="2.2s" repeatCount="indefinite" begin="-0.88s"></animate>
<animate attributeName="fill" values="#3d7d9a;#3d7d9a;#45a6d2;#3d7d9a;#3d7d9a" repeatCount="indefinite" times="0;0.1;0.2;0.3;1" dur="2.2s" begin="-0.88s"></animate>
</circle><circle cx="29.775" cy="35.305" fill="undefined" r="4.00727">
<animate attributeName="r" values="3.5999999999999996;3.5999999999999996;6;3.5999999999999996;3.5999999999999996" times="0;0.1;0.2;0.3;1" dur="2.2s" repeatCount="indefinite" begin="-0.66s"></animate>
<animate attributeName="fill" values="#3d7d9a;#3d7d9a;#45a6d2;#3d7d9a;#3d7d9a" repeatCount="indefinite" times="0;0.1;0.2;0.3;1" dur="2.2s" begin="-0.66s"></animate>
</circle><circle cx="42.275" cy="26.224" fill="undefined" r="3.6">
<animate attributeName="r" values="3.5999999999999996;3.5999999999999996;6;3.5999999999999996;3.5999999999999996" times="0;0.1;0.2;0.3;1" dur="2.2s" repeatCount="indefinite" begin="-0.44s"></animate>
<animate attributeName="fill" values="#3d7d9a;#3d7d9a;#45a6d2;#3d7d9a;#3d7d9a" repeatCount="indefinite" times="0;0.1;0.2;0.3;1" dur="2.2s" begin="-0.44s"></animate>
</circle><circle cx="57.725" cy="26.224" fill="undefined" r="3.6">
<animate attributeName="r" values="3.5999999999999996;3.5999999999999996;6;3.5999999999999996;3.5999999999999996" times="0;0.1;0.2;0.3;1" dur="2.2s" repeatCount="indefinite" begin="-0.22s"></animate>
<animate attributeName="fill" values="#3d7d9a;#3d7d9a;#45a6d2;#3d7d9a;#3d7d9a" repeatCount="indefinite" times="0;0.1;0.2;0.3;1" dur="2.2s" begin="-0.22s"></animate>
</circle><circle cx="70.225" cy="35.305" fill="undefined" r="3.6">
<animate attributeName="r" values="3.5999999999999996;3.5999999999999996;6;3.5999999999999996;3.5999999999999996" times="0;0.1;0.2;0.3;1" dur="2.2s" repeatCount="indefinite" begin="0s"></animate>
<animate attributeName="fill" values="#3d7d9a;#3d7d9a;#45a6d2;#3d7d9a;#3d7d9a" repeatCount="indefinite" times="0;0.1;0.2;0.3;1" dur="2.2s" begin="0s"></animate>
</circle></svg>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment