feat: 上传文章
36
.dumi/global.less
Normal file
@ -0,0 +1,36 @@
|
||||
#root .dumi-default-doc-layout .dumi-default-features-item {
|
||||
text-align: center;
|
||||
}
|
||||
#root .dumi-default-doc-layout > main {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
#root .dumi-default-sidebar {
|
||||
overflow-y: hidden;
|
||||
&:hover {
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
#root .dumi-default-logo {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
#root .dumi-default-logo img {
|
||||
width: 30px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#root .dumi-default-navbar>li {
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#root .dumi-default-search-bar-input {
|
||||
width: 200px;
|
||||
height: 32px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#root .dumi-default-hero-title>span {
|
||||
font-size: 96px;
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
import { defineConfig } from 'dumi';
|
||||
|
||||
export default defineConfig({
|
||||
title: 'Nice Note',
|
||||
themeConfig: {
|
||||
name: 'nicenote',
|
||||
navs: [
|
||||
null,
|
||||
{
|
||||
@ -11,8 +11,8 @@ export default defineConfig({
|
||||
},
|
||||
]
|
||||
},
|
||||
favicons: ['https://jzx-h5.oss-cn-hangzhou.aliyuncs.com/logo.ico'],
|
||||
// logo: 'http://jzx-h5.oss-cn-hangzhou.aliyuncs.com/logo.png',
|
||||
logo: 'https://i.niupic.com/images/2021/06/07/9krN.png',
|
||||
favicons: ['https://i.niupic.com/images/2021/06/07/9krN.png'],
|
||||
outputPath: 'docs-dist',
|
||||
hash: true,
|
||||
history: {
|
||||
|
1
.gitignore
vendored
@ -4,3 +4,4 @@ node_modules
|
||||
.dumi/tmp-production
|
||||
.DS_Store
|
||||
.umi
|
||||
/docs-dist
|
||||
|
3
.npmrc
Normal file
@ -0,0 +1,3 @@
|
||||
registry="https://registry.npmmirror.com"
|
||||
strict-peer-dependencies=false
|
||||
ignore-workspace-root-check=true
|
@ -1,53 +0,0 @@
|
||||
// @ts-nocheck
|
||||
|
||||
if (window.g_initWebpackHotDevClient) {
|
||||
function tryApplyUpdates(onHotUpdateSuccess?: Function) {
|
||||
// @ts-ignore
|
||||
if (!module.hot) {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
function isUpdateAvailable() {
|
||||
// @ts-ignore
|
||||
return window.g_getMostRecentCompilationHash() !== __webpack_hash__;
|
||||
}
|
||||
|
||||
// TODO: is update available?
|
||||
// @ts-ignore
|
||||
if (!isUpdateAvailable() || module.hot.status() !== 'idle') {
|
||||
return;
|
||||
}
|
||||
|
||||
function handleApplyUpdates(err: Error | null, updatedModules: any) {
|
||||
if (err || !updatedModules || window.g_getHadRuntimeError()) {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
onHotUpdateSuccess?.();
|
||||
|
||||
if (isUpdateAvailable()) {
|
||||
// While we were updating, there was a new update! Do it again.
|
||||
tryApplyUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
module.hot.check(true).then(
|
||||
function (updatedModules: any) {
|
||||
handleApplyUpdates(null, updatedModules);
|
||||
},
|
||||
function (err: Error) {
|
||||
handleApplyUpdates(err, null);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
window.g_initWebpackHotDevClient({
|
||||
tryApplyUpdates,
|
||||
});
|
||||
}
|
||||
|
||||
export const __mfsu = 1;
|
||||
|
@ -1,21 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import { createBrowserHistory, History } from '/Users/teddyj/Library/Mobile Documents/com~apple~CloudDocs/Documents/workspace/dev/nicenote/node_modules/_@umijs_runtime@3.5.41@@umijs/runtime';
|
||||
|
||||
let options = {
|
||||
"basename": "/"
|
||||
};
|
||||
if ((<any>window).routerBase) {
|
||||
options.basename = (<any>window).routerBase;
|
||||
}
|
||||
|
||||
// remove initial history because of ssr
|
||||
let history: History = process.env.__IS_SERVER ? null : createBrowserHistory(options);
|
||||
export const createHistory = (hotReload = false) => {
|
||||
if (!hotReload) {
|
||||
history = createBrowserHistory(options);
|
||||
}
|
||||
|
||||
return history;
|
||||
};
|
||||
|
||||
export { history };
|
@ -1,8 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import { Plugin } from '/Users/teddyj/Library/Mobile Documents/com~apple~CloudDocs/Documents/workspace/dev/nicenote/node_modules/_@umijs_runtime@3.5.41@@umijs/runtime';
|
||||
|
||||
const plugin = new Plugin({
|
||||
validKeys: ['modifyClientRenderOpts','patchRoutes','rootContainer','render','onRouteChange','__mfsu',],
|
||||
});
|
||||
|
||||
export { plugin };
|
297
.umi/core/pluginConfig.d.ts
vendored
@ -1,297 +0,0 @@
|
||||
// Created by Umi Plugin
|
||||
|
||||
export interface IConfigFromPlugins {
|
||||
"404"?: boolean
|
||||
routes?: {
|
||||
/**
|
||||
* Any valid URL path
|
||||
*/
|
||||
path?: string
|
||||
/**
|
||||
* A React component to render only when the location matches.
|
||||
*/
|
||||
component?: (string | (() => any))
|
||||
wrappers?: string[]
|
||||
/**
|
||||
* navigate to a new location
|
||||
*/
|
||||
redirect?: string
|
||||
/**
|
||||
* When true, the active class/style will only be applied if the location is matched exactly.
|
||||
*/
|
||||
exact?: boolean
|
||||
routes?: any[]
|
||||
[k: string]: any
|
||||
}[]
|
||||
history?: {
|
||||
type?: ("browser" | "hash" | "memory")
|
||||
options?: {
|
||||
|
||||
}
|
||||
}
|
||||
polyfill?: {
|
||||
imports?: string[]
|
||||
}
|
||||
alias?: {
|
||||
|
||||
}
|
||||
analyze?: {
|
||||
analyzerMode?: ("server" | "static" | "disabled")
|
||||
analyzerHost?: string
|
||||
analyzerPort?: any
|
||||
openAnalyzer?: boolean
|
||||
generateStatsFile?: boolean
|
||||
statsFilename?: string
|
||||
logLevel?: ("info" | "warn" | "error" | "silent")
|
||||
defaultSizes?: ("stat" | "parsed" | "gzip")
|
||||
[k: string]: any
|
||||
}
|
||||
/**
|
||||
* postcss autoprefixer, default flexbox: no-2009
|
||||
*/
|
||||
autoprefixer?: {
|
||||
|
||||
}
|
||||
base?: string
|
||||
chainWebpack?: (() => any)
|
||||
chunks?: string[]
|
||||
/**
|
||||
* more css-loader options see https://webpack.js.org/loaders/css-loader/#options
|
||||
*/
|
||||
cssLoader?: {
|
||||
url?: (boolean | (() => any))
|
||||
import?: (boolean | (() => any))
|
||||
modules?: (boolean | string | {
|
||||
|
||||
})
|
||||
sourceMap?: boolean
|
||||
importLoaders?: number
|
||||
onlyLocals?: boolean
|
||||
esModule?: boolean
|
||||
localsConvention?: ("asIs" | "camelCase" | "camelCaseOnly" | "dashes" | "dashesOnly")
|
||||
}
|
||||
cssModulesTypescriptLoader?: {
|
||||
mode?: ("emit" | "verify")
|
||||
}
|
||||
cssnano?: {
|
||||
|
||||
}
|
||||
copy?: any[]
|
||||
define?: {
|
||||
|
||||
}
|
||||
devScripts?: {
|
||||
|
||||
}
|
||||
/**
|
||||
* devServer configs
|
||||
*/
|
||||
devServer?: {
|
||||
/**
|
||||
* devServer port, default 8000
|
||||
*/
|
||||
port?: number
|
||||
host?: string
|
||||
https?: ({
|
||||
key?: string
|
||||
cert?: string
|
||||
http2?: boolean
|
||||
[k: string]: any
|
||||
} | boolean)
|
||||
headers?: {
|
||||
|
||||
}
|
||||
writeToDisk?: (boolean | (() => any))
|
||||
[k: string]: any
|
||||
}
|
||||
devtool?: string
|
||||
/**
|
||||
* Code splitting for performance optimization
|
||||
*/
|
||||
dynamicImport?: {
|
||||
/**
|
||||
* loading the component before loaded
|
||||
*/
|
||||
loading?: string
|
||||
}
|
||||
/**
|
||||
* Code splitting for import statement syntax
|
||||
*/
|
||||
dynamicImportSyntax?: {
|
||||
|
||||
}
|
||||
exportStatic?: {
|
||||
htmlSuffix?: boolean
|
||||
dynamicRoot?: boolean
|
||||
supportWin?: boolean
|
||||
/**
|
||||
* extra render paths only enable in ssr
|
||||
*/
|
||||
extraRoutePaths?: (() => any)
|
||||
}
|
||||
externals?: ({
|
||||
|
||||
} | string | (() => any))
|
||||
extraBabelIncludes?: any[]
|
||||
extraBabelPlugins?: any[]
|
||||
extraBabelPresets?: any[]
|
||||
extraPostCSSPlugins?: any[]
|
||||
/**
|
||||
* fork-ts-checker-webpack-plugin options see https://github.com/TypeStrong/fork-ts-checker-webpack-plugin#options
|
||||
*/
|
||||
forkTSChecker?: {
|
||||
async?: boolean
|
||||
typescript?: (boolean | {
|
||||
|
||||
})
|
||||
eslint?: {
|
||||
|
||||
}
|
||||
issue?: {
|
||||
|
||||
}
|
||||
formatter?: (string | {
|
||||
|
||||
})
|
||||
logger?: {
|
||||
|
||||
}
|
||||
[k: string]: any
|
||||
}
|
||||
fastRefresh?: {
|
||||
|
||||
}
|
||||
hash?: boolean
|
||||
ignoreMomentLocale?: boolean
|
||||
inlineLimit?: number
|
||||
lessLoader?: {
|
||||
|
||||
}
|
||||
manifest?: {
|
||||
fileName?: string
|
||||
publicPath?: ""
|
||||
basePath?: string
|
||||
writeToFileEmit?: boolean
|
||||
}
|
||||
/**
|
||||
* open mfsu feature
|
||||
*/
|
||||
mfsu?: {
|
||||
development?: {
|
||||
output?: string
|
||||
}
|
||||
production?: {
|
||||
output?: string
|
||||
}
|
||||
mfName?: string
|
||||
exportAllMembers?: {
|
||||
|
||||
}
|
||||
chunks?: string[]
|
||||
ignoreNodeBuiltInModules?: boolean
|
||||
}
|
||||
mountElementId?: ""
|
||||
mpa?: {
|
||||
|
||||
}
|
||||
nodeModulesTransform?: {
|
||||
type?: ("all" | "none")
|
||||
exclude?: string[]
|
||||
}
|
||||
outputPath?: ""
|
||||
plugins?: string[]
|
||||
postcssLoader?: {
|
||||
|
||||
}
|
||||
presets?: string[]
|
||||
proxy?: {
|
||||
|
||||
}
|
||||
publicPath?: string
|
||||
runtimePublicPath?: boolean
|
||||
ssr?: {
|
||||
/**
|
||||
* force execing Page getInitialProps functions
|
||||
*/
|
||||
forceInitial?: boolean
|
||||
/**
|
||||
* remove window.g_initialProps in html
|
||||
*/
|
||||
removeWindowInitialProps?: boolean
|
||||
/**
|
||||
* disable serve-side render in umi dev mode.
|
||||
*/
|
||||
devServerRender?: boolean
|
||||
mode?: ("stream" | "string")
|
||||
/**
|
||||
* static markup in static site
|
||||
*/
|
||||
staticMarkup?: boolean
|
||||
}
|
||||
singular?: boolean
|
||||
styleLoader?: {
|
||||
|
||||
}
|
||||
targets?: {
|
||||
|
||||
}
|
||||
terserOptions?: {
|
||||
|
||||
}
|
||||
theme?: {
|
||||
|
||||
}
|
||||
runtimeHistory?: {
|
||||
|
||||
}
|
||||
webpack5?: {
|
||||
lazyCompilation?: {
|
||||
entries?: boolean
|
||||
imports?: boolean
|
||||
test?: any
|
||||
}
|
||||
}
|
||||
workerLoader?: {
|
||||
|
||||
}
|
||||
favicon?: string
|
||||
headScripts?: any[]
|
||||
links?: any[]
|
||||
metas?: any[]
|
||||
scripts?: any[]
|
||||
styles?: any[]
|
||||
title?: string
|
||||
mock?: {
|
||||
exclude?: string[]
|
||||
}
|
||||
themeConfig?: {
|
||||
|
||||
}
|
||||
logo?: (string | boolean)
|
||||
mode?: any
|
||||
description?: string
|
||||
locales?: string[][]
|
||||
resolve?: {
|
||||
|
||||
}
|
||||
menus?: {
|
||||
|
||||
}
|
||||
navs?: (any[] | {
|
||||
|
||||
})
|
||||
algolia?: {
|
||||
appId?: string
|
||||
apiKey?: string
|
||||
indexName?: string
|
||||
debug?: boolean
|
||||
}
|
||||
sitemap?: {
|
||||
hostname?: string
|
||||
excludes?: string[]
|
||||
}
|
||||
apiParser?: {
|
||||
|
||||
}
|
||||
[k: string]: any
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import { plugin } from './plugin';
|
||||
|
||||
|
||||
export const __mfsu = 1;
|
@ -1,4 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import 'core-js';
|
||||
import 'regenerator-runtime/runtime';
|
||||
export {};
|
@ -1,129 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { ApplyPluginsType } from '/Users/teddyj/Library/Mobile Documents/com~apple~CloudDocs/Documents/workspace/dev/nicenote/node_modules/_@umijs_runtime@3.5.41@@umijs/runtime';
|
||||
import * as umiExports from './umiExports';
|
||||
import { plugin } from './plugin';
|
||||
|
||||
export function getRoutes() {
|
||||
const routes = [
|
||||
{
|
||||
"path": "/~demos/:uuid",
|
||||
"layout": false,
|
||||
"wrappers": [require('../dumi/layout').default],
|
||||
"component": ((props) => {
|
||||
const React = require('react');
|
||||
const { default: getDemoRenderArgs } = require('/Users/teddyj/Library/Mobile Documents/com~apple~CloudDocs/Documents/workspace/dev/nicenote/node_modules/_@umijs_preset-dumi@1.1.53@@umijs/preset-dumi/lib/plugins/features/demo/getDemoRenderArgs');
|
||||
const { default: Previewer } = require('dumi-theme-default/es/builtins/Previewer.js');
|
||||
const { usePrefersColor, context } = require('dumi/theme');
|
||||
|
||||
|
||||
const { demos } = React.useContext(context);
|
||||
const [renderArgs, setRenderArgs] = React.useState([]);
|
||||
|
||||
// update render args when props changed
|
||||
React.useLayoutEffect(() => {
|
||||
setRenderArgs(getDemoRenderArgs(props, demos));
|
||||
}, [props.match.params.uuid, props.location.query.wrapper, props.location.query.capture]);
|
||||
|
||||
// for listen prefers-color-schema media change in demo single route
|
||||
usePrefersColor();
|
||||
|
||||
switch (renderArgs.length) {
|
||||
case 1:
|
||||
// render demo directly
|
||||
return renderArgs[0];
|
||||
|
||||
case 2:
|
||||
// render demo with previewer
|
||||
return React.createElement(
|
||||
Previewer,
|
||||
renderArgs[0],
|
||||
renderArgs[1],
|
||||
);
|
||||
|
||||
default:
|
||||
return `Demo ${props.match.params.uuid} not found :(`;
|
||||
}
|
||||
|
||||
})
|
||||
},
|
||||
{
|
||||
"path": "/_demos/:uuid",
|
||||
"redirect": "/~demos/:uuid"
|
||||
},
|
||||
{
|
||||
"__dumiRoot": true,
|
||||
"layout": false,
|
||||
"path": "/",
|
||||
"wrappers": [require('../dumi/layout').default, require('/Users/teddyj/Library/Mobile Documents/com~apple~CloudDocs/Documents/workspace/dev/nicenote/node_modules/_dumi-theme-default@1.1.24@dumi-theme-default/es/layout.js').default],
|
||||
"routes": [
|
||||
{
|
||||
"path": "/guide",
|
||||
"component": require('/Users/teddyj/Library/Mobile Documents/com~apple~CloudDocs/Documents/workspace/dev/nicenote/new/docs/guide.md').default,
|
||||
"exact": true,
|
||||
"meta": {
|
||||
"filePath": "docs/guide.md",
|
||||
"updatedTime": 1698630719271,
|
||||
"slugs": [],
|
||||
"title": "Guide"
|
||||
},
|
||||
"title": "Guide - nicenote"
|
||||
},
|
||||
{
|
||||
"path": "/",
|
||||
"component": require('/Users/teddyj/Library/Mobile Documents/com~apple~CloudDocs/Documents/workspace/dev/nicenote/new/docs/index.md').default,
|
||||
"exact": true,
|
||||
"meta": {
|
||||
"filePath": "docs/index.md",
|
||||
"updatedTime": 1698630719273,
|
||||
"title": "A static site based on dumi",
|
||||
"hero": {
|
||||
"title": "Site",
|
||||
"description": "nicenote,nicecode,学习,总结",
|
||||
"actions": [
|
||||
{
|
||||
"text": "Hello",
|
||||
"link": "/"
|
||||
},
|
||||
{
|
||||
"text": "World",
|
||||
"link": "/"
|
||||
}
|
||||
]
|
||||
},
|
||||
"features": [
|
||||
{
|
||||
"title": "Hello",
|
||||
"emoji": "💎",
|
||||
"description": "Put hello description here"
|
||||
},
|
||||
{
|
||||
"title": "World",
|
||||
"emoji": "🌈",
|
||||
"description": "Put world description here"
|
||||
},
|
||||
{
|
||||
"title": "!",
|
||||
"emoji": "🚀",
|
||||
"description": "Put ! description here"
|
||||
}
|
||||
],
|
||||
"slugs": []
|
||||
},
|
||||
"title": "A static site based on dumi - nicenote"
|
||||
}
|
||||
],
|
||||
"title": "nicenote",
|
||||
"component": (props) => props.children
|
||||
}
|
||||
];
|
||||
|
||||
// allow user to extend routes
|
||||
plugin.applyPlugins({
|
||||
key: 'patchRoutes',
|
||||
type: ApplyPluginsType.event,
|
||||
args: { routes },
|
||||
});
|
||||
|
||||
return routes;
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
// @ts-nocheck
|
||||
export { history } from './history';
|
||||
export { plugin } from './plugin';
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1,32 +0,0 @@
|
||||
{
|
||||
"menus": {
|
||||
"en-US": {
|
||||
"*": [
|
||||
{
|
||||
"path": "/",
|
||||
"title": "A static site based on dumi",
|
||||
"meta": {}
|
||||
},
|
||||
{
|
||||
"path": "/guide",
|
||||
"title": "Guide",
|
||||
"meta": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"locales": [
|
||||
{
|
||||
"name": "en-US",
|
||||
"label": "English"
|
||||
}
|
||||
],
|
||||
"navs": {},
|
||||
"title": "nicenote",
|
||||
"mode": "doc",
|
||||
"repository": {
|
||||
"url": "",
|
||||
"branch": "master"
|
||||
},
|
||||
"theme": {}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { dynamic } from 'dumi';
|
||||
|
||||
export default {
|
||||
};
|
@ -1,8 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import config from '@@/dumi/config';
|
||||
import demos from '@@/dumi/demos';
|
||||
import apis from '@@/dumi/apis';
|
||||
import Layout from '/Users/teddyj/Library/Mobile Documents/com~apple~CloudDocs/Documents/workspace/dev/nicenote/node_modules/_@umijs_preset-dumi@1.1.53@@umijs/preset-dumi/lib/theme/layout';
|
||||
|
||||
export default (props) => <Layout {...props} config={config} demos={demos} apis={apis} />;
|
58
.umi/umi.ts
@ -1,58 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import './core/polyfill';
|
||||
import '@@/core/devScripts';
|
||||
import { plugin } from './core/plugin';
|
||||
import './core/pluginRegister';
|
||||
import { createHistory } from './core/history';
|
||||
import { ApplyPluginsType } from '/Users/teddyj/Library/Mobile Documents/com~apple~CloudDocs/Documents/workspace/dev/nicenote/node_modules/_@umijs_runtime@3.5.41@@umijs/runtime';
|
||||
import { renderClient } from '/Users/teddyj/Library/Mobile Documents/com~apple~CloudDocs/Documents/workspace/dev/nicenote/node_modules/_@umijs_renderer-react@3.5.41@@umijs/renderer-react/dist/index.js';
|
||||
import { getRoutes } from './core/routes';
|
||||
|
||||
|
||||
|
||||
|
||||
const getClientRender = (args: { hot?: boolean; routes?: any[] } = {}) => plugin.applyPlugins({
|
||||
key: 'render',
|
||||
type: ApplyPluginsType.compose,
|
||||
initialValue: () => {
|
||||
const opts = plugin.applyPlugins({
|
||||
key: 'modifyClientRenderOpts',
|
||||
type: ApplyPluginsType.modify,
|
||||
initialValue: {
|
||||
routes: args.routes || getRoutes(),
|
||||
plugin,
|
||||
history: createHistory(args.hot),
|
||||
isServer: process.env.__IS_SERVER,
|
||||
rootElement: 'root',
|
||||
defaultTitle: ``,
|
||||
},
|
||||
});
|
||||
return renderClient(opts);
|
||||
},
|
||||
args,
|
||||
});
|
||||
|
||||
const clientRender = getClientRender();
|
||||
export default clientRender();
|
||||
|
||||
|
||||
window.g_umi = {
|
||||
version: '3.5.41',
|
||||
};
|
||||
|
||||
|
||||
// hot module replacement
|
||||
// @ts-ignore
|
||||
if (module.hot) {
|
||||
// @ts-ignore
|
||||
module.hot.accept('./core/routes', () => {
|
||||
const ret = require('./core/routes');
|
||||
if (ret.then) {
|
||||
ret.then(({ getRoutes }) => {
|
||||
getClientRender({ hot: true, routes: getRoutes() })();
|
||||
});
|
||||
} else {
|
||||
getClientRender({ hot: true, routes: ret.getRoutes() })();
|
||||
}
|
||||
});
|
||||
}
|
52
CHANGELOG.md
@ -2,34 +2,30 @@
|
||||
|
||||
### 🌟 新功能
|
||||
|
||||
* 初始化项目 ([466dbeb](https://github.com/j710328466/j710328466.github.io/commit/466dbeb))
|
||||
* 新增模块 ([9e0b3a9](https://github.com/j710328466/j710328466.github.io/commit/9e0b3a9))
|
||||
* 新增心跳组件 ([82a59b4](https://github.com/j710328466/j710328466.github.io/commit/82a59b4))
|
||||
* 修改tools,git命令 ([efb8285](https://github.com/j710328466/j710328466.github.io/commit/efb8285))
|
||||
* **docs:** 新增文章 ([f659605](https://github.com/j710328466/j710328466.github.io/commit/f659605))
|
||||
* **fea/vue:** 新增vue教程文档 ([d150264](https://github.com/j710328466/j710328466.github.io/commit/d150264))
|
||||
* **fea:** typescript ([abb3cfe](https://github.com/j710328466/j710328466.github.io/commit/abb3cfe))
|
||||
* **md:** 新文章 ([41459c4](https://github.com/j710328466/j710328466.github.io/commit/41459c4))
|
||||
* **package.json:** 添加husky ([95a0051](https://github.com/j710328466/j710328466.github.io/commit/95a0051))
|
||||
* **resume:** 修改简历 ([9f28c78](https://github.com/j710328466/j710328466.github.io/commit/9f28c78))
|
||||
* svg学习笔记 ([63e96b7](https://github.com/j710328466/j710328466.github.io/commit/63e96b7))
|
||||
|
||||
- 初始化项目 ([466dbeb](https://github.com/j710328466/j710328466.github.io/commit/466dbeb))
|
||||
- 新增模块 ([9e0b3a9](https://github.com/j710328466/j710328466.github.io/commit/9e0b3a9))
|
||||
- 新增心跳组件 ([82a59b4](https://github.com/j710328466/j710328466.github.io/commit/82a59b4))
|
||||
- 修改 tools,git 命令 ([efb8285](https://github.com/j710328466/j710328466.github.io/commit/efb8285))
|
||||
- **docs:** 新增文章 ([f659605](https://github.com/j710328466/j710328466.github.io/commit/f659605))
|
||||
- **fea/vue:** 新增 vue 教程文档 ([d150264](https://github.com/j710328466/j710328466.github.io/commit/d150264))
|
||||
- **fea:** typescript ([abb3cfe](https://github.com/j710328466/j710328466.github.io/commit/abb3cfe))
|
||||
- **md:** 新文章 ([41459c4](https://github.com/j710328466/j710328466.github.io/commit/41459c4))
|
||||
- **package.json:** 添加 husky ([95a0051](https://github.com/j710328466/j710328466.github.io/commit/95a0051))
|
||||
- **resume:** 修改简历 ([9f28c78](https://github.com/j710328466/j710328466.github.io/commit/9f28c78))
|
||||
- svg 学习笔记 ([63e96b7](https://github.com/j710328466/j710328466.github.io/commit/63e96b7))
|
||||
|
||||
### 🐛 Bug 修复
|
||||
|
||||
* **工具类:** lerna QA ([dbb0c36](https://github.com/j710328466/j710328466.github.io/commit/dbb0c36))
|
||||
* 设计模式添加 ([79143a6](https://github.com/j710328466/j710328466.github.io/commit/79143a6))
|
||||
* 新增react学习 ([a7ec84e](https://github.com/j710328466/j710328466.github.io/commit/a7ec84e))
|
||||
* 修改路径 ([2261dc4](https://github.com/j710328466/j710328466.github.io/commit/2261dc4))
|
||||
* 修改配置 ([bfd5f0f](https://github.com/j710328466/j710328466.github.io/commit/bfd5f0f))
|
||||
* 修改设计模式 ([6f5630d](https://github.com/j710328466/j710328466.github.io/commit/6f5630d))
|
||||
* 修改bug ([83e7ea9](https://github.com/j710328466/j710328466.github.io/commit/83e7ea9))
|
||||
* 优化react 设计模式 ([cf4958e](https://github.com/j710328466/j710328466.github.io/commit/cf4958e))
|
||||
* **fed/vue:** 新增内容 ([07f15ba](https://github.com/j710328466/j710328466.github.io/commit/07f15ba))
|
||||
* **resume:** 新增简历 ([f40ea2e](https://github.com/j710328466/j710328466.github.io/commit/f40ea2e))
|
||||
* **resume:** 修改简历 ([aa7715c](https://github.com/j710328466/j710328466.github.io/commit/aa7715c))
|
||||
* **resume:** 修改简历 ([3e498ff](https://github.com/j710328466/j710328466.github.io/commit/3e498ff))
|
||||
* **sd:** sd ([e7d434d](https://github.com/j710328466/j710328466.github.io/commit/e7d434d))
|
||||
|
||||
|
||||
|
||||
- **工具类:** lerna QA ([dbb0c36](https://github.com/j710328466/j710328466.github.io/commit/dbb0c36))
|
||||
- 设计模式添加 ([79143a6](https://github.com/j710328466/j710328466.github.io/commit/79143a6))
|
||||
- 新增 react 学习 ([a7ec84e](https://github.com/j710328466/j710328466.github.io/commit/a7ec84e))
|
||||
- 修改路径 ([2261dc4](https://github.com/j710328466/j710328466.github.io/commit/2261dc4))
|
||||
- 修改配置 ([bfd5f0f](https://github.com/j710328466/j710328466.github.io/commit/bfd5f0f))
|
||||
- 修改设计模式 ([6f5630d](https://github.com/j710328466/j710328466.github.io/commit/6f5630d))
|
||||
- 修改 bug ([83e7ea9](https://github.com/j710328466/j710328466.github.io/commit/83e7ea9))
|
||||
- 优化 react 设计模式 ([cf4958e](https://github.com/j710328466/j710328466.github.io/commit/cf4958e))
|
||||
- **fed/vue:** 新增内容 ([07f15ba](https://github.com/j710328466/j710328466.github.io/commit/07f15ba))
|
||||
- **resume:** 新增简历 ([f40ea2e](https://github.com/j710328466/j710328466.github.io/commit/f40ea2e))
|
||||
- **resume:** 修改简历 ([aa7715c](https://github.com/j710328466/j710328466.github.io/commit/aa7715c))
|
||||
- **resume:** 修改简历 ([3e498ff](https://github.com/j710328466/j710328466.github.io/commit/3e498ff))
|
||||
- **sd:** sd ([e7d434d](https://github.com/j710328466/j710328466.github.io/commit/e7d434d))
|
||||
|
@ -159,3 +159,4 @@ class Car implements Alarm, Light {
|
||||
1. [Type Search](https://www.typescriptlang.org/dt/search?search=)
|
||||
2. [quick Type:自动生成 Type](https://app.quicktype.io)
|
||||
3. [ts playground: 线上编写测试代码](https://www.typescriptlang.org/zh/play)
|
||||
4. [tsconfig 参数解释](https://segmentfault.com/a/1190000021749847)
|
||||
|
@ -1,8 +1,8 @@
|
||||
---
|
||||
title: A static site based on dumi
|
||||
title: Nice Note
|
||||
hero:
|
||||
title: NiceNote
|
||||
description: dev 的学习博客
|
||||
title: Nice Note
|
||||
description: dev 的博客
|
||||
actions:
|
||||
- text: 开始学习
|
||||
link: /fea/website
|
||||
@ -12,6 +12,8 @@ features:
|
||||
description: <a href="https://nicecoders.github.io">前端工具合集</a>
|
||||
---
|
||||
|
||||
这是我用来记录我的职业生涯总结的各种乱七八糟的知识点,希望能对你有帮助
|
||||
这里记录了我所有工作中和非工作中的思考和总结
|
||||
|
||||
思维比较发散,想到哪写到哪
|
||||
|
||||
<embed src="../CHANGELOG.md"></embed>
|
||||
|
@ -17,11 +17,13 @@ group:
|
||||
#### 确认网络
|
||||
|
||||
- ping [j710328466.github.io](j710328466.github.io)
|
||||
|
||||
#### 关闭 iptables 规则
|
||||
|
||||
- iptables -L 查看
|
||||
- iptables -F 关闭
|
||||
- iptables -t nat -L
|
||||
|
||||
#### 关闭 getenforce
|
||||
|
||||
- setenforce 0
|
||||
@ -37,6 +39,9 @@ group:
|
||||
```
|
||||
|
||||
### 安装编译工具和库
|
||||
|
||||
如果没有再安装
|
||||
|
||||
```js
|
||||
// 1
|
||||
wget [http://downloads.sourceforge.net/project/pcre/pcre/8.35/pcre-8.35.tar.gz](http://downloads.sourceforge.net/project/pcre/pcre/8.35/pcre-8.35.tar.gz)
|
||||
@ -52,16 +57,30 @@ yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel
|
||||
- yum -y update
|
||||
|
||||
### centos 快速安装
|
||||
|
||||
- yum install nginx -y
|
||||
|
||||
## 默认文件位置
|
||||
|
||||
```js
|
||||
/etc/nginx/nginx.conf //yum方式安装后默认配置文件的路径
|
||||
|
||||
/usr/share/nginx/html //nginx网站默认存放目录
|
||||
|
||||
/usr/share/nginx/html/index.html //网站默认主页路径
|
||||
```
|
||||
|
||||
## 常用命令
|
||||
|
||||
### 查看 nginx 配置文件路径和安装路径
|
||||
|
||||
> nginx -t
|
||||
|
||||
### 开始
|
||||
|
||||
systemctl start nginx
|
||||
方法 1. systemctl start nginx
|
||||
|
||||
方法 2. systemctl enable --now nginx
|
||||
|
||||
### 重启
|
||||
|
||||
@ -73,10 +92,9 @@ systemctl start nginx
|
||||
> killall -9 nginx
|
||||
|
||||
### 初始目录
|
||||
|
||||
> /usr/share/nginx/html
|
||||
|
||||
|
||||
|
||||
### 配置文件
|
||||
|
||||
```
|
||||
@ -185,6 +203,7 @@ http {
|
||||
## Q&A
|
||||
|
||||
### 1. forbedden 403
|
||||
|
||||
> chmod -R 777 /data
|
||||
> chmod -R 777 /data/www
|
||||
|
||||
@ -195,5 +214,3 @@ vi /etc/selinux/config
|
||||
#SELINUX=enforcing
|
||||
SELINUX=disabled
|
||||
```
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "dumi build",
|
||||
"deploy": "npm run build && gh-pages -d docs-dist",
|
||||
"deploy": "gh-pages -d docs-dist",
|
||||
"dev": "dumi dev",
|
||||
"prepare": "husky install && dumi setup",
|
||||
"start": "npm run dev"
|
||||
@ -27,6 +27,7 @@
|
||||
"@commitlint/cli": "^17.1.2",
|
||||
"@commitlint/config-conventional": "^17.1.0",
|
||||
"dumi": "^2.2.13",
|
||||
"gh-pages": "^6.1.1",
|
||||
"husky": "^8.0.1",
|
||||
"lint-staged": "^13.0.3",
|
||||
"prettier": "^2.7.1"
|
||||
|
15898
pnpm-lock.yaml
@ -1,94 +0,0 @@
|
||||
|
||||
import React, { useRef, useEffect } from 'react';
|
||||
|
||||
export default () => {
|
||||
const clockRef = useRef()
|
||||
|
||||
function clock() {
|
||||
var theCanv = clockRef.current;
|
||||
var theCanvObject = theCanv.getContext('2d');
|
||||
var x = 200;
|
||||
var y = 200;
|
||||
|
||||
startTime();
|
||||
|
||||
function startTime() {
|
||||
|
||||
//分秒刻度和表盘
|
||||
theCanvObject.lineWidth = 1;
|
||||
for (var i = 0; i < 60; i++) {
|
||||
drawArc(150, i*6, (i+1)*6);
|
||||
}
|
||||
drawArc(145, 0, 360, true);
|
||||
|
||||
//时刻度
|
||||
theCanvObject.lineWidth = 2;
|
||||
for (var i = 0; i < 12; i++) {
|
||||
drawArc(150, i*30, (i+1)*30);
|
||||
}
|
||||
drawArc(140, 0, 360, true);
|
||||
|
||||
//针
|
||||
drawHand(getTime().hour,5,60,'#ECFC00');
|
||||
drawHand(getTime().min,4,100,'#00BB3F');
|
||||
drawHand(getTime().sec,3,130,'#D60062');
|
||||
|
||||
setInterval(function () {
|
||||
drawArc(135,0,360,true);
|
||||
drawHand(getTime().hour,5,60,'#ECFC00');
|
||||
drawHand(getTime().min,4,100,'#00BB3F');
|
||||
drawHand(getTime().sec,3,130,'#D60062');
|
||||
},1000);
|
||||
}
|
||||
|
||||
function drawArc(iRadius, iBeginAngle, iEndAngle, ifClear) {
|
||||
var beginRadian = iBeginAngle*Math.PI/180;
|
||||
var endRadian = iEndAngle*Math.PI/180;
|
||||
|
||||
theCanvObject.beginPath(); //创建一个路径
|
||||
theCanvObject.moveTo(x, y); //将路径移到x,y
|
||||
theCanvObject.arc(x, y, iRadius, beginRadian, endRadian, false);
|
||||
//画弧
|
||||
!ifClear && theCanvObject.stroke();
|
||||
|
||||
if (ifClear) {
|
||||
theCanvObject.fillStyle = 'white';
|
||||
theCanvObject.fill();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function drawHand(iAngle, iWidth, iLength, iColor) {
|
||||
|
||||
theCanvObject.save(); //保存的是canvas的属性,不是截图
|
||||
theCanvObject.lineWidth = iWidth;
|
||||
theCanvObject.strokeStyle = iColor;
|
||||
drawArc(iLength, iAngle, iAngle);
|
||||
theCanvObject.restore(); //弹出栈中的状态
|
||||
|
||||
}
|
||||
|
||||
//根据当前时间返回各个针要指的度数
|
||||
function getTime() {
|
||||
|
||||
var jTime = {};
|
||||
var iNow = new Date();
|
||||
jTime.sec = -90 + iNow.getSeconds()*6;
|
||||
jTime.min = -90 + iNow.getMinutes()*6 + iNow.getSeconds()/20;
|
||||
jTime.hour = -90 + iNow.getHours()*30 + iNow.getMinutes()/2;
|
||||
|
||||
return jTime;
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
clock()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<canvas ref={clockRef} width="600" height="600" />
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
import React, { useRef, useEffect } from 'react';
|
||||
|
||||
export default () => {
|
||||
const canvasRef = useRef()
|
||||
|
||||
function init() {
|
||||
var c = canvasRef.current,
|
||||
$ = c.getContext('2d'),
|
||||
w = c.width = window.innerWidth / 2,
|
||||
h = c.height = window.innerHeight / 2,
|
||||
particles = []
|
||||
|
||||
/**
|
||||
* 随机获取颜色
|
||||
*
|
||||
* @returns rgb(x,x,x)
|
||||
*/
|
||||
function randomColor() {
|
||||
var r = 100 + Math.floor(Math.random() * 255),
|
||||
g = Math.floor(Math.random() * 150),
|
||||
b = Math.floor(Math.random() * 15)
|
||||
return 'rgb(' + r + ',' + g + ',' + b + ')'
|
||||
}
|
||||
|
||||
function particle() {
|
||||
this.location = {
|
||||
x: w / 2,
|
||||
y: h / 2
|
||||
}
|
||||
this.speed = {
|
||||
x: -1.5 + Math.random() * 3,
|
||||
y: 1 + Math.random() * 5.5
|
||||
}
|
||||
this.life = 50
|
||||
this.radius = 1 + Math.floor(Math.random() * 25)
|
||||
this.color = randomColor()
|
||||
this.opacity = 1
|
||||
this.dead = false
|
||||
this.draw = function () {
|
||||
$.globalCompositeOperation = 'lighter'
|
||||
$.fillStyle = this.color
|
||||
$.beginPath()
|
||||
$.arc(this.location.x, this.location.y, this.radius, 0, Math.PI * 2)
|
||||
$.globalAlpha = this.opacity
|
||||
$.fill()
|
||||
$.closePath()
|
||||
}
|
||||
this.update = function () {
|
||||
if (this.location.x < 0 || this.life == 0 || this.opacity === 0 || this.radius < 1) {
|
||||
this.dead = true
|
||||
}
|
||||
if (!this.dead) {
|
||||
this.location.x += this.speed.x
|
||||
this.location.y -= this.speed.y
|
||||
this.life--
|
||||
this.opacity -= 0.05
|
||||
this.radius--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 将火焰置于背景之后
|
||||
function stage() {
|
||||
$.globalCompositeOperation = 'source-over'
|
||||
$.fillStyle = 'rgba(0, 0, 0, 1)'
|
||||
$.fillRect(0, 0, w, h)
|
||||
}
|
||||
|
||||
// 重置画布大小
|
||||
function reset() {
|
||||
w = c.width = window.innerWidth / 2
|
||||
h = c.height = window.innerHeight / 2
|
||||
}
|
||||
|
||||
function loop() {
|
||||
stage()
|
||||
var L = particles.length
|
||||
if (L < 100) {
|
||||
particles.push(new particle())
|
||||
}
|
||||
for (var i = 0; i < L; i++) {
|
||||
var p = particles[i]
|
||||
p.draw()
|
||||
p.update()
|
||||
if (p.dead) {
|
||||
particles[i] = new particle()
|
||||
}
|
||||
}
|
||||
requestAnimationFrame(loop)
|
||||
}
|
||||
|
||||
function _init() {
|
||||
reset()
|
||||
loop()
|
||||
}
|
||||
|
||||
window.addEventListener('resize', reset)
|
||||
_init()
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
init()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<canvas ref={canvasRef} width="200" height="200" />
|
||||
</div>
|
||||
)
|
||||
}
|
Before Width: | Height: | Size: 166 KiB |
Before Width: | Height: | Size: 150 KiB |
@ -1,118 +0,0 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
const img1 = require('./img/clipImg1.jpg')
|
||||
const img2 = require('./img/clipImg2.jpg')
|
||||
|
||||
export default () => {
|
||||
const canvasRef = useRef()
|
||||
const clipImgs1Ref = useRef()
|
||||
const clipImgs2Ref = useRef()
|
||||
|
||||
|
||||
function clipPathMaskRender() {
|
||||
const NUM_CIRCLES = 60
|
||||
const MIN_SIZE = 50
|
||||
const MAX_SIZE = 100
|
||||
|
||||
function getRndInt(min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min
|
||||
}
|
||||
|
||||
var c = canvasRef && canvasRef.current
|
||||
var ctx = c.getContext('2d')
|
||||
var clipImg1 = clipImgs1Ref && clipImgs1Ref.current
|
||||
var clipImg2 = clipImgs2Ref && clipImgs2Ref.current
|
||||
var t
|
||||
|
||||
class Circle {
|
||||
constructor() {
|
||||
this.x = 0
|
||||
this.y = 0
|
||||
this.size = 0
|
||||
this._needsRandomized = false
|
||||
}
|
||||
|
||||
randomize () {
|
||||
this.x = getRndInt(50, c.width - 50)
|
||||
this.y = getRndInt(50, c.height - 50)
|
||||
this.maxSize = getRndInt(MIN_SIZE, MAX_SIZE)
|
||||
}
|
||||
|
||||
// 更新
|
||||
update (t, ofs) {
|
||||
// abs 绝对值
|
||||
this.size = Math.abs(Math.round(Math.sin(t + ofs) * this.maxSize))
|
||||
|
||||
if (this.size < 2) {
|
||||
if (this._needsRandomized) {
|
||||
this.randomize()
|
||||
this._needsRandomized = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 画
|
||||
draw () {
|
||||
ctx.moveTo(this.x, this.y)
|
||||
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI)
|
||||
}
|
||||
}
|
||||
|
||||
var circles =[]
|
||||
for (let i = 0; i < NUM_CIRCLES; i++) {
|
||||
var circle = new Circle()
|
||||
circle.randomize()
|
||||
circles.push(circle)
|
||||
}
|
||||
|
||||
function update() {
|
||||
t = 0.001 * Date.now()
|
||||
circles.forEach((circle, idx) => {
|
||||
circle.update(t, idx)
|
||||
})
|
||||
}
|
||||
|
||||
async function render() {
|
||||
await ctx.drawImage(clipImg1, 0, 0)
|
||||
await ctx.save()
|
||||
await ctx.beginPath()
|
||||
|
||||
circles.forEach(function(circle) {
|
||||
circle.draw()
|
||||
})
|
||||
|
||||
ctx.closePath()
|
||||
ctx.clip()
|
||||
|
||||
ctx.drawImage(clipImg2, 0, 0)
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
function loop() {
|
||||
requestAnimationFrame(loop)
|
||||
update()
|
||||
render()
|
||||
}
|
||||
|
||||
loop()
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
clipPathMaskRender()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="clipPathMask demo">
|
||||
<div className="wrap">
|
||||
<h1 className="wrap_tit">Nice Note</h1>
|
||||
<canvas ref={canvasRef} className="wrap_canvas" width="500px" height="500px"></canvas>
|
||||
</div>
|
||||
<div id="clipImgs">
|
||||
<img ref={clipImgs1Ref} id="clipImgs_1" crossOrigin="anonymous" src={img1} />
|
||||
<img ref={clipImgs2Ref} id="clipImgs_2" crossOrigin="anonymous" src={img2} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
.clipPathMask {
|
||||
text-align: center;
|
||||
height: 80vh;
|
||||
color: #fff;
|
||||
background: teal linear-gradient(transparent, #ff0099);
|
||||
.wrap {
|
||||
&_tit {
|
||||
padding: 10px 0;
|
||||
font-size: 30px;
|
||||
}
|
||||
&_canvas {
|
||||
border: 1px solid yellow;
|
||||
}
|
||||
}
|
||||
#clipImgs {
|
||||
display: none;
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
import React, { useRef, useEffect } from 'react';
|
||||
|
||||
export default () => {
|
||||
const canvasRef = useRef()
|
||||
|
||||
function init() {
|
||||
const theCanvas = canvasRef.current,
|
||||
ctx = theCanvas.getContext('2d'),
|
||||
current_point = {
|
||||
x: null, //当前鼠标x
|
||||
y: null, //当前鼠标y
|
||||
max: 20000,
|
||||
};
|
||||
|
||||
let canvas_width = theCanvas.width,
|
||||
canvas_height = theCanvas.height,
|
||||
random_points = [],
|
||||
all_points = [];
|
||||
|
||||
// theCanvas.style = "position: absolute; top: 0px; left: 0px;";
|
||||
|
||||
|
||||
function draw() {
|
||||
//清屏
|
||||
ctx.clearRect(0, 0, canvas_width, canvas_height);
|
||||
let i,pi,x_dist,y_dist,dist,w;
|
||||
|
||||
//遍历点集合绘制线条,类似于握手问题,两个点只绘制一条线
|
||||
random_points.forEach((p, index) => {
|
||||
p.x += p.xa, //按指定速度移动
|
||||
p.y += p.ya,
|
||||
//小球碰撞则速度取相反数
|
||||
p.xa *= p.x > canvas_width || p.x < 0 ? -1 : 1,
|
||||
p.ya *= p.y > canvas_height || p.y < 0 ? -1 : 1,
|
||||
ctx.fillRect(p.x - 0.5, p.y - 0.5, 1, 1); //绘制点
|
||||
|
||||
for(i = index + 1; i < all_points.length; i++ ) {
|
||||
pi = all_points[i];
|
||||
if(pi.x !== null && pi.y !== null) {
|
||||
x_dist = p.x - pi.x;
|
||||
y_dist = p.y - pi.y;
|
||||
dist = x_dist * x_dist + y_dist * y_dist;
|
||||
//当两点距离小于极限距离时会产生连线,当第二个点是鼠标所产生点时,第一个点在范围内会产生向鼠标点的速度,产生吸附效果
|
||||
dist < pi.max && (pi === current_point && dist >= pi.max / 2 && (p.x -= 0.03 * x_dist, p.y -= 0.03 * y_dist));
|
||||
//根据距离计算连线的透明度,使过度效果流畅
|
||||
w = (pi.max - dist) / pi.max;
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = w / 2;
|
||||
ctx.strokeStyle = `rgba(110,110,110,${w + 0.2})`;
|
||||
ctx.moveTo(p.x, p.y);
|
||||
ctx.lineTo(pi.x, pi.y);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}),requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
|
||||
//绑定事件,判断是否添加鼠标这个点
|
||||
window.onmousemove = e => {
|
||||
e = e || window.event;
|
||||
current_point.x = e.clientX;
|
||||
current_point.y = e.clientY;
|
||||
};
|
||||
window.onmouseout = () => {
|
||||
current_point.x = null;
|
||||
current_point.y = null;
|
||||
};
|
||||
|
||||
|
||||
//随机生成100个点
|
||||
for(let i = 0; i < 100; i++ ) {
|
||||
|
||||
let x = Math.random() * canvas_width, //初始坐标
|
||||
y = Math.random() * canvas_height,
|
||||
xa = 2 * Math.random() - 1, //x速度
|
||||
ya = 2 * Math.random() - 1, //y速度
|
||||
max = 6000; //会产生连线的距离的平方
|
||||
|
||||
random_points[i] = {x, y, xa, ya, max};
|
||||
}
|
||||
//将鼠标的点添加至点集合中
|
||||
all_points = [...random_points,current_point];
|
||||
|
||||
//只是背景特效-所以延迟执行
|
||||
setTimeout(draw, 100);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
init()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div style={{ position: 'relative' }}>
|
||||
<canvas ref={canvasRef} width="500px" height="300px"></canvas>
|
||||
</div>
|
||||
)
|
||||
}
|
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 10 KiB |
@ -1,214 +0,0 @@
|
||||
import React, { useRef, useEffect } from 'react';
|
||||
|
||||
import img1 from './imgs/1.jpg'
|
||||
import img2 from './imgs/2.jpg'
|
||||
import img3 from './imgs/3.jpg'
|
||||
|
||||
const imgs = [img1, img2, img3]
|
||||
class Particale {
|
||||
constructor(opt) {
|
||||
this.warp = opt.warp; //画布
|
||||
this.ctx = opt.warp && opt.warp.getContext('2d');
|
||||
this.imgsUrl = opt.imgsUrl; //图片地址数组
|
||||
this.imgsObj = []; //图片对象数组
|
||||
this.radius = opt.radius || 10; //粒子半径
|
||||
this.index = 0; //当前图片下标
|
||||
this.initz = 300;
|
||||
this.dots = [];
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
|
||||
//限制小球半径
|
||||
if (this.warp.width > 500 || this.warp.height > 300)
|
||||
this.radius >= 4 ? this.radius = this.radius : this.radius = 4;
|
||||
else
|
||||
this.radius >= 2 ? this.radius = this.radius : this.radius = 2;
|
||||
|
||||
let promiseArr = this.imgsUrl.map(imgUrl => {
|
||||
return new Promise((resolve, reject) => {
|
||||
var imgObj = new Image();
|
||||
imgObj.onload = () => {
|
||||
this.imgsObj.push(imgObj);
|
||||
resolve();
|
||||
};
|
||||
imgObj.src = imgUrl;
|
||||
});
|
||||
});
|
||||
//图片全部加载完毕开始绘制
|
||||
Promise.all(promiseArr).then(() => {
|
||||
this.picLoop();
|
||||
});
|
||||
}
|
||||
|
||||
picLoop() {
|
||||
this.dots = [];
|
||||
this.drawPic(); //绘制当前图片
|
||||
this.toParticle(); //得到像素点
|
||||
this.combineAnimate(); //合成图像
|
||||
this.index === this.imgsUrl.length-1 ? this.index = 0 : this.index++; //下标移动到下一张图片
|
||||
}
|
||||
drawPic() {
|
||||
//清除画布
|
||||
this.ctx.clearRect(0, 0, this.warp.width, this.warp.height);
|
||||
let imgObj = this.imgsObj[this.index];
|
||||
|
||||
//限制图片大小
|
||||
if(imgObj.width > imgObj.height) {
|
||||
let ImgScale = imgObj.height / imgObj.width;
|
||||
imgObj.width = this.warp.width * .5;
|
||||
imgObj.height = imgObj.width * ImgScale;
|
||||
} else {
|
||||
let ImgScale = imgObj.width / imgObj.height;
|
||||
imgObj.height = this.warp.height * .7;
|
||||
imgObj.width = imgObj.height * ImgScale;
|
||||
}
|
||||
|
||||
|
||||
//绘制图片到canvas
|
||||
this.ctx.drawImage(imgObj, this.warp.width / 2 - imgObj.width / 2, this.warp.height / 2 - imgObj.height / 2, imgObj.width, imgObj.height);
|
||||
|
||||
}
|
||||
toParticle() {
|
||||
//得到像素
|
||||
let imageData = this.ctx.getImageData(0, 0, this.warp.width, this.warp.height);
|
||||
let data = imageData.data;
|
||||
|
||||
for(let x = 0; x < imageData.width; x += this.radius * 2) {
|
||||
for(let y = 0; y < imageData.height; y += this.radius * 2) {
|
||||
let i = (x + y * this.warp.width) * 4;
|
||||
if(data[i+3] !== 0 && data[i] !== 255 && data[i+1] !== 255 && data[i+2] !== 255) {
|
||||
let dot = {
|
||||
x: x, //图片x轴坐标
|
||||
y: y, // y轴坐标
|
||||
z: 0, // z轴坐标
|
||||
r: data[i], // rgba
|
||||
g: data[i+1], // rgba
|
||||
b: data[i+2], // rgba
|
||||
a: 1, // rgba
|
||||
ix: Math.random() * this.warp.width, //初始化x轴坐标
|
||||
iy: Math.random() * this.warp.height, // y轴坐标
|
||||
iz: Math.random() * this.initz * 2 - this.initz, // z轴坐标
|
||||
ir: 255, // rgba
|
||||
ig: 255, // rgba
|
||||
ib: 255, // rgba
|
||||
ia: 0, // rgba
|
||||
tx: Math.random() * this.warp.width, //目标x轴坐标
|
||||
ty: Math.random() * this.warp.height, // y轴坐标
|
||||
tz: Math.random() * this.initz * 2 - this.initz, // z轴坐标
|
||||
tr: 255, // rgba
|
||||
tg: 255, // rgba
|
||||
tb: 255, // rgba
|
||||
ta: 0, // rgba
|
||||
};
|
||||
this.dots.push(dot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
combineAnimate() {
|
||||
let combined = false;
|
||||
this.ctx.clearRect(0, 0, this.warp.width, this.warp.height);
|
||||
this.dots.map(dot => {
|
||||
if (Math.abs(dot.ix - dot.x) < 0.1 && Math.abs(dot.iy - dot.y) < 0.1 && Math.abs(dot.iz - dot.z) < 0.1) {
|
||||
dot.ix = dot.x;
|
||||
dot.iy = dot.y;
|
||||
dot.iz = dot.z;
|
||||
dot.ir = dot.r;
|
||||
dot.ig = dot.g;
|
||||
dot.ib = dot.b;
|
||||
dot.ia = dot.a;
|
||||
combined = true;
|
||||
} else {
|
||||
dot.ix += (dot.x - dot.ix) * 0.07;
|
||||
dot.iy += (dot.y - dot.iy) * 0.07;
|
||||
dot.iz += (dot.z - dot.iz) * 0.07;
|
||||
dot.ir += (dot.r - dot.ir) * 0.3;
|
||||
dot.ig += (dot.g - dot.ig) * 0.3;
|
||||
dot.ib += (dot.b - dot.ib) * 0.3;
|
||||
dot.ia += (dot.a - dot.ia) * 0.1;
|
||||
combined = false;
|
||||
}
|
||||
|
||||
return this.drowDot(dot);
|
||||
});
|
||||
|
||||
|
||||
if(!combined) {
|
||||
requestAnimationFrame(() => {
|
||||
return this.combineAnimate();
|
||||
});
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
return this.separateAnimate();
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
separateAnimate() {
|
||||
let separated = false;
|
||||
this.ctx.clearRect(0, 0, this.warp.width, this.warp.height);
|
||||
this.dots.map(dot => {
|
||||
if (Math.abs(dot.ix - dot.tx) < 0.1 && Math.abs(dot.iy - dot.ty) < 0.1 && Math.abs(dot.iz - dot.tz) < 0.1) {
|
||||
dot.ix = dot.tx;
|
||||
dot.iy = dot.ty;
|
||||
dot.iz = dot.tz;
|
||||
dot.ir = dot.tr;
|
||||
dot.ig = dot.tg;
|
||||
dot.ib = dot.tb;
|
||||
dot.ia = dot.ta;
|
||||
separated = true;
|
||||
} else {
|
||||
dot.ix += (dot.tx - dot.ix) * 0.07;
|
||||
dot.iy += (dot.ty - dot.iy) * 0.07;
|
||||
dot.iz += (dot.tz - dot.iz) * 0.07;
|
||||
dot.ir += (dot.tr - dot.ir) * 0.02;
|
||||
dot.ig += (dot.tg - dot.ig) * 0.02;
|
||||
dot.ib += (dot.tb - dot.ib) * 0.02;
|
||||
dot.ia += (dot.ta - dot.ia) * 0.03;
|
||||
separated = false;
|
||||
}
|
||||
|
||||
return this.drowDot(dot);
|
||||
});
|
||||
|
||||
|
||||
if(!separated) {
|
||||
requestAnimationFrame(() => {
|
||||
return this.separateAnimate();
|
||||
});
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
return this.picLoop(); //间接递归,使用尾递归优化
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
drowDot(dot) {
|
||||
let scale = this.initz / (this.initz + dot.iz);
|
||||
this.ctx.save();
|
||||
this.ctx.beginPath();
|
||||
this.ctx.fillStyle = `rgba(${Math.floor(dot.ir)}, ${Math.floor(dot.ig)}, ${Math.floor(dot.ib)}, ${dot.ia})`;
|
||||
this.ctx.arc(this.warp.width / 2 + (dot.ix - this.warp.width / 2) * scale, this.warp.height / 2 + (dot.iy - this.warp.height / 2) * scale, this.radius * scale, 0, Math.PI * 2);
|
||||
this.ctx.fill();
|
||||
this.ctx.closePath();
|
||||
this.ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const canvasRef = useRef()
|
||||
|
||||
useEffect(() => {
|
||||
if (canvasRef && canvasRef.current) {
|
||||
new Particale({
|
||||
warp: canvasRef && canvasRef.current,
|
||||
imgsUrl: imgs,
|
||||
radius: 1,
|
||||
});
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<canvas ref={canvasRef} width="500px" height="500px"></canvas>
|
||||
)
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
import React, { useRef, useEffect } from 'react';
|
||||
|
||||
export default () => {
|
||||
const canvasRef = useRef()
|
||||
|
||||
async function init() {
|
||||
var snake = [41, 40], //snake队列表示蛇身,初始节点存在但不显示
|
||||
direction = 1, //1表示向右,-1表示向左,20表示向下,-20表示向上
|
||||
food = 43, //食物的位置
|
||||
n, //与下次移动的位置有关
|
||||
box = canvasRef.current && canvasRef.current.getContext('2d');
|
||||
//从0到399表示box里[0~19]*[0~19]的所有节点,每20px一个节点
|
||||
|
||||
function draw(seat, color) {
|
||||
box.fillStyle = color;
|
||||
box.fillRect(seat % 20 *20 + 1, ~~(seat / 20) * 20 + 1, 18, 18);
|
||||
//用color填充一个矩形,以前两个参数为x,y坐标,后两个参数为宽和高。
|
||||
}
|
||||
|
||||
document.onkeydown = function(evt) { //当键盘上下左右键摁下的时候改变direction
|
||||
direction = snake[1] - snake[0] == (n = [-1, -20, 1, 20][(evt || event).keyCode - 37] || direction) ? direction : n;
|
||||
console.log([-1, -20, 1, 20][(evt || event).keyCode - 37]);
|
||||
};
|
||||
|
||||
function _move() {
|
||||
snake.unshift(n = snake[0] + direction); //此时的n为下次蛇头出现的位置,n进入队列
|
||||
if(snake.indexOf(n, 1) > 0 || n < 0 || n > 399 || direction == 1 && n % 20 == 0 || direction == -1 && n % 20 == 19) {
|
||||
//if语句判断贪吃蛇是否撞到自己或者墙壁,碰到时返回,结束程序
|
||||
return alert("GAME OVER!");
|
||||
}
|
||||
draw(n, "lime"); //画出蛇头下次出现的位置
|
||||
if(n == food) { //如果吃到食物时,产生一个蛇身以外的随机的点,不会去掉蛇尾
|
||||
while (snake.indexOf(food = ~~(Math.random() * 400)) > 0);
|
||||
draw(food, "yellow");
|
||||
} else { //没有吃到食物时正常移动,蛇尾出队列
|
||||
draw(snake.pop(),"black");
|
||||
}
|
||||
setTimeout(() => _move(), 150); //每隔0.15秒执行函数一次,可以调节蛇的速度
|
||||
}
|
||||
|
||||
box && await _move()
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ background: '#000' }}>
|
||||
<button type="button" onClick={() => init()} >开始</button>
|
||||
<canvas ref={canvasRef} width="400" height="400" />
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,562 +0,0 @@
|
||||
---
|
||||
nav:
|
||||
title: FC
|
||||
path: /funny
|
||||
group:
|
||||
title: canvas
|
||||
order: 4
|
||||
path: /canvas
|
||||
---
|
||||
|
||||
# canvas
|
||||
|
||||
### 粒子背景
|
||||
|
||||
<code src="./demos/ParticleBG/index.jsx" ></code>
|
||||
|
||||
### 粒子图片
|
||||
|
||||
<code src="./demos/ParticleIMG/index.jsx" ></code>
|
||||
|
||||
### 贪吃蛇
|
||||
|
||||
<code src="./demos/Snake/index.jsx" ></code>
|
||||
|
||||
### 液体海报
|
||||
|
||||
<code src="./demos/LiquidPost/index.jsx" ></code>
|
||||
|
||||
### 大转盘(doing)
|
||||
|
||||
```jsx
|
||||
import React, { useRef, useEffect } from 'react';
|
||||
|
||||
class Global {
|
||||
constructor () {};
|
||||
|
||||
/**
|
||||
* 判断是否为 PC 端,若是则返回 true,否则返回 flase
|
||||
*/
|
||||
IsPC() {
|
||||
let userAgentInfo = navigator.userAgent,
|
||||
flag = true,
|
||||
Agents = ["Android", "iPhone","SymbianOS", "Windows Phone","iPad", "iPod"];
|
||||
|
||||
for (let v = 0; v < Agents.length; v++) {
|
||||
if (userAgentInfo.indexOf(Agents[v]) > 0) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
};
|
||||
|
||||
/**
|
||||
* 缓动函数,由快到慢
|
||||
* @param {Num} t 当前时间
|
||||
* @param {Num} b 初始值
|
||||
* @param {Num} c 变化值
|
||||
* @param {Num} d 持续时间
|
||||
*/
|
||||
easeOut(t, b, c, d) {
|
||||
if ((t /= d / 2) < 1) return c / 2 * t * t + b;
|
||||
return -c / 2 * ((--t) * (t - 2) - 1) + b;
|
||||
};
|
||||
|
||||
windowToCanvas(canvas, e) {
|
||||
let bbox = canvas.getBoundingClientRect(),
|
||||
x = this.IsPC() ? e.clientX || event.clientX : e.changedTouches[0].clientX,
|
||||
y = this.IsPC() ? e.clientY || event.clientY : e.changedTouches[0].clientY;
|
||||
|
||||
return {
|
||||
x: x - bbox.left,
|
||||
y: y - bbox.top
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 绘制自动换行的文本
|
||||
* @param {Obj} context
|
||||
* @param {Str} t 文本内容
|
||||
* @param {Num} x 坐标
|
||||
* @param {Num} y 坐标
|
||||
* @param {Num} w 文本限制宽度
|
||||
* @param {Num} lineHeight 行高
|
||||
*/
|
||||
drawText(context, t, x, y, w, lineHeight = 20){
|
||||
let chr = t.split(''),
|
||||
temp = '',
|
||||
row = [];
|
||||
|
||||
for (let a = 0; a < chr.length; a++){
|
||||
if ( context.measureText(temp).width < w ) {
|
||||
;
|
||||
}
|
||||
else{
|
||||
row.push(temp);
|
||||
temp = '';
|
||||
}
|
||||
temp += chr[a];
|
||||
};
|
||||
|
||||
row.push(temp);
|
||||
|
||||
for(let b = 0; b < row.length; b++){
|
||||
context.fillText(row[b], x, y + (b + 1) * lineHeight);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* 定义圆角矩形的方法
|
||||
* @param {Obj} context
|
||||
* @param {Num} cornerX
|
||||
* @param {Num} cornerY
|
||||
* @param {Num} width
|
||||
* @param {Num} height
|
||||
* @param {Num} cornerRadius
|
||||
*/
|
||||
roundedRect(context, cornerX, cornerY, width, height, cornerRadius) {
|
||||
if (width > 0) context.moveTo(cornerX + cornerRadius, cornerY);
|
||||
else context.moveTo(cornerX - cornerRadius, cornerY);
|
||||
|
||||
context.arcTo(cornerX + width, cornerY,
|
||||
cornerX + width, cornerY + height,
|
||||
cornerRadius);
|
||||
|
||||
context.arcTo(cornerX + width, cornerY + height,
|
||||
cornerX, cornerY + height,
|
||||
cornerRadius);
|
||||
|
||||
context.arcTo(cornerX, cornerY + height,
|
||||
cornerX, cornerY,
|
||||
cornerRadius);
|
||||
|
||||
if (width > 0) {
|
||||
context.arcTo(cornerX, cornerY,
|
||||
cornerX + cornerRadius, cornerY,
|
||||
cornerRadius);
|
||||
}
|
||||
else {
|
||||
context.arcTo(cornerX, cornerY,
|
||||
cornerX - cornerRadius, cornerY,
|
||||
cornerRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RouletteWheel extends Global{
|
||||
constructor(params) {
|
||||
super()
|
||||
this.width = params.width
|
||||
this.height = params.height
|
||||
|
||||
this.centerX = params.centerX
|
||||
this.centerY = params.centerY
|
||||
this.outsideRadius = params.outsideRadius
|
||||
|
||||
this.evenColor = params.evenColor
|
||||
this.oddColor = params.oddColor
|
||||
this.loseColor = params.odd
|
||||
this.textColor = params.textColor
|
||||
|
||||
this.awards = params.awards || []
|
||||
|
||||
this.startRadian = params.startRadian || 0
|
||||
this.duration = params.duration || 4000
|
||||
this.velocity = params.velocity || 10
|
||||
|
||||
// 回调函数
|
||||
this.finish = params.finish
|
||||
}
|
||||
|
||||
initCanvas() {
|
||||
let canvas = this.canvas
|
||||
canvas.width = this.width;
|
||||
canvas.height = this.height;
|
||||
let ctx = canvas.getContext('2d')
|
||||
|
||||
for (let i = 0; i < this.awards.length; i++) {
|
||||
// const award = awards[i]
|
||||
let _startR = this.startRadian + this.awardRadian * i
|
||||
let _endR = _startR + this.awardRadian
|
||||
|
||||
if (i % 2 === 0) ctx.fillStyle = "#FF6766"
|
||||
else ctx.fillStyle = "#FD5757"
|
||||
|
||||
ctx.beginPath(); //开始绘制路径
|
||||
ctx.moveTo(250, 250); //将当前位置移动到新的目标点
|
||||
ctx.arc(250, 250, this.radius, _startR, _endR);
|
||||
ctx.closePath(); //绘制路径
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
ctx.beginPath(); //开始绘制路径
|
||||
ctx.moveTo(250, 250); //将当前位置移动到新的目标点
|
||||
ctx.arc(250, 250, 250, Math.PI / 2, Math.PI);
|
||||
ctx.closePath(); //绘制路径
|
||||
ctx.fillStyle = "#ccc"; //填充背景颜色
|
||||
ctx.fill();
|
||||
ctx.beginPath(); //开始绘制路径
|
||||
ctx.moveTo(250, 250); //将当前位置移动到新的目标点
|
||||
ctx.arc(250, 250, 250, Math.PI, Math.PI * 1.5);
|
||||
ctx.closePath(); //绘制路径
|
||||
ctx.fillStyle = "#ddd"; //填充背景颜色
|
||||
ctx.fill();
|
||||
ctx.beginPath(); //开始绘制路径
|
||||
ctx.moveTo(250, 250); //将当前位置移动到新的目标点
|
||||
ctx.arc(250, 250, 250, Math.PI * 1.5, Math.PI * 2);
|
||||
ctx.closePath(); //绘制路径
|
||||
ctx.fillStyle = "#aaa"; //填充背景颜色
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const canvasRef = useRef()
|
||||
|
||||
useEffect(() => {
|
||||
let rw = new RouletteWheel({
|
||||
canvas: canvasRef.current,
|
||||
width: '500',
|
||||
height: '500',
|
||||
awards: [ // 转盘内的奖品个数以及内容
|
||||
'大保健', '话费10元', '话费20元', '话费30元', '保时捷911', '周大福土豪金项链',
|
||||
// 'iphone 20', '火星7日游'
|
||||
]
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<canvas ref={canvasRef} width="200" height="200" ></code>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 火焰
|
||||
|
||||
<code src="./demos/Fire/index.jsx" ></code>
|
||||
|
||||
### 星空
|
||||
|
||||
|
||||
```jsx
|
||||
import React, { useRef, useEffect } from 'react';
|
||||
|
||||
/**
|
||||
* 星空初始化
|
||||
*/
|
||||
class NightSky {
|
||||
constructor(opt) {
|
||||
this.opt = {
|
||||
width: 500,
|
||||
height: 500,
|
||||
num: 120,
|
||||
canvas: null,
|
||||
...opt
|
||||
}
|
||||
this.opt.canvas.width = this.opt.width
|
||||
this.opt.canvas.height = this.opt.height
|
||||
this.ctx = this.opt.canvas && this.opt.canvas.getContext('2d')
|
||||
this.opt.canvas.style.backgroundColor = '#000'
|
||||
this.starList = []
|
||||
this.draw = this.draw
|
||||
this.init()
|
||||
}
|
||||
|
||||
init() {
|
||||
this.drawStar()
|
||||
this.animate()
|
||||
}
|
||||
|
||||
drawStar() {
|
||||
let { width, height, num } = this.opt
|
||||
|
||||
for (let i = 0; i < num; i++) {
|
||||
this.starList[i] = new Star({
|
||||
maxRadius: 3,
|
||||
ctx: this.ctx,
|
||||
width,
|
||||
height
|
||||
})
|
||||
this.starList[i].draw()
|
||||
}
|
||||
}
|
||||
|
||||
animate() {
|
||||
let ctx = this.ctx
|
||||
let starList = this.starList
|
||||
let { width, height } = this.opt
|
||||
|
||||
function _move() {
|
||||
ctx.clearRect(0, 0, width, height)
|
||||
for (const i in starList) {
|
||||
starList[i].move()
|
||||
}
|
||||
window.requestAnimationFrame(_move)
|
||||
}
|
||||
|
||||
window.requestAnimationFrame(_move)
|
||||
}
|
||||
|
||||
draw(val) {
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
class Star {
|
||||
constructor(opt) {
|
||||
let { width, height, maxRadius = 2, ctx, speed = 0.5 } = opt
|
||||
this.x = Math.random() * width
|
||||
this.y = Math.random() * height
|
||||
this.height = height
|
||||
this.width = width
|
||||
this.speed = speed
|
||||
this.maxRadius = maxRadius
|
||||
this.ctx = ctx
|
||||
this.r = Math.random() * maxRadius
|
||||
var alpha = (Math.floor(Math.random() * 10) + 1) / 10
|
||||
this.color = `rgba(255, 255, 255, ${alpha})`
|
||||
}
|
||||
|
||||
draw() {
|
||||
this.ctx.fillStyle = this.color
|
||||
this.ctx.shadowBlur = this.r * 2
|
||||
this.ctx.beginPath()
|
||||
this.ctx.arc(this.x, this.y, this.r * Math.random(), 0, 2 * Math.PI, false)
|
||||
this.ctx.closePath()
|
||||
this.ctx.fill()
|
||||
}
|
||||
|
||||
move() {
|
||||
this.y -= this.speed
|
||||
if (this.y <= -10) {
|
||||
this.y = this.height + 10
|
||||
}
|
||||
this.draw()
|
||||
}
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const canvasRef = useRef()
|
||||
|
||||
useEffect(() => {
|
||||
let nightSky = new NightSky({
|
||||
canvas: canvasRef.current,
|
||||
width: 500,
|
||||
height: 300
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<canvas ref={canvasRef} width="200" height="200" ></code>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 移动(doing)
|
||||
|
||||
|
||||
```jsx
|
||||
import React, { useRef, useEffect } from 'react';
|
||||
|
||||
class Move {
|
||||
constructor(opt) {
|
||||
const option = {
|
||||
canvas: null,
|
||||
width: document.documentElement.clientWidth, // 宽度
|
||||
height: document.documentElement.clientHeight, // 高度
|
||||
bgColor: '#000',
|
||||
para: {
|
||||
num: 100,
|
||||
color: false, // 颜色 如果是false 则是随机渐变颜色
|
||||
r: 0.9, // 圆每次增加的半径
|
||||
o: 0.09, // 判断圆消失的条件,数值越大,消失的越快
|
||||
},
|
||||
...opt
|
||||
}
|
||||
const { canvas, width, height, bgColor } = option
|
||||
this.option = option
|
||||
this.round_arr = []
|
||||
this.ctx = canvas.getContext('2d')
|
||||
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
canvas.style.backgroundColor = bgColor
|
||||
|
||||
this.init(this)
|
||||
}
|
||||
|
||||
init(opt) {
|
||||
let tempSum = 0
|
||||
window.onmousemove = function (event) {
|
||||
|
||||
let mouseX = event.clientX;
|
||||
let mouseY = event.clientY;
|
||||
|
||||
if (tempSum < 5) {
|
||||
tempSum++
|
||||
} else {
|
||||
opt.round_arr.push({
|
||||
mouseX,
|
||||
mouseY,
|
||||
r: opt.option.para.r, // 设置半径每次增大的数值
|
||||
o: 1, // 判断圆消失的条件,数值越大,消失得越快
|
||||
})
|
||||
tempSum = 0
|
||||
opt.animate()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
animate() {
|
||||
let { para, width, height } = this.option
|
||||
let color = 0, color2
|
||||
let ctx = this.ctx
|
||||
let round_arr = this.round_arr
|
||||
|
||||
if (!para.color) {
|
||||
color += Math.random();
|
||||
color2 = 'hsl(' + color + ',100%,80%)';
|
||||
}
|
||||
|
||||
function _move() {
|
||||
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
|
||||
for (var i = 0; i < round_arr.length; i++) {
|
||||
|
||||
ctx.fillStyle = color2;
|
||||
ctx.beginPath();
|
||||
ctx.arc( round_arr[i].mouseX ,round_arr[i].mouseY, round_arr[i].r, 0, Math.PI * 2);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
round_arr[i].r += para.r;
|
||||
round_arr[i].o -= para.o;
|
||||
|
||||
if( round_arr[i].o <= 0){
|
||||
round_arr.splice(i,1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.requestAnimationFrame(_move);
|
||||
}
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const canvasRef = useRef()
|
||||
|
||||
useEffect(() => {
|
||||
let rw = new Move({
|
||||
canvas: canvasRef.current,
|
||||
width: 500,
|
||||
height: 300
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<canvas ref={canvasRef} width="200" height="200" ></code>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 棒棒糖
|
||||
|
||||
|
||||
```jsx
|
||||
import React, { useRef, useEffect } from 'react';
|
||||
|
||||
class Lollipop {
|
||||
constructor(opt) {
|
||||
this.opt = {
|
||||
canvas: null, // 画布
|
||||
width: document.documentElement.clientWidth, // 宽度
|
||||
height: document.documentElement.clientHeight, // 高度
|
||||
bgColor: '#000',
|
||||
...opt
|
||||
}
|
||||
this.ctx = this.opt.canvas.getContext('2d')
|
||||
|
||||
// 初始化画布
|
||||
this.opt.canvas.width = this.opt.width
|
||||
this.opt.canvas.height = this.opt.height
|
||||
this.opt.canvas.style.backgroundColor = this.opt.bgColor
|
||||
|
||||
this.render()
|
||||
}
|
||||
|
||||
render() {
|
||||
this._drawCircle(this.ctx)
|
||||
this._drawStick(this.ctx)
|
||||
this._drawHalfCircle(this.ctx)
|
||||
}
|
||||
|
||||
/**
|
||||
* 画圆
|
||||
* @param {*} ctx
|
||||
*/
|
||||
_drawCircle(ctx) {
|
||||
ctx.beginPath()
|
||||
ctx.arc(300, 300, 50, 0, Math.PI * 2, true)
|
||||
ctx.closePath()
|
||||
ctx.fillStyle = '#fff'
|
||||
ctx.shadowBlur = 15
|
||||
ctx.shadowColor = '#fff'
|
||||
ctx.fill()
|
||||
}
|
||||
|
||||
/**
|
||||
* 棍子
|
||||
* @param {*} ctx
|
||||
*/
|
||||
_drawStick(ctx) {
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(340, 340)
|
||||
ctx.lineTo(450, 450)
|
||||
ctx.lineWidth = 8
|
||||
ctx.lineCap = 'round'
|
||||
ctx.strokeStyle = '#fff'
|
||||
ctx.stroke()
|
||||
ctx.closePath()
|
||||
}
|
||||
|
||||
_drawHalfCircle(ctx) {
|
||||
ctx.beginPath()
|
||||
ctx.arc(300, 300, 30, 0, Math.PI * 0.6, false)
|
||||
ctx.shadowBlur = 5
|
||||
ctx.lineWidth = 5
|
||||
ctx.lineCap = 'round'
|
||||
ctx.strokeStyle = '#ccc'
|
||||
ctx.stroke()
|
||||
}
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const canvasRef = useRef()
|
||||
|
||||
useEffect(() => {
|
||||
new Lollipop({
|
||||
canvas: canvasRef.current,
|
||||
width: 500,
|
||||
height: 800
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<canvas ref={canvasRef} width="200" height="200" ></code>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 时钟
|
||||
|
||||
<code src="./demos/Clock/index.jsx" ></code>
|
@ -1,106 +0,0 @@
|
||||
@property --rotate {
|
||||
syntax: "<angle>";
|
||||
initial-value: 132deg;
|
||||
inherits: false;
|
||||
}
|
||||
|
||||
.cont {
|
||||
position: relative;
|
||||
min-height: 400px;
|
||||
height: 500px;
|
||||
background: #212534;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
box-sizing: border-box;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #191c29;
|
||||
width: 200px;
|
||||
height: 300px;
|
||||
padding: 3px;
|
||||
position: relative;
|
||||
border-radius: 6px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
font-size: 1.5em;
|
||||
cursor: pointer;
|
||||
font-family: cursive;
|
||||
&_heart {
|
||||
font-size: 150px;
|
||||
color: #e00;
|
||||
animation: beat .25s infinite alternate;
|
||||
transform-origin: center;
|
||||
}
|
||||
:global :local{
|
||||
/* Heart beat animation */
|
||||
@keyframes beat {
|
||||
to { transform: scale(1.4); }
|
||||
}
|
||||
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
color: rgb(88 199 250 / 100%);
|
||||
transition: color 1s;
|
||||
}
|
||||
.card:hover:before, .card:hover:after {
|
||||
animation: none;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
||||
.card::before{
|
||||
content: "";
|
||||
width: 104%;
|
||||
height: 102%;
|
||||
border-radius: 8px;
|
||||
background-image: linear-gradient(
|
||||
var(--rotate)
|
||||
, #5ddcff, #3c67e3 43%, #4e00c2);
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
top: -1%;
|
||||
left: -2%;
|
||||
animation: spin 2.5s linear infinite;
|
||||
}
|
||||
|
||||
.card::after {
|
||||
position: absolute;
|
||||
content: "";
|
||||
top: 20px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: -1;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
transform: scale(0.8);
|
||||
filter: blur(30px);
|
||||
background-image: linear-gradient(
|
||||
var(--rotate)
|
||||
, #5ddcff, #3c67e3 43%, #4e00c2);
|
||||
opacity: 1;
|
||||
transition: opacity .5s;
|
||||
animation: spin 2.5s linear infinite;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,13 +0,0 @@
|
||||
import './index.less';
|
||||
|
||||
|
||||
export default function () {
|
||||
return (
|
||||
<div className="cont">
|
||||
<div className="card">
|
||||
{/* <div className={styles.card_heart}>♥</div> */}
|
||||
{/* <h1 className={styles.card_title}>hello! motherfucker!</h1> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
|
||||
.textMask {
|
||||
position: relative;
|
||||
height: 300px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
.bg {
|
||||
height: 300px;
|
||||
width: 100%;
|
||||
background-image: url('https://images4.alphacoders.com/284/284838.jpg');
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
transform: rotateY(180deg);
|
||||
transition: all 2.5s ease-in-out;
|
||||
}
|
||||
.text {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
background-image: url('https://images4.alphacoders.com/284/284838.jpg');
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
font-size: 50px;
|
||||
color: transparent;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
line-height: 200px;
|
||||
transform: translate(-50%, -50%);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
transition: all 2.5s ease-in-out;
|
||||
}
|
||||
&:hover {
|
||||
.text {
|
||||
background-size: 80% 80%;
|
||||
}
|
||||
.bg {
|
||||
background-size: 150% 150%;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
export default (): any => {
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="demo textMask">
|
||||
<div className="bg"></div>
|
||||
<div className="text">
|
||||
Text Mask
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
.box {
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: #ccc;
|
||||
}
|
||||
.ball {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
position: absolute;
|
||||
background: red;
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
export default (): any => {
|
||||
const ballRef = useRef(null)
|
||||
|
||||
function fun(v) {
|
||||
let Vx = Math.random()*v;
|
||||
let Vy = Math.sqrt(v*v - Vx*Vx);
|
||||
let startX = Math.random()*490;
|
||||
let startY = Math.random()*490;
|
||||
const ball = ballRef.current;
|
||||
Math.random() > 0.5 && (Vx *= -1);
|
||||
Math.random() > 0.5 && (Vy *= -1);
|
||||
ball.style.left = startX + 'px';
|
||||
ball.style.top = startY + 'px';
|
||||
function animate(){
|
||||
if(startX >= 490 || startX <= 0)
|
||||
Vx = -Vx;
|
||||
startX += Vx;
|
||||
if(startY >= 490 || startY <= 0)
|
||||
Vy = -Vy;
|
||||
startY += Vy;
|
||||
ball.style.left = startX + 'px';
|
||||
ball.style.top = startY + 'px';
|
||||
window.requestAnimationFrame(animate);
|
||||
}
|
||||
window.requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="box">
|
||||
<button onClick={() => fun(5)} type="button">开始</button>
|
||||
<div className="ball" ref={ballRef}></div>
|
||||
</div>
|
||||
)
|
||||
}
|
Before Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 684 KiB |
Before Width: | Height: | Size: 1.9 MiB |
@ -1,157 +0,0 @@
|
||||
@keyframes ani {
|
||||
from {
|
||||
mask-position: 0 0;
|
||||
}
|
||||
to {
|
||||
mask-position: 100% 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ani2 {
|
||||
from {
|
||||
mask-position: 100% 0;
|
||||
}
|
||||
to {
|
||||
mask-position: 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.buttonMask {
|
||||
button {
|
||||
width: 101%;
|
||||
height: 100%;
|
||||
font-family: 'Righteous', cursive;
|
||||
font-weight: 300;
|
||||
font-size: 20px;
|
||||
letter-spacing: 1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.mas {
|
||||
margin-top: 12px;
|
||||
position: absolute;
|
||||
color: #000;
|
||||
text-align: center;
|
||||
width: 101%;
|
||||
font-family: 'Righteous' sans-serif;
|
||||
font-weight: 300;
|
||||
font-size: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.btn {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 6vh;
|
||||
overflow: hidden;
|
||||
border: 1px solid ;
|
||||
font-family: 'Righteous' sans-serif;
|
||||
font-weight: 300;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
transition: .5s;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
.button-container-1 {
|
||||
button {
|
||||
background: #000;
|
||||
mask: url('./img/button1.png');
|
||||
mask-size: 2300% 100%;
|
||||
border: none;
|
||||
color: #fff;
|
||||
-webkit-animation: ani2 .7s steps(22) forwards;
|
||||
animation: ani2 .7s steps(22) forwards;
|
||||
|
||||
&:hover {
|
||||
-webkit-animation: ani .7s steps(22) forwards;
|
||||
animation: ani .7s steps(22) forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
.button-container-2 {
|
||||
button {
|
||||
background: #000;
|
||||
mask: url('./img/button2.png');
|
||||
mask-size: 3000% 100%;
|
||||
border: none;
|
||||
color: #fff;
|
||||
-webkit-animation: ani2 .7s steps(29) forwards;
|
||||
animation: ani2 .7s steps(29) forwards;
|
||||
|
||||
&:hover {
|
||||
-webkit-animation: ani .7s steps(29) forwards;
|
||||
animation: ani .7s steps(29) forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
.button-container-3 {
|
||||
button {
|
||||
background: #000;
|
||||
mask: url('./img/button3.png');
|
||||
mask-size: 7100% 100%;
|
||||
border: none;
|
||||
color: #fff;
|
||||
-webkit-animation: ani2 0.7s steps(70) forwards;
|
||||
animation: ani2 0.7s steps(70) forwards;
|
||||
|
||||
&:hover {
|
||||
-webkit-animation: ani 0.7s steps(70) forwards;
|
||||
animation: ani 0.7s steps(70) forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
.button-container-4 {
|
||||
position: relative;
|
||||
height: 45px;
|
||||
width: 200px;
|
||||
background: #fff;
|
||||
color: #6cf;
|
||||
text-align: center;
|
||||
line-height: 45px;
|
||||
-webkit-box-sizing:border-box;
|
||||
box-sizing:border-box;
|
||||
margin: 40px auto;
|
||||
border: 1px solid #ccc;
|
||||
cursor: pointer;
|
||||
}
|
||||
.button-container-4::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 1px;
|
||||
right: -2px;
|
||||
top: -2px;
|
||||
background-color: #6cf;
|
||||
z-index: -1;
|
||||
transition: width .4s linear, height .4s linear;
|
||||
}
|
||||
.button-container-4::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 1px;
|
||||
left: -2px;
|
||||
bottom: -2px;
|
||||
background-color: #6cf;
|
||||
z-index: -1;
|
||||
transition: width .4s linear, height .4s linear;
|
||||
}
|
||||
.button-container-4:hover {
|
||||
&::before {
|
||||
content: "";
|
||||
transition: width .4s linear, height .4s linear;
|
||||
width: 201px;
|
||||
height: 46px;
|
||||
}
|
||||
&::after {
|
||||
content: "";
|
||||
transition: width .4s linear, height .4s linear;
|
||||
width: 201px;
|
||||
height: 46px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
export default (): any => {
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="buttonMask">
|
||||
<div className="btn button-container-1">
|
||||
<span className="mas">MASK1</span>
|
||||
<button type="button" name="Hover">MASK1</button>
|
||||
</div>
|
||||
<div className="btn button-container-2">
|
||||
<span className="mas">MASK2</span>
|
||||
<button type="button" name="Hover">MASK2</button>
|
||||
</div>
|
||||
<div className="btn button-container-3">
|
||||
<span className="mas">MASK2</span>
|
||||
<button type="button" name="Hover">MASK3</button>
|
||||
</div>
|
||||
<div className="button-container-4">
|
||||
描边动画
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
Before Width: | Height: | Size: 329 KiB |
@ -1,47 +0,0 @@
|
||||
.svgMask {
|
||||
position: relative;
|
||||
.rang {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 250px;
|
||||
z-index: 10;
|
||||
svg {
|
||||
width: 100%;
|
||||
height: inherit;
|
||||
text {
|
||||
text-anchor: middle;
|
||||
}
|
||||
.svgDemo {
|
||||
&_rect {
|
||||
fill: darken( #fff, 60%);
|
||||
}
|
||||
&_tit {
|
||||
letter-spacing: -2px;
|
||||
font-size: 6em;
|
||||
font-weight: 800;
|
||||
}
|
||||
&_subtit {
|
||||
letter-spacing: 8px;
|
||||
font-size: 1.2em;
|
||||
font-weight: 300;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
.down {
|
||||
fill: #000;
|
||||
mask: url(#svgDemo)
|
||||
}
|
||||
}
|
||||
}
|
||||
.intro {
|
||||
position: relative;
|
||||
background: url('./img/amazon_view.jpg');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
export default (): any => {
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div class="svgMask">
|
||||
<div class="rang">
|
||||
<svg>
|
||||
<defs>
|
||||
<mask id="svgDemo" class="svgDemo" width="100%" heigth="100%" x="0" y="0">
|
||||
<rect class="svgDemo_rect" x="0" y="0" width="100%" height="100%" />
|
||||
|
||||
<text class="svgDemo_tit" x="50%" y="0" dy="1.58em">SVG + CSS</text>
|
||||
<text class="svgDemo_subtit" x="50%" y="0" dy="9.8em">welcome!</text>
|
||||
</mask>
|
||||
</defs>
|
||||
<rect class="down" x="0" y="0" width="100%" height="100%" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="intro">嗨,你好吗?</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="45px" height="26px" viewBox="0 0 45 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Group</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="block/navigation_primary_white" transform="translate(-165.000000, -12.000000)" fill="#303233">
|
||||
<g id="Group">
|
||||
<g transform="translate(165.000000, 12.000000)">
|
||||
<g id="systemicon/black/djilogo">
|
||||
<path d="M17.9822999,14.0172253 L21.3322723,0 L28.6674466,0 L24.8560701,15.9459198 C24.1224248,19.0236511 21.8345765,19.7624088 19.7179972,19.7624088 L2.81348162,19.7624088 C0.951249717,19.7624088 -0.609344073,18.9712479 0.235498266,15.4180531 L1.75902636,9.05809025 C2.52845917,5.83081808 4.92750466,5.09206033 6.6619238,5.09206033 L18.464154,5.09206033 L17.5119489,9.06831527 L11.4868555,9.06831527 C10.6023912,9.06831527 10.1167027,9.26131253 9.87002406,10.2927615 L8.89609083,14.354651 C8.54971825,15.8117164 9.05969116,15.9114104 10.1243714,15.9114104 L15.6458826,15.9114104 C16.6568816,15.9114104 17.5451803,15.8487821 17.9822999,14.0172253 Z M37.8744387,5.0897597 L45,5.0897597 L41.5477774,19.7626645 L34.422216,19.7626645 L37.8744387,5.0897597 Z M29.1385644,5.0897597 L36.2641257,5.0897597 L32.9461065,18.8807564 C31.5618943,24.6604494 27.6955583,25.9973709 25.077953,25.9973709 L15.0817171,25.9973709 L16.2767664,21.0254545 C16.2767664,21.0254545 21.5937772,21.0510171 21.7829401,21.0280108 C23.684794,20.869523 25.5777009,19.9441586 26.2333804,17.1974624 L29.1385644,5.0897597 Z" id="LOGO"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.9 KiB |
@ -1,51 +0,0 @@
|
||||
|
||||
@keyframes move {
|
||||
0% {
|
||||
background-position: 0 0;
|
||||
}
|
||||
50% {
|
||||
background-position: 100% 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.realMask {
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
z-index: 1;
|
||||
height: 500px;
|
||||
overflow: hidden;
|
||||
&_bg {
|
||||
background-image: url('https://sp-webfront.skypixel.com/skypixel/v2/public/website/assets/1535027674204-f6eca6369ec03e70262b58b0e25cda7b.jpg');
|
||||
background-size: cover;
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
left: -20px;
|
||||
right: -20px;
|
||||
bottom: -20px;
|
||||
filter: blur(15px);
|
||||
z-index: -1;
|
||||
}
|
||||
&_mask {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 200px;
|
||||
height: 80px;
|
||||
animation: move 88s infinite;
|
||||
background-image: url(https://sp-webfront.skypixel.com/skypixel/v2/public/website/assets/1535027674204-f6eca6369ec03e70262b58b0e25cda7b.jpg);
|
||||
background-size: cover;
|
||||
mask-image: url('./img/dji.svg');
|
||||
mask-size: cover;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
&_slogan {
|
||||
color: white;
|
||||
margin-top: 24px;
|
||||
font-size: 36px;
|
||||
font-weight: 300;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
export default (): any => {
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="realMask">
|
||||
<div className="realMask_bg"></div>
|
||||
<div className="realMask_mask"></div>
|
||||
<div className="realMask_slogan">NiceNote</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
|
||||
@keyframes Gradient {
|
||||
0%{background-position:50% 0%}
|
||||
50%{background-position:50% 100%}
|
||||
100%{background-position:50% 0%}
|
||||
}
|
||||
|
||||
.gradientMask {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
font-size: 50px;
|
||||
letter-spacing: 1px;
|
||||
font-weight: bold;
|
||||
background: linear-gradient(0deg, #e55d87, #5fc3e4);
|
||||
background-size: 400% 400%;
|
||||
animation: Gradient 4s linear infinite;
|
||||
svg {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
text {
|
||||
text-anchor: middle;
|
||||
}
|
||||
svg mask rect {
|
||||
fill: #eee;
|
||||
}
|
||||
svg > rect {
|
||||
fill: #eee;
|
||||
mask: url(#gradientMask_svg__mask);
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
export default (): any => {
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="gradientMask">
|
||||
<svg
|
||||
className="gradientMask_svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="100%"
|
||||
height="100%"
|
||||
>
|
||||
<defs>
|
||||
<mask id="gradientMask_svg__mask" x="0" y="0" width="100%" height="100%">
|
||||
<rect x="0" y="0" width="100%" height="100%" />
|
||||
<text x="50%" y="1em">Hello</text>
|
||||
<text x="50%" y="2em">Motal</text>
|
||||
</mask>
|
||||
</defs>
|
||||
<rect x="0" y="0" width="100%" height="100%" />
|
||||
</svg>
|
||||
</div>
|
||||
)
|
||||
}
|
Before Width: | Height: | Size: 329 KiB |
@ -1,47 +0,0 @@
|
||||
.svgBgMask {
|
||||
position: relative;
|
||||
font-weight: 700;
|
||||
h1, h2 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.picture {
|
||||
img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
will-change: transform;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
z-index: -1;
|
||||
}
|
||||
svg {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.article {
|
||||
padding-top: 100px;
|
||||
background-color: #222;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
h1 {
|
||||
margin: 0;
|
||||
letter-spacing: 3pt;
|
||||
font-weight: 300;
|
||||
font-size: 50px;
|
||||
}
|
||||
ul {
|
||||
margin-top: 100px;
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 60px 100px;
|
||||
h2 {
|
||||
margin-top: 35px;
|
||||
font-size: 1.1em;
|
||||
font-weight: 300;
|
||||
color: #888;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
const img = require('./img/amazon_view.jpg')
|
||||
|
||||
export default (): any => {
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="svgBgMask">
|
||||
<div className="picture">
|
||||
<img src={img} alt="" />
|
||||
<svg width="100%" height="1280">
|
||||
<defs>
|
||||
<linearGradient id="gradient" gradientTransform="rotate(76)">
|
||||
<stop offset="18%" stop-color="#1a237e" />
|
||||
<stop offset="80%" stop-color="#00e5ff" />
|
||||
</linearGradient>
|
||||
<mask id="mask">
|
||||
<rect width="100%" height="100%" fill="#fff" />
|
||||
<text x="10%" y="25%" font-size="50px" font-weight="300">hello</text>
|
||||
<text x="10%" y="50%" font-size="100px" letter-spacing="8">My Friend</text>
|
||||
</mask>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="url(#gradient)" fill-opacity="0.8" mask="url(#mask)" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="article">
|
||||
<h1>You Are The Best</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<img src="https://s.cdpn.io/387787/scalable.svg" alt="" width="60" height="60" />
|
||||
<h2>bread</h2>
|
||||
</li>
|
||||
<li>
|
||||
<img src="https://s.cdpn.io/387787/customizable.svg" alt="" width="60" height="60" />
|
||||
<h2>hand</h2>
|
||||
</li>
|
||||
<li>
|
||||
<img src="https://s.cdpn.io/387787/accessible.svg" alt="" width="60" height="60" />
|
||||
<h2>heart</h2>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
|
||||
@keyframes typing {
|
||||
from { width: 0; }
|
||||
}
|
||||
|
||||
@keyframes blink-caret {
|
||||
50% {
|
||||
border-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.cssPrint {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: black;
|
||||
&_h1 {
|
||||
display: inline-block;
|
||||
color: lime;
|
||||
font: bold 200% Consolas;
|
||||
/*font: bold 200% "Source Code Pro";*/
|
||||
/*必须使用等宽字体*/
|
||||
border-right: .1em solid currentColor;
|
||||
width: 28ch;
|
||||
margin: 2em 1em;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
animation: typing 3s steps(20, end),
|
||||
blink-caret .5s step-end infinite alternate;
|
||||
/*step-end每个关键帧在end处跳转,infinite无限循环播放,alternate来回播放,normal顺序播放*/
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
export default (): any => {
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="cssPrint">
|
||||
<h1 className="cssPrint_h1">
|
||||
This is Nice Note WebSite By Json!
|
||||
</h1>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
|
||||
.ribbon {
|
||||
display:inline-block;
|
||||
height: 300px;
|
||||
background-color: #000;
|
||||
&::before, &::after {
|
||||
margin-top:.5em;
|
||||
content: "";
|
||||
float:left;
|
||||
border:1.5em solid #fff;
|
||||
}
|
||||
&::before {
|
||||
border-left-color: transparent;
|
||||
}
|
||||
&::after {
|
||||
border-right-color: transparent;
|
||||
}
|
||||
a {
|
||||
float: left;
|
||||
height: 3.5em;
|
||||
color: #000;
|
||||
text-decoration:none;
|
||||
overflow: hidden;
|
||||
&:hover span {
|
||||
margin-top: 0;
|
||||
background-color: #FFD204;
|
||||
}
|
||||
}
|
||||
span {
|
||||
position: relative;
|
||||
background: #fff;
|
||||
display: inline-block;
|
||||
line-height: 3em;
|
||||
margin-top: .5em;
|
||||
padding: 0 1em;
|
||||
transition: background .2s, margin-top .2s;
|
||||
&:before {
|
||||
content: "";
|
||||
position:absolute;
|
||||
top:3em;
|
||||
left:0;
|
||||
border-right:0.5em solid #9B8651;
|
||||
border-bottom:0.5em solid #fff;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
export default (): any => {
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className='ribbon'>
|
||||
<a href='#'><span>首页</span></a>
|
||||
<a href='#'><span>关于我</span></a>
|
||||
<a href='#'><span>服务</span></a>
|
||||
<a href='#'><span>介绍</span></a>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
.wraper {
|
||||
width: 260px;
|
||||
height: 260px;
|
||||
margin: 128px auto;
|
||||
perspective: 1000px;
|
||||
}
|
||||
|
||||
.cube {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
transform-style: preserve-3d;
|
||||
/*transform: rotateX(-30deg) rotateY(-45deg);*/
|
||||
animation: spin 5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.cube>div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: rgba(0, 0, 0, .8);
|
||||
text-align: center;
|
||||
line-height: 260px;
|
||||
color: #fff;
|
||||
font-size: 48px;
|
||||
border: 2px solid #fff;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.front {
|
||||
transform: translateZ(130px);
|
||||
}
|
||||
|
||||
.end {
|
||||
transform: rotateY(180deg) translateZ(130px);
|
||||
}
|
||||
|
||||
.top {
|
||||
transform: rotateX(90deg) translateZ(130px);
|
||||
}
|
||||
|
||||
.bottom {
|
||||
transform: rotateX(-90deg) translateZ(130px);
|
||||
}
|
||||
|
||||
.left {
|
||||
transform: rotateY(-90deg) translateZ(130px);
|
||||
}
|
||||
|
||||
.right {
|
||||
transform: rotateY(90deg) translateZ(130px);
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
export default (): any => {
|
||||
|
||||
/**
|
||||
* 手动控制动画
|
||||
*/
|
||||
function init() {
|
||||
setTimeout(function () {
|
||||
var cube = document.querySelector(".cube"),
|
||||
downX, downY, moveX, moveY, tempX, tempY, degX = 0, degY = 0;
|
||||
|
||||
window.onmousedown = function (e) {
|
||||
e = e || event;
|
||||
downX = e.clientX; //获取鼠标点下去时的坐标
|
||||
downY = e.clientY;
|
||||
console.log('can');
|
||||
|
||||
window.onmousemove = function (e) {
|
||||
e = e || event;
|
||||
moveX = e.clientX - downX; //算出鼠标移动的距离
|
||||
moveY = e.clientY - downY;
|
||||
//根据一定比例将变化反应在盒子上,改变比例5可以调节拖动的速度
|
||||
tempX = degX + moveX / 5;
|
||||
tempY = degY - moveY / 5;
|
||||
cube.style.transform = "rotatex(" + tempY + "deg) rotatey(" + tempX + "deg)";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
window.onmouseup = function (e) {
|
||||
e = e || event;
|
||||
degX += moveX / 5; //鼠标松开时将拖动期间改变的最终结果保存
|
||||
degY += - moveY / 5;
|
||||
window.onmousemove = null; //取消监听
|
||||
};
|
||||
|
||||
// !function () {
|
||||
// var n = 1000;
|
||||
// var wraper = document.querySelector('.wraper');
|
||||
// wraper.style.perspective = n + 'px';
|
||||
// window.onmousewheel = function (e) {
|
||||
// e = e || event;
|
||||
// if (e.wheelDelta) { //判断浏览器IE,谷歌滑轮事件
|
||||
// if (e.wheelDelta > 0) { //当滑轮向上滚动时减小景深
|
||||
// wraper.style.perspective = n - 50 + 'px';
|
||||
// if (n > 350) {
|
||||
// n = n - 50;
|
||||
// }
|
||||
// }
|
||||
// if (e.wheelDelta < 0) { //当滑轮向下滚动时增加景深
|
||||
// wraper.style.perspective = n + 50 + 'px';
|
||||
// n += 50;
|
||||
// }
|
||||
// } else if (e.detail) { //Firefox滑轮事件
|
||||
// if (e.detail > 0) {
|
||||
// wraper.style.perspective = n - 50 + 'px';
|
||||
// if (n > 350) {
|
||||
// n = n - 50;
|
||||
// }
|
||||
// }
|
||||
// if (e.detail < 0) {
|
||||
// wraper.style.perspective = n + 50 + 'px';
|
||||
// n += 50;
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// }();
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="wraper">
|
||||
<div className="cube">
|
||||
<div className="front">Front</div>
|
||||
<div className="end">End</div>
|
||||
<div className="left">Left</div>
|
||||
<div className="right">Right</div>
|
||||
<div className="top">Top</div>
|
||||
<div className="bottom">Bottom</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
---
|
||||
nav:
|
||||
title: FC
|
||||
path: /funny
|
||||
group:
|
||||
title: css
|
||||
order: 3
|
||||
path: /css
|
||||
---
|
||||
|
||||
# css
|
||||
|
||||
|
||||
### 心跳卡片
|
||||
|
||||
<a href="https://codepen.io/gayane-gasparyan/pen/jOmaBQK">参考</a>
|
||||
<code src="./demos/HeartBeat/index.tsx" ></code>
|
||||
|
||||
### 小球动画
|
||||
|
||||
<code src="./demos/demo10/index.tsx" ></code>
|
||||
|
||||
### 3D 方块
|
||||
|
||||
<code src="./demos/demo9/index.tsx" ></code>
|
||||
|
||||
### 3D 导航条
|
||||
|
||||
<code src="./demos/demo8/index.tsx" ></code>
|
||||
|
||||
### 键盘打字效果
|
||||
|
||||
<code src="./demos/demo7/index.tsx" ></code>
|
||||
|
||||
### 镂空文字背景
|
||||
|
||||
<code src="./demos/demo1/index.tsx" ></code>
|
||||
|
||||
### 按钮合集
|
||||
|
||||
<code src="./demos/demo2/index.tsx" ></code>
|
||||
|
||||
### Svg 蒙版
|
||||
|
||||
<code src="./demos/demo3/index.tsx" ></code>
|
||||
|
||||
### 毛玻璃蒙版
|
||||
|
||||
<code src="./demos/demo4/index.tsx" ></code>
|
||||
|
||||
### 渐变文字
|
||||
|
||||
<code src="./demos/demo5/index.tsx" ></code>
|
||||
|
||||
### 渐变文字
|
||||
|
||||
<code src="./demos/demo6/index.tsx" ></code>
|
36
src/index.md
@ -1,36 +0,0 @@
|
||||
---
|
||||
nav:
|
||||
title: FC
|
||||
path: /funny
|
||||
group:
|
||||
title: 说明
|
||||
order: 4
|
||||
path: /code
|
||||
---
|
||||
|
||||
# 说明
|
||||
|
||||
funny code 的缩写,就是记录一些有意思的酷炫 code
|
||||
|
||||
## 迪士尼动画12原则
|
||||
|
||||
1. 挤压与拉伸
|
||||
2. 预备动作
|
||||
3. 表情与呈像方式
|
||||
4. 逐帧画法与关键帧画法
|
||||
5. 动作的惯性跟随和重叠
|
||||
6. 慢入与慢出
|
||||
7. 弧形运动轨迹
|
||||
8. 次要动作
|
||||
9. 节奏
|
||||
10. 夸张
|
||||
11. 熟练的手绘技法
|
||||
12. 吸引力
|
||||
|
||||
## 提升页面性能技巧
|
||||
|
||||
页面渲染顺序:js - css - layout(重排) - paint(重绘) - composite
|
||||
|
||||
* translate 替换为 left\top\right\bottom
|
||||
* scale 替换为 width\height
|
||||
* opacity 替换为 display\visibility
|