mirror of
https://github.com/zerosoul/chinese-colors.git
synced 2024-11-27 04:40:12 +08:00
feat: screenshot
This commit is contained in:
parent
18bf815eed
commit
8d2e950e40
@ -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",
|
||||
|
17
src/App.js
17
src/App.js
@ -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} />}
|
||||
</>
|
||||
|
75
src/components/DownloadBtn.js
Normal file
75
src/components/DownloadBtn.js
Normal 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;
|
48
src/components/IconClose.js
Normal file
48
src/components/IconClose.js
Normal 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;
|
@ -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;
|
||||
|
47
src/components/IconScreenshoot.js
Normal file
47
src/components/IconScreenshoot.js
Normal 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
64
src/components/Preview.js
Normal 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;
|
37
src/hooks.js
37
src/hooks.js
@ -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;
|
||||
|
19
yarn.lock
19
yarn.lock
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user