feat: screenshot

This commit is contained in:
tristan 2019-09-12 18:17:46 +08:00
parent 18bf815eed
commit 8d2e950e40
9 changed files with 305 additions and 5 deletions

View File

@ -28,6 +28,7 @@
"homepage": "https://works.yangerxiao.com/chinese-colors/",
"dependencies": {
"color-convert": "^2.0.1",
"html2canvas": "^1.0.0-rc.3",
"pinyin": "^2.9.0",
"react": "^16.9.0",
"react-copy-to-clipboard": "^5.0.1",

View File

@ -4,12 +4,14 @@ import pinyin from 'pinyin';
import convert from 'color-convert';
import ColorTitle from './components/ColorTitle';
import Color from './components/Color';
import Preview from './components/Preview';
import ColorParam from './components/ColorParam';
import InfoModal from './components/InfoModal';
import IconInfo from './components/IconInfo';
import IconScreenshoot from './components/IconScreenshoot';
import Header from './components/Header';
import ColorSet from './components/ColorSet';
import { useModal, useColor } from './hooks';
import { useModal, useColor, usePreview } from './hooks';
import colors from './assets/colors.json';
colors.push({
@ -40,13 +42,14 @@ const Wrapper = styled.section`
display: flex;
padding: 1rem 0.5rem;
justify-content: space-evenly;
transition: all 0.9s;
.params {
margin-right: 1rem;
}
aside {
position: fixed;
bottom: 2rem;
right: 5rem;
right: 3rem;
padding: 0 1rem;
z-index: 999;
}
@ -66,6 +69,7 @@ const Wrapper = styled.section`
console.log('colors', colors);
const App = () => {
const { visible: modalVisible, showModal, closeModal } = useModal();
const { preview, showPreview, closePreview } = usePreview();
const { sets, currSet, currColor, updateCurrColor, updateCurrSet } = useColor({
sets: Colors.map(set => {
const newSet = { ...set };
@ -103,6 +107,15 @@ const App = () => {
<ColorTitle {...currColor}></ColorTitle>
<Header />
</Wrapper>
{preview && (
<Preview
closePreview={closePreview}
name={currColor.name}
pinyin={currColor.pinyin}
color={currColor.hex}
/>
)}
<IconScreenshoot showPreview={showPreview} />
{!modalVisible && <IconInfo showInfoModal={showModal} />}
{modalVisible && <InfoModal bgColor={currColor.hex} closeModal={closeModal} />}
</>

View File

@ -0,0 +1,75 @@
import React from 'react';
import html2canvas from 'html2canvas';
import styled, { keyframes } from 'styled-components';
const Float = keyframes`
0%,40%,80%{
transform:translateX(-50%) translateY(0%);
}
20%,60%,100%{
transform:translateX(-50%) translateY(2%);
}
`;
function saveAs(uri, filename) {
var link = document.createElement('a');
if (typeof link.download === 'string') {
link.href = uri;
link.download = filename;
//Firefox requires the link to be in the body
document.body.appendChild(link);
//simulate click
link.click();
//remove the link when done
document.body.removeChild(link);
} else {
window.open(uri);
}
}
const Wrapper = styled.button`
cursor: pointer;
position: absolute;
bottom: 10vh;
left: 50%;
/* transform: translateX(-50%); */
border: none;
border-radius: 0.3rem;
padding: 0.6rem 0.8rem;
font-size: 1rem;
color: #eee;
background: #1f2f2d;
box-shadow: 0px 5px 9px rgba(0, 0, 0, 0.5);
animation: ${Float} 3s infinite forwards;
`;
const Download = ({ name }) => {
const handleDownloadClick = () => {
// startScreenshoot();
let ele = document.querySelector('#PREVIEW');
ele.classList.add('starting');
ele.style.height = window.innerHeight + 'px';
html2canvas(ele, {
// width: window.screen.availWidth,
// height: window.screen.availHeight,
// width: window.innerWidth,
// height: window.screen.availHeight
// onclone: cloned => {
// cloned.querySelector('aside').remove();
// cloned.querySelector('button').remove();
// return cloned;
// }
}).then(function(canvas) {
console.log(canvas);
saveAs(canvas.toDataURL(), `${name}-${new Date().getTime()}.png`);
ele.classList.remove('starting');
});
};
return <Wrapper onClick={handleDownloadClick}>保存</Wrapper>;
};
export default Download;

View File

@ -0,0 +1,48 @@
import React from 'react';
import styled from 'styled-components';
const Wrapper = styled.aside`
position: absolute;
top: 1rem;
right: 1rem;
cursor: pointer;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
.icon {
width: 1.8rem;
height: 1.8rem;
}
`;
const IconClose = ({ closePreview }) => {
return (
<Wrapper onClick={closePreview}>
<svg
t="1568280236953"
className="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="5848"
width="32"
height="32"
>
<path
d="M511.488511 972.851149c254.238434 0 460.33966-206.101227 460.339661-460.33966S765.726945 52.171828 511.488511 52.171828 51.148851 258.273055 51.148851 512.511489s206.101227 460.33966 460.33966 460.33966z m0 51.148851C229.00159 1024 0 794.99841 0 512.511489S229.00159 1.022977 511.488511 1.022977s511.488511 229.00159 511.488512 511.488512-229.00159 511.488511-511.488512 511.488511z"
p-id="5849"
fill="#ffffff"
></path>
<path
d="M513.306342 478.160943l-162.755645-162.754621c-9.986302-9.987325-26.180028-9.987325-36.167352 0-9.987325 9.987325-9.987325 26.181051 0 36.168375l162.755644 162.754622-162.755644 162.754621c-9.987325 9.987325-9.987325 26.180028 0 36.167353 9.987325 9.987325 26.181051 9.987325 36.168375 0l162.754622-162.754622 162.754621 162.755645c9.987325 9.986302 26.180028 9.986302 36.167353 0 9.987325-9.988348 9.987325-26.181051 0-36.168376l-162.754622-162.755644 162.755645-162.753599c9.986302-9.987325 9.986302-26.181051 0-36.168375-9.988348-9.987325-26.181051-9.987325-36.168376 0l-162.755644 162.755644z"
p-id="5850"
fill="#ffffff"
></path>
</svg>
</Wrapper>
);
};
export default IconClose;

View File

@ -10,7 +10,7 @@ const Wrapper = styled.aside`
display: flex;
justify-content: center;
align-items: center;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.62);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
.icon {
width: 1.8rem;
height: 1.8rem;

View File

@ -0,0 +1,47 @@
import React from 'react';
import styled from 'styled-components';
const Wrapper = styled.aside`
position: fixed;
top: 4rem;
right: 1rem;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
.icon {
width: 1.8rem;
height: 1.8rem;
}
`;
const IconInfo = ({ showPreview }) => {
return (
<Wrapper onClick={showPreview}>
<svg
t="1568267241706"
className="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1970"
width="48"
height="48"
>
<path
d="M853.333333 0h-682.666666C75.093333 0 0 75.093333 0 170.666667v682.666666C0 948.906667 75.093333 1024 170.666667 1024h682.666666c95.573333 0 170.666667-75.093333 170.666667-170.666667v-682.666666C1024 75.093333 948.906667 0 853.333333 0zM955.733333 853.333333c0 54.613333-47.786667 102.4-102.4 102.4h-682.666666c-54.613333 0-102.4-47.786667-102.4-102.4v-682.666666C68.266667 116.053333 116.053333 68.266667 170.666667 68.266667h682.666666c54.613333 0 102.4 47.786667 102.4 102.4v682.666666z"
p-id="1971"
fill="#ffffff"
></path>
<path
d="M853.333333 136.533333h-273.066666c-20.48 0-34.133333 13.653333-34.133334 34.133334s13.653333 34.133333 34.133334 34.133333H819.2v238.933333c0 20.48 13.653333 34.133333 34.133333 34.133334s34.133333-13.653333 34.133334-34.133334v-273.066666c0-20.48-13.653333-34.133333-34.133334-34.133334zM443.733333 819.2H204.8V580.266667c0-20.48-13.653333-34.133333-34.133333-34.133334s-34.133333 13.653333-34.133334 34.133334v273.066666c0 20.48 13.653333 34.133333 34.133334 34.133334h273.066666c20.48 0 34.133333-13.653333 34.133334-34.133334s-13.653333-34.133333-34.133334-34.133333z"
p-id="1972"
fill="#eee"
></path>
</svg>
</Wrapper>
);
};
export default IconInfo;

64
src/components/Preview.js Normal file
View File

@ -0,0 +1,64 @@
import React from 'react';
import styled from 'styled-components';
import Download from './DownloadBtn';
import IconClose from './IconClose';
import BodyBg from '../assets/img/bg.texture.png';
const Wrapper = styled.section`
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
z-index: 999;
background-color: ${({ bgColor }) => bgColor};
background-image: url(${BodyBg});
width: 100%;
height: 100%;
&.starting {
aside,
button {
display: none;
}
}
hgroup {
position: absolute;
left: 1rem;
top: 1rem;
display: flex;
align-items: flex-end;
> h1 {
font-family: 'TChinese', 'SimSun', 'FangSong', 'STSong', 'STZhongsong', 'LiSu', 'KaiTi',
'Microsoft YaHei';
font-size: 6rem;
width: 6rem;
opacity: 0.6;
border-top: 0.6rem solid ${({ bgColor }) => bgColor};
}
> h2 {
font-size: 2.8rem;
text-transform: capitalize;
transform-origin: left;
transform: rotate(90deg);
opacity: 0.3;
margin-bottom: 2.6rem;
margin-left: 1rem;
font-weight: bold;
}
}
`;
const Preview = ({ name, pinyin, color, closePreview }) => {
return (
<Wrapper id="PREVIEW" bgColor={color}>
<IconClose closePreview={closePreview} />
<hgroup>
<h1>{name}</h1>
<h2>{pinyin}</h2>
</hgroup>
<Download name={name} />
</Wrapper>
);
};
export default Preview;

View File

@ -1,4 +1,37 @@
import { useState, useReducer } from 'react';
import { useState, useReducer, useEffect } from 'react';
const useMobile = (width = 411) => {
const [isMobile, setIsMobile] = useState(window.innerWidth <= width);
console.log('mmmmmm');
useEffect(() => {
const checkMobile = () => {
console.log('rrrr');
if (window.innerWidth <= width) {
setIsMobile(true);
} else {
setIsMobile(false);
}
};
window.addEventListener('resize', checkMobile);
return () => {
window.removeEventListener('resize', checkMobile, true);
};
}, [width]);
return { isMobile };
};
const usePreview = () => {
const [preview, setPreview] = useState(false);
const closePreview = () => {
setPreview(false);
};
const showPreview = () => {
setPreview(true);
};
return { preview, closePreview, showPreview };
};
const useModal = () => {
const [visible, setVisible] = useState(false);
@ -47,5 +80,5 @@ const useColor = initialValue => {
return { ...state, updateCurrColor, updateCurrSet };
};
export { useModal, useColor };
export { useModal, usePreview, useColor, useMobile };
export default useColor;

View File

@ -1620,6 +1620,11 @@ balanced-match@^1.0.0:
resolved "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
base64-arraybuffer@^0.2.0:
version "0.2.0"
resolved "https://registry.npm.taobao.org/base64-arraybuffer/download/base64-arraybuffer-0.2.0.tgz#4b944fac0191aa5907afe2d8c999ccc57ce80f45"
integrity sha1-S5RPrAGRqlkHr+LYyZnMxXzoD0U=
base64-js@^1.0.2:
version "1.3.1"
resolved "https://registry.npm.taobao.org/base64-js/download/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
@ -2438,6 +2443,13 @@ css-color-keywords@^1.0.0:
resolved "https://registry.npm.taobao.org/css-color-keywords/download/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
integrity sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=
css-line-break@1.1.1:
version "1.1.1"
resolved "https://registry.npm.taobao.org/css-line-break/download/css-line-break-1.1.1.tgz#d5e9bdd297840099eb0503c7310fd34927a026ef"
integrity sha1-1em90peEAJnrBQPHMQ/TSSegJu8=
dependencies:
base64-arraybuffer "^0.2.0"
css-loader@^3.2.0:
version "3.2.0"
resolved "https://registry.npm.taobao.org/css-loader/download/css-loader-3.2.0.tgz#bb570d89c194f763627fcf1f80059c6832d009b2"
@ -4027,6 +4039,13 @@ html-webpack-plugin@^3.2.0:
toposort "^1.0.0"
util.promisify "1.0.0"
html2canvas@^1.0.0-rc.3:
version "1.0.0-rc.3"
resolved "https://registry.npm.taobao.org/html2canvas/download/html2canvas-1.0.0-rc.3.tgz#1de88b073f6bcaa6954ca1edfb46da13b258b038"
integrity sha1-HeiLBz9ryqaVTKHt+0baE7JYsDg=
dependencies:
css-line-break "1.1.1"
htmlparser2@^3.3.0:
version "3.10.1"
resolved "https://registry.npm.taobao.org/htmlparser2/download/htmlparser2-3.10.1.tgz?cache=0&sync_timestamp=1564773692945&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhtmlparser2%2Fdownload%2Fhtmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"