Initial commit.
commit
9e324a1f94
|
@ -0,0 +1,11 @@
|
|||
###
|
||||
|
||||
.git*
|
||||
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
|
||||
docker-compose.yml
|
||||
|
||||
*.md
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
extends: airbnb
|
||||
|
||||
parser: babel-eslint
|
||||
|
||||
plugins:
|
||||
- babel
|
||||
- json
|
||||
|
||||
env:
|
||||
browser: true
|
||||
node: true
|
||||
es6: true
|
||||
|
||||
rules:
|
||||
no-underscore-dangle: 'off'
|
||||
no-plusplus:
|
||||
- error
|
||||
- allowForLoopAfterthoughts: true
|
||||
react/no-array-index-key: 0
|
|
@ -0,0 +1,28 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directory
|
||||
# Deployed apps should consider commenting this line out:
|
||||
# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git
|
||||
node_modules
|
||||
|
||||
# Webpack output
|
||||
/dist
|
|
@ -0,0 +1,16 @@
|
|||
sudo: false
|
||||
|
||||
language: node_js
|
||||
node_js:
|
||||
- 6
|
||||
|
||||
before_install:
|
||||
- npm install codecov.io coveralls
|
||||
|
||||
after_success:
|
||||
- cat ./coverage/lcov.info | ./node_modules/codecov.io/bin/codecov.io.js
|
||||
- cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
|
@ -0,0 +1,4 @@
|
|||
FROM icedream/caddy
|
||||
|
||||
WORKDIR /data
|
||||
COPY ./dist/ /data
|
|
@ -0,0 +1,29 @@
|
|||
node("docker && linux && amd64") {
|
||||
checkout scm
|
||||
|
||||
docker.image("node:8.2.1").inside {
|
||||
// Install dependencies
|
||||
sh "npm install"
|
||||
|
||||
// Build website with npm
|
||||
sh "npm run build"
|
||||
archive "dist/**"
|
||||
}
|
||||
|
||||
// Build docker image to be deployed
|
||||
def image = docker.build("docker.dreamnetwork.oss:5000/icedream/carl-kittelberger-website:${env.BRANCH_NAME ?: "latest"}", "-f Dockerfile.dist .")
|
||||
|
||||
// @NOTE - https://issues.jenkins-ci.org/browse/JENKINS-42152?focusedCommentId=307976&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-307976
|
||||
image.push()
|
||||
if (env.BRANCH_NAME) {
|
||||
switch(env.BRANCH_NAME) {
|
||||
case "master":
|
||||
image.push("latest")
|
||||
break
|
||||
default:
|
||||
image.push()
|
||||
break
|
||||
}
|
||||
}
|
||||
image.push("${sh(script: "git describe --tags --always", returnStdout: true).trim()}")
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
# VIzon countdown website
|
||||
|
||||
Source code for vizon-countdown.icedream.pw.
|
|
@ -0,0 +1,37 @@
|
|||
module.exports = {
|
||||
type: 'react-app',
|
||||
|
||||
babel: {
|
||||
loose: false,
|
||||
presets: [
|
||||
'babel-preset-env',
|
||||
],
|
||||
plugins: [
|
||||
'babel-plugin-transform-class-properties',
|
||||
],
|
||||
},
|
||||
|
||||
webpack: {
|
||||
autoprefixer: '> 1%, last 2 versions, Firefox ESR, ios >= 8',
|
||||
|
||||
extra: {
|
||||
resolve: {
|
||||
extensions: [
|
||||
'.jsx',
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
publicPath: '',
|
||||
|
||||
rules: {
|
||||
babel: {
|
||||
test: /\.jsx?/,
|
||||
},
|
||||
'sass-css': {
|
||||
modules: true,
|
||||
localIdentName: '[name]__[local]__[hash:base64:5]',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"name": "vizon-countdown-website",
|
||||
"version": "0.1.0",
|
||||
"description": "Website for a countdown to the next draw on VIzon",
|
||||
"private": true,
|
||||
"main": "src/index.jsx",
|
||||
"scripts": {
|
||||
"build": "nwb build-react-app ./src",
|
||||
"clean": "nwb clean-app",
|
||||
"start": "nwb serve-react-app ./src",
|
||||
"test": "nwb test-react",
|
||||
"test:coverage": "nwb test-react --coverage",
|
||||
"test:watch": "nwb test-react --server",
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "ssh://git@git.icedream.tech:2222/icedream/vizon-countdown-website.git"
|
||||
},
|
||||
"keywords": [
|
||||
"website",
|
||||
"vizon",
|
||||
"rizon",
|
||||
"draw",
|
||||
"countdown"
|
||||
],
|
||||
"author": "Carl Kittelberger <icedream@icedream.pw>",
|
||||
"license": "UNLICENSED",
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^7.2.3",
|
||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||
"babel-preset-env": "^1.6.0",
|
||||
"eslint": "^4.4.1",
|
||||
"eslint-config-airbnb": "^15.1.0",
|
||||
"eslint-plugin-babel": "^4.1.2",
|
||||
"eslint-plugin-import": "^2.7.0",
|
||||
"eslint-plugin-json": "^1.2.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.0.2",
|
||||
"eslint-plugin-react": "^7.2.1",
|
||||
"file-loader": "^0.11.2",
|
||||
"nwb": "^0.18.10",
|
||||
"nwb-sass": "^0.8.1",
|
||||
"svg-inline-loader": "^0.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"moment": "^2.18.1",
|
||||
"normalize-scss": "^7.0.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"react": "^15.6.1",
|
||||
"react-dom": "^15.6.1",
|
||||
"react-helmet": "^5.1.3",
|
||||
"react-router": "^4.1.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import moment from 'moment';
|
||||
import Countdown from './Countdown';
|
||||
import Header from './Header';
|
||||
import ProgressCircle from './ProgressCircle';
|
||||
import getUpcomingDate from './getUpcomingDate';
|
||||
|
||||
import style from './App.sass';
|
||||
|
||||
class App extends React.Component {
|
||||
static propTypes = {
|
||||
getNow: PropTypes.func,
|
||||
weekdays: PropTypes.arrayOf(PropTypes.string),
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
getNow: () => moment(),
|
||||
weekdays: [
|
||||
'tuesday',
|
||||
'thursday',
|
||||
'saturday',
|
||||
],
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.interval = setInterval(this.updateUpcomingDate.bind(this), 1000);
|
||||
this.updateUpcomingDate();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
|
||||
calculateUpcomingDate() {
|
||||
const { getNow, weekdays } = this.props;
|
||||
const now = getNow();
|
||||
return moment.min(
|
||||
...weekdays.map(weekday => getUpcomingDate(now, weekday)),
|
||||
);
|
||||
}
|
||||
|
||||
updateUpcomingDate() {
|
||||
this.setState({ nextUpcomingDate: this.calculateUpcomingDate() });
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.state) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { nextUpcomingDate } = this.state;
|
||||
|
||||
return (
|
||||
<div className={style.app}>
|
||||
<Header>
|
||||
VIzon countdown
|
||||
</Header>
|
||||
|
||||
<div className={style.content}>
|
||||
<div className={style.contentContainer}>
|
||||
<p>
|
||||
The next VIzon draw is on {nextUpcomingDate.format('dddd')}, {nextUpcomingDate.format('L LT')}.
|
||||
</p>
|
||||
<Countdown date={nextUpcomingDate} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
|
@ -0,0 +1,19 @@
|
|||
.app
|
||||
background-color: #f8f8f8
|
||||
min-height: 100vh
|
||||
font-size: 24px
|
||||
|
||||
display: flex
|
||||
flex-direction: column
|
||||
justify-content: stretch
|
||||
align-items: center
|
||||
|
||||
.content
|
||||
color: #222
|
||||
line-height: 1.5
|
||||
width: 100%
|
||||
max-width: 1024px
|
||||
padding: 1em 0
|
||||
box-sizing: content-box
|
||||
flex-grow: 1
|
||||
text-align: center
|
|
@ -0,0 +1,97 @@
|
|||
import React from 'react';
|
||||
import moment from 'moment';
|
||||
import PropTypes from 'prop-types';
|
||||
import DigitBlock from './DigitBlock';
|
||||
import ProgressCircle from './ProgressCircle';
|
||||
|
||||
import style from './Countdown.sass';
|
||||
|
||||
export default class Countdown extends React.Component {
|
||||
static propTypes = {
|
||||
date: PropTypes.object.isRequired,
|
||||
locale: PropTypes.string,
|
||||
minimumIntegerDigits: PropTypes.number,
|
||||
useGrouping: PropTypes.bool,
|
||||
getNow: PropTypes.func,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
locale: undefined,
|
||||
minimumIntegerDigits: 2,
|
||||
useGrouping: false,
|
||||
getNow: () => moment(),
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.tick();
|
||||
this.interval = setInterval(this.tick.bind(this), 1000);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
|
||||
calculateDiff() {
|
||||
const { getNow, date } = this.props;
|
||||
return date.diff(getNow());
|
||||
}
|
||||
|
||||
tick() {
|
||||
this.setState({ duration: this.calculateDiff() });
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.state) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { duration } = this.state;
|
||||
|
||||
const durationMoment = moment.duration(duration);
|
||||
|
||||
const days = durationMoment.days();
|
||||
const hours = durationMoment.hours();
|
||||
const minutes = durationMoment.minutes();
|
||||
const seconds = durationMoment.seconds();
|
||||
|
||||
const size = 160; // @HACK
|
||||
|
||||
const { locale, minimumIntegerDigits, useGrouping } = this.props;
|
||||
return (
|
||||
<div className={style.countdown}>
|
||||
<ProgressCircle size={size} max={3} progress={days} stroke="rgb(60, 90, 128)">
|
||||
<DigitBlock suffix="d">
|
||||
{days.toLocaleString(locale, {
|
||||
minimumIntegerDigits,
|
||||
useGrouping,
|
||||
})}
|
||||
</DigitBlock>
|
||||
</ProgressCircle>
|
||||
<ProgressCircle size={size} max={24} progress={hours} stroke="rgb(60, 144, 60)">
|
||||
<DigitBlock suffix="h">
|
||||
{hours.toLocaleString(locale, {
|
||||
minimumIntegerDigits,
|
||||
useGrouping,
|
||||
})}
|
||||
</DigitBlock>
|
||||
</ProgressCircle>
|
||||
<ProgressCircle size={size} max={60} progress={minutes} stroke="rgb(160, 154, 40)">
|
||||
<DigitBlock suffix="m">
|
||||
{minutes.toLocaleString(locale, {
|
||||
minimumIntegerDigits,
|
||||
useGrouping,
|
||||
})}
|
||||
</DigitBlock>
|
||||
</ProgressCircle>
|
||||
<ProgressCircle size={size} max={60} progress={seconds} stroke="rgb(155, 50, 70)">
|
||||
<DigitBlock suffix="s">
|
||||
{durationMoment.seconds().toLocaleString(locale, {
|
||||
minimumIntegerDigits,
|
||||
useGrouping,
|
||||
})}
|
||||
</DigitBlock>
|
||||
</ProgressCircle>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
.countdown
|
||||
display: flex
|
||||
flex-direction: row
|
||||
flex-wrap: wrap
|
||||
font-family: monospace
|
||||
justify-content: space-around
|
||||
|
||||
&> *:not(:first-child)
|
||||
margin-left: 0.25em
|
|
@ -0,0 +1,22 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import style from './DigitBlock.sass';
|
||||
|
||||
const DigitBlock = ({ children, suffix }) => (
|
||||
<div className={style.digitBlock}>
|
||||
<span>{children}</span>
|
||||
<span className={style.digitBlockSuffix}>{suffix}</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
DigitBlock.defaultProps = {
|
||||
suffix: null,
|
||||
};
|
||||
|
||||
DigitBlock.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
suffix: PropTypes.string,
|
||||
};
|
||||
|
||||
export default DigitBlock;
|
|
@ -0,0 +1,10 @@
|
|||
.digitBlock
|
||||
font-size: 2em
|
||||
display: inline-block
|
||||
white-space: pre
|
||||
|
||||
&Suffix
|
||||
font-size: 0.5em
|
||||
text-transform: uppercase
|
||||
font-weight: bold
|
||||
color: #888
|
|
@ -0,0 +1,23 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import style from './Header.sass';
|
||||
|
||||
export default function Header({ className, children }) {
|
||||
return (
|
||||
<header className={[style.header, className].join(' ')}>
|
||||
{children}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
Header.propTypes = {
|
||||
children: PropTypes.node,
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
|
||||
Header.defaultProps = {
|
||||
children: null,
|
||||
className: null,
|
||||
};
|
|
@ -0,0 +1,10 @@
|
|||
.header
|
||||
background-color: #222
|
||||
color: #f8f8f8
|
||||
font-weight: bold
|
||||
font-size: 1.5em
|
||||
text-align: center
|
||||
box-shadow: 0px 4px 4vh 4px rgba(34,34,34,0.9)
|
||||
z-index: 2
|
||||
padding: 12px 0
|
||||
width: 100%
|
|
@ -0,0 +1,81 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import style from './ProgressCircle.sass';
|
||||
|
||||
const ProgressCircle = ({
|
||||
children,
|
||||
min,
|
||||
max,
|
||||
progress,
|
||||
size,
|
||||
strokeWidth,
|
||||
backStroke,
|
||||
stroke,
|
||||
}) => {
|
||||
const width = size;
|
||||
const height = size;
|
||||
|
||||
const viewBox = [0, 0, width, height].join(' ');
|
||||
|
||||
const cx = width / 2;
|
||||
const cy = height / 2;
|
||||
|
||||
const r = (size / 2) - (strokeWidth / 2);
|
||||
|
||||
const strokeLength = 2 * Math.PI * r;
|
||||
|
||||
const finalProgress = (progress - min) / (max - min);
|
||||
|
||||
const strokeDasharray = strokeLength;
|
||||
const strokeDashoffset = strokeLength * (1 - finalProgress);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={style.progressCircleContainer}
|
||||
style={{
|
||||
width: `${width}px`,
|
||||
height: `${height}px`,
|
||||
}}
|
||||
>
|
||||
<svg className={style.progressCircle} {...{ width, height, viewBox }}>
|
||||
<circle
|
||||
fill="none"
|
||||
stroke={backStroke}
|
||||
{...{ cx, cy, r, strokeWidth }}
|
||||
/>
|
||||
<circle
|
||||
className={style.progressValue}
|
||||
fill="none"
|
||||
{...{ cx, cy, r, stroke, strokeWidth, strokeDashoffset, strokeDasharray }}
|
||||
/>
|
||||
</svg>
|
||||
<span className={style.progressCircleLabel}>
|
||||
{children}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ProgressCircle.propTypes = {
|
||||
children: PropTypes.node,
|
||||
size: PropTypes.number.isRequired,
|
||||
progress: PropTypes.number,
|
||||
strokeWidth: PropTypes.number,
|
||||
min: PropTypes.number,
|
||||
max: PropTypes.number,
|
||||
backStroke: PropTypes.string,
|
||||
stroke: PropTypes.string,
|
||||
};
|
||||
|
||||
ProgressCircle.defaultProps = {
|
||||
stroke: '#444',
|
||||
backStroke: '#eee',
|
||||
strokeWidth: 10,
|
||||
progress: 0.5,
|
||||
min: 0,
|
||||
max: 1,
|
||||
children: null,
|
||||
};
|
||||
|
||||
export default ProgressCircle;
|
|
@ -0,0 +1,18 @@
|
|||
.progressCircle
|
||||
transform: rotate(-90deg)
|
||||
position: absolute
|
||||
left: 0
|
||||
top: 0
|
||||
|
||||
.progressValue
|
||||
transition: stroke-dashoffset 1s linear
|
||||
|
||||
.progressCircleContainer
|
||||
position: relative
|
||||
display: inline-flex
|
||||
flex-direction: column
|
||||
justify-content: space-around
|
||||
|
||||
.progressCircleLabel
|
||||
flex-basis: auto
|
||||
text-align: center
|
|
@ -0,0 +1,16 @@
|
|||
import moment from 'moment';
|
||||
|
||||
export default function getUpcomingDate(now, weekday: String) {
|
||||
let wanted = moment()
|
||||
.isoWeekday(weekday)
|
||||
.second(0)
|
||||
.minute(0)
|
||||
.hour(0);
|
||||
|
||||
if (wanted.isBefore(now)) {
|
||||
// we want the date from the upcoming week
|
||||
wanted = wanted.add(1, 'weeks');
|
||||
}
|
||||
|
||||
return wanted;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<title>my-app</title>
|
||||
<meta name="description" content="">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,7 @@
|
|||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
|
||||
import './index.sass';
|
||||
import App from './App';
|
||||
|
||||
render(<App />, document.querySelector('#app'));
|
|
@ -0,0 +1,6 @@
|
|||
@import "~normalize-scss/sass/normalize"
|
||||
|
||||
body
|
||||
font-family: sans-serif
|
||||
margin: 0
|
||||
padding: 0
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_2_1_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 841.9 595.3" enable-background="new 0 0 841.9 595.3" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#61DAFB" d="M666.3,296.5c0-32.5-40.7-63.3-103.1-82.4c14.4-63.6,8-114.2-20.2-130.4c-6.5-3.8-14.1-5.6-22.4-5.6v22.3
|
||||
c4.6,0,8.3,0.9,11.4,2.6c13.6,7.8,19.5,37.5,14.9,75.7c-1.1,9.4-2.9,19.3-5.1,29.4c-19.6-4.8-41-8.5-63.5-10.9
|
||||
c-13.5-18.5-27.5-35.3-41.6-50c32.6-30.3,63.2-46.9,84-46.9l0-22.3c0,0,0,0,0,0c-27.5,0-63.5,19.6-99.9,53.6
|
||||
c-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7,0,51.4,16.5,84,46.6c-14,14.7-28,31.4-41.3,49.9c-22.6,2.4-44,6.1-63.6,11
|
||||
c-2.3-10-4-19.7-5.2-29c-4.7-38.2,1.1-67.9,14.6-75.8c3-1.8,6.9-2.6,11.5-2.6l0-22.3c0,0,0,0,0,0c-8.4,0-16,1.8-22.6,5.6
|
||||
c-28.1,16.2-34.4,66.7-19.9,130.1c-62.2,19.2-102.7,49.9-102.7,82.3c0,32.5,40.7,63.3,103.1,82.4c-14.4,63.6-8,114.2,20.2,130.4
|
||||
c6.5,3.8,14.1,5.6,22.5,5.6c27.5,0,63.5-19.6,99.9-53.6c36.4,33.8,72.4,53.2,99.9,53.2c8.4,0,16-1.8,22.6-5.6
|
||||
c28.1-16.2,34.4-66.7,19.9-130.1C625.8,359.7,666.3,328.9,666.3,296.5z M536.1,229.8c-3.7,12.9-8.3,26.2-13.5,39.5
|
||||
c-4.1-8-8.4-16-13.1-24c-4.6-8-9.5-15.8-14.4-23.4C509.3,224,523,226.6,536.1,229.8z M490.3,336.3c-7.8,13.5-15.8,26.3-24.1,38.2
|
||||
c-14.9,1.3-30,2-45.2,2c-15.1,0-30.2-0.7-45-1.9c-8.3-11.9-16.4-24.6-24.2-38c-7.6-13.1-14.5-26.4-20.8-39.8
|
||||
c6.2-13.4,13.2-26.8,20.7-39.9c7.8-13.5,15.8-26.3,24.1-38.2c14.9-1.3,30-2,45.2-2c15.1,0,30.2,0.7,45,1.9
|
||||
c8.3,11.9,16.4,24.6,24.2,38c7.6,13.1,14.5,26.4,20.8,39.8C504.7,309.8,497.8,323.2,490.3,336.3z M522.6,323.3
|
||||
c5.4,13.4,10,26.8,13.8,39.8c-13.1,3.2-26.9,5.9-41.2,8c4.9-7.7,9.8-15.6,14.4-23.7C514.2,339.4,518.5,331.3,522.6,323.3z
|
||||
M421.2,430c-9.3-9.6-18.6-20.3-27.8-32c9,0.4,18.2,0.7,27.5,0.7c9.4,0,18.7-0.2,27.8-0.7C439.7,409.7,430.4,420.4,421.2,430z
|
||||
M346.8,371.1c-14.2-2.1-27.9-4.7-41-7.9c3.7-12.9,8.3-26.2,13.5-39.5c4.1,8,8.4,16,13.1,24C337.1,355.7,341.9,363.5,346.8,371.1z
|
||||
M420.7,163c9.3,9.6,18.6,20.3,27.8,32c-9-0.4-18.2-0.7-27.5-0.7c-9.4,0-18.7,0.2-27.8,0.7C402.2,183.3,411.5,172.6,420.7,163z
|
||||
M346.7,221.9c-4.9,7.7-9.8,15.6-14.4,23.7c-4.6,8-8.9,16-13,24c-5.4-13.4-10-26.8-13.8-39.8C318.6,226.7,332.4,224,346.7,221.9z
|
||||
M256.2,347.1c-35.4-15.1-58.3-34.9-58.3-50.6c0-15.7,22.9-35.6,58.3-50.6c8.6-3.7,18-7,27.7-10.1c5.7,19.6,13.2,40,22.5,60.9
|
||||
c-9.2,20.8-16.6,41.1-22.2,60.6C274.3,354.2,264.9,350.8,256.2,347.1z M310,490c-13.6-7.8-19.5-37.5-14.9-75.7
|
||||
c1.1-9.4,2.9-19.3,5.1-29.4c19.6,4.8,41,8.5,63.5,10.9c13.5,18.5,27.5,35.3,41.6,50c-32.6,30.3-63.2,46.9-84,46.9
|
||||
C316.8,492.6,313,491.7,310,490z M547.2,413.8c4.7,38.2-1.1,67.9-14.6,75.8c-3,1.8-6.9,2.6-11.5,2.6c-20.7,0-51.4-16.5-84-46.6
|
||||
c14-14.7,28-31.4,41.3-49.9c22.6-2.4,44-6.1,63.6-11C544.3,394.8,546.1,404.5,547.2,413.8z M585.7,347.1c-8.6,3.7-18,7-27.7,10.1
|
||||
c-5.7-19.6-13.2-40-22.5-60.9c9.2-20.8,16.6-41.1,22.2-60.6c9.9,3.1,19.3,6.5,28.1,10.2c35.4,15.1,58.3,34.9,58.3,50.6
|
||||
C644,312.2,621.1,332.1,585.7,347.1z"/>
|
||||
<polygon fill="#61DAFB" points="320.8,78.4 320.8,78.4 320.8,78.4 "/>
|
||||
<circle fill="#61DAFB" cx="420.9" cy="296.5" r="45.7"/>
|
||||
<polygon fill="#61DAFB" points="520.5,78.1 520.5,78.1 520.5,78.1 "/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
Loading…
Reference in New Issue