FixedForwardRef#
import React, { forwardRef } from " react";
// ジェネリックコンポーネントで動作する型を宣言
type FixedForwardRef = <T, P= {}>(
render: (props: P, ref: React.Ref<T>)=> React.ReactNode
)=> (props: P & React.RefAttributes<T>)=> React.ReactNode;
// 古い forwardRef を新しいものにキャスト
export const fixedForwardRef = forwardRef as FixedForwardRef;
## グラデーションボーダーの tailwind 実装
```tsx
export const AnimatedGradientBorderTW: React.FC<{
children: React.ReactNode
}> = ({ children }) => {
const boxRef = useRef<HTMLDivElement>(null)
useEffect(() => {
const boxElement = boxRef.current
if (!boxElement) {
return
}
const updateAnimation = () => {
const angle = (parseFloat(boxElement.style.getPropertyValue('--angle')) + 0.5) % 360
boxElement.style.setProperty('--angle', `${angle}deg`)
requestAnimationFrame(updateAnimation)
}
requestAnimationFrame(updateAnimation)
}, [])
return (
<div
ref={boxRef}
style={
{
'--angle': '0deg',
'--border-color': 'linear-gradient(var(--angle), #070707, #687aff)',
'--bg-color': 'linear-gradient(#131219, #131219)',
} as CSSProperties
}
className="flex h-[400px] w-[400px] items-center justify-center rounded-lg border-2 border-[#0000] p-3 [background:padding-box_var(--bg-color),border-box_var(--border-color)]"
>
{children}
</div>
)
}
iOS H5 history.back () で前のルートに戻る際のページ白画面問題#
history.scrollRestoration を変更
history.back で前のページに戻るとき、ブラウザはページのスクロール位置を記録しますが、iOS ではスクロール後に戻るとページのレンダリングに問題が発生し、白画面になります。scrollRestoration 属性を利用できます。デフォルトは auto で、スクロール位置を記録します(これは H5 で追加された属性なので、ブラウザがサポートしているかを判断する必要があります。私の実践ではほとんどのモバイル端末に対応できます)。
if ('scrollRestoration' in history) {
history.scrollRestoration = 'manual' // manual に変更すると、スクロール位置は記録されません
}
Vite の ws 転送設定#
スクリーンのズーム比が変わったときのページの処理方法#
- ホームページの最初のモジュールのすべての 100vh を動的に calc(100vh * 2)に変更する必要があります。
- 動画の幅は 100% に調整する必要があります(動画の動きがなくなります)。
- ログインモーダルの内部のロジックをズーム処理に調整します。
- 問題のある動作モジュールは直接表示しないことにします。
- さらに、URS モーダルの CSS を注入して、Win と Mac を区別できます。
antd-mobile CSS 変数の上書き#
:root:root {
--adm-button-border-radius: 2px;
}
nginx の一般的なパスプロキシ設定#
location /docs/zh {
proxy_pass https://your.domain.com/zh/;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
nginx ネットワークセグメント禁止設定#
server {
listen 80;
server_name domain1.com www.domain1.com;
access_log logs/domain1.access.log main;
root html;
deny 61.135.0.0/16;
}
nginx-openresty ログ位置の確認#
Canvas ツール関数#
// 画像のサイズを調整
function imageUrl2ExactCanvas(image: HTMLImageElement, imageSize: LimitImageSize) {
const cvs = document.createElement('canvas')
const ctx = cvs.getContext('2d')
const width = imageSize[0]
const height = imageSize[1]
cvs.width = width
cvs.height = height
ctx!.drawImage(image, 0, 0, cvs.width, cvs.height)
image2white(ctx!, width, height)
return cvs
}
// 画像の透明部分を白に変換
function image2white(ctx: CanvasRenderingContext2D, width: number, height: number) {
let imageData = ctx!.getImageData(0, 0, width, height)
for (let i = 0; i < imageData.data.length; i += 4) {
// そのピクセルが透明な場合、白に設定
if (imageData.data[i + 3] === 0) {
imageData.data[i] = 255
imageData.data[i + 1] = 255
imageData.data[i + 2] = 255
imageData.data[i + 3] = 255
}
}
ctx!.putImageData(imageData, 0, 0)
}
/**
* @param image 画像
* @param backType 戻り値のタイプ blob, file
* @param quality 画像圧縮比 0-1, 数字が小さいほど画像圧縮が小さくなる
* @returns
*/
function compressorImage(image: File, backType?: 'blob' | 'file', quality?: number) {
return new Promise((resolve, reject) => {
new Compressor(image, {
quality: quality || 0.8,
success(result) {
let file = new File([result], image.name, { type: image.type })
if (!backType || backType === 'blob') {
resolve(result)
} else if (backType === 'file') {
resolve(file)
} else {
resolve(file)
}
},
error(err) {
reject(err)
},
})
})
}
nginx の正規表現リバースプロキシ設定#
resolver 8.8.8.8;
location ~ /xx/([0-9a-z]+).html {
proxy_pass http://your.domain/xx/$1/
}
FFmpeg スクリプト#
ffmpeg -i video.mp4 -i audio.mp4 -c:v copy -c:a aac -strict experimental output.mp4
webpack4 に強力なローカルキャッシュを追加#
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
plugins: [
new HardSourceWebpackPlugin({
cacheDirectory: path.resolve(__dirname, '../cache'),
}),
]
nextjs でプロジェクト外の .ts, .tsx ファイルのコンパイルをサポート#
const nextConfig = {
webpack: (config, options) => {
config.module.rules.forEach((rule) => {
if (rule.test && rule.test.toString().includes('tsx|ts')) {
rule.include = [...rule.include, path.resolve(__dirname, '../common-package/src')]
}
if (Array.isArray(rule.oneOf)) {
rule.oneOf.forEach((rule_inner) => {
if (rule_inner.test && rule_inner.test.toString().includes('tsx|ts')) {
rule_inner.include = [
...rule_inner.include,
path.resolve(__dirname, '../common-package/src'),
]
}
})
}
})
return config
},
}
H5 の使用テクニック#
// 1、カメラをキャッチ、user は前面カメラ、environment は背面カメラを示します
<input type="file" capture="user" accept="image/*" />
// 2、10 秒ごとにリフレッシュ
<meta http-equiv="refresh" content="10" />
// 3、input 入力ボックスのスペルチェックを有効にする
<input type="text" spellcheck="true" lang="en" />
// 4、ファイルをアップロードする際に許可されるファイル形式を指定
<input type="file" accept=".jpeg,.png" />
// 5、ブラウザの翻訳を防ぐ、ロゴやブランド名などのシーンに適用
<p translate="no">ブランド名</p>
// 6、複数のファイルを選択できるようにする
<input type="file" multiple />
// 7、video タグにサムネイルを追加
<video poster="picture.png"></video>
// 8、リソースファイルのダウンロードを宣言
<a href="image.png" download></a>
vite と whistle を組み合わせてローカル環境の server-hmr 設定を実行#
server: {
hmr: {
protocol: 'ws',
host: 'localhost',
},
},